commit 5ba5803ba2e165e0fe6b0504df44e20cc80dfa52 Author: Kevinlinpr Date: Sat Jun 22 04:25:20 2024 +0800 App Build diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..979d027 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..0897082 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..44ca2d9 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,41 @@ + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..fdf8d99 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0ad17cb --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..269839b --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,73 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) +} + +android { + namespace = "com.aiosman.riderpro" + compileSdk = 34 + + defaultConfig { + applicationId = "com.aiosman.riderpro" + minSdk = 24 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3.android) + implementation(libs.androidx.navigation.compose) + implementation (libs.androidx.paging.compose) + implementation(libs.androidx.paging.runtime) + implementation("com.google.maps.android:maps-compose:4.3.3") + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/aiosman/riderpro/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/aiosman/riderpro/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..79a2c03 --- /dev/null +++ b/app/src/androidTest/java/com/aiosman/riderpro/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.aiosman.riderpro + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.aiosman.riderpro", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..678b3de --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ChatNotificationData.kt b/app/src/main/java/com/aiosman/riderpro/ChatNotificationData.kt new file mode 100644 index 0000000..de03b08 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/ChatNotificationData.kt @@ -0,0 +1,11 @@ +package com.aiosman.riderpro + +import androidx.annotation.DrawableRes + +data class ChatNotificationData( + @DrawableRes val avatar: Int, + val name: String, + val message: String, + val time: String, + val unread: Int +) diff --git a/app/src/main/java/com/aiosman/riderpro/ChatNotificationUtils.kt b/app/src/main/java/com/aiosman/riderpro/ChatNotificationUtils.kt new file mode 100644 index 0000000..15d0ccf --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/ChatNotificationUtils.kt @@ -0,0 +1,50 @@ +package com.aiosman.riderpro + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import kotlin.math.ceil +import kotlinx.coroutines.delay + +internal class TestChatBackend( + private val backendDataList: List, + private val loadDelay: Long = 500, +) { + val DataBatchSize = 1 + class DesiredLoadResultPageResponse(val data: List) + /** Returns [DataBatchSize] items for a key */ + fun searchItemsByKey(key: Int): DesiredLoadResultPageResponse { + val maxKey = ceil(backendDataList.size.toFloat() / DataBatchSize).toInt() + if (key >= maxKey) { + return DesiredLoadResultPageResponse(emptyList()) + } + val from = key * DataBatchSize + val to = minOf((key + 1) * DataBatchSize, backendDataList.size) + val currentSublist = backendDataList.subList(from, to) + return DesiredLoadResultPageResponse(currentSublist) + } + fun getAllData() = TestChatPagingSource(this, loadDelay) +} +internal class TestChatPagingSource( + private val backend: TestChatBackend, + private val loadDelay: Long, +) : PagingSource() { + override suspend fun load(params: LoadParams): LoadResult { + // Simulate latency + delay(loadDelay) + val pageNumber = params.key ?: 0 + val response = backend.searchItemsByKey(pageNumber) + // Since 0 is the lowest page number, return null to signify no more pages should + // be loaded before it. + val prevKey = if (pageNumber > 0) pageNumber - 1 else null + // This API defines that it's out of data when a page returns empty. When out of + // data, we return `null` to signify no more pages should be loaded + val nextKey = if (response.data.isNotEmpty()) pageNumber + 1 else null + return LoadResult.Page(data = response.data, prevKey = prevKey, nextKey = nextKey) + } + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition?.let { + state.closestPageToPosition(it)?.prevKey?.plus(1) + ?: state.closestPageToPosition(it)?.nextKey?.minus(1) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/MainActivity.kt b/app/src/main/java/com/aiosman/riderpro/MainActivity.kt new file mode 100644 index 0000000..8a64e8b --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/MainActivity.kt @@ -0,0 +1,227 @@ +package com.aiosman.riderpro + +import android.app.StatusBarManager +import android.os.Bundle +import android.widget.HorizontalScrollView +import android.widget.ScrollView +import androidx.activity.ComponentActivity +import androidx.activity.SystemBarStyle +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.layout.windowInsetsStartWidth +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.text.BasicText +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemColors +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorProducer +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.view.WindowCompat +import androidx.navigation.NavController +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController +import com.aiosman.riderpro.ui.theme.RiderProTheme +import com.google.android.gms.maps.model.CameraPosition +import com.google.android.gms.maps.model.LatLng +import com.google.maps.android.compose.GoogleMap +import com.google.maps.android.compose.Marker +import com.google.maps.android.compose.MarkerComposable +import com.google.maps.android.compose.MarkerState +import com.google.maps.android.compose.rememberCameraPositionState + + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + Navigation() + } + } +} + +@Composable +fun NavigationController(navController: NavHostController){ + NavHost( + navController = navController, startDestination = NavigationItem.Home.route){ + composable(route = NavigationItem.Home.route){ + Home() + } + composable(route = NavigationItem.Street.route){ + Street() + } + composable(route = NavigationItem.Add.route){ + Add() + } + composable(route = NavigationItem.Message.route){ + Message() + } + composable(route = NavigationItem.Profile.route){ + Profile() + } + } +} + +@Composable +fun Navigation(){ + val navigationBarHeight = with(LocalDensity.current) { + WindowInsets.navigationBars.getBottom(this).toDp() + } + val navController = rememberNavController() + val item = listOf( + NavigationItem.Home, + NavigationItem.Street, + NavigationItem.Add, + NavigationItem.Message, + NavigationItem.Profile + ) + Scaffold ( + modifier = Modifier.statusBarsPadding(), + topBar = {}, + bottomBar = { + NavigationBar ( + modifier = Modifier.height(56.dp + navigationBarHeight), + containerColor = Color.Black + ){ + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = navBackStackEntry?.destination?.route + item.forEach{ it -> + NavigationBarItem( + selected = currentRoute == it.route , + onClick = { + if(currentRoute != it.route){ + navController.navigate(it.route) + } + }, + colors = NavigationBarItemColors( + selectedIconColor = Color.Red, + selectedTextColor = Color.Red, + selectedIndicatorColor = Color.Black, + unselectedIconColor = Color.Red, + unselectedTextColor = Color.Red, + disabledIconColor = Color.Red, + disabledTextColor = Color.Red, + + ), + icon = { + Icon(modifier = Modifier.size(24.dp), + imageVector = it.icon(), contentDescription = null, + tint = if(currentRoute == it.route) Color.Red else Color.White + ) + } + ) + } + } + } + ){ + NavigationController(navController = navController) + } +} + +@Composable +fun Home(){ + Column ( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ){ + PagingBackendSample() + } +} + + +@Composable +fun Street(){ + Column ( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + StreetPage() + } +} + +@Composable +fun Add(){ + Column ( + modifier = Modifier.fillMaxSize().background(Color.Black), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ){ + + } +} + +@Composable +fun Message(){ + Column ( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.CenterHorizontally, + ){ + MessagePage() + } +} + +@Composable +fun Profile(){ + Column ( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ){ + ProfilePage() + } +} + + + + +@Preview(showBackground = true) +@Composable +fun GreetingPreview() { + RiderProTheme { + Surface (modifier = Modifier.fillMaxSize(), color = Color.White){ + Navigation() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/Message.kt b/app/src/main/java/com/aiosman/riderpro/Message.kt new file mode 100644 index 0000000..21abe2d --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/Message.kt @@ -0,0 +1,231 @@ +package com.aiosman.riderpro + +import android.view.RoundedCorner +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Person +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.paging.LoadState +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.compose.collectAsLazyPagingItems + +val chatNotificationData = ChatNotificationData( + R.drawable.default_avatar, + "Tokunaga Yae", + "Memphis", + "3 minutes ago", + 6 +) + +private val ChatData = (0..10).toList().map { chatNotificationData} + +@Composable +fun MessagePage(){ + val myBackend = remember { TestChatBackend(ChatData) } + val pager = remember { + Pager( + PagingConfig( + pageSize = myBackend.DataBatchSize, + enablePlaceholders = true, + maxSize = 200 + ) + ) { + myBackend.getAllData() + } + } + val lazyPagingItems = pager.flow.collectAsLazyPagingItems() + MessageTopSwitchBtnGroup() + MessageBarrierLine() + MessageNotification() + LazyColumn ( + modifier = Modifier.padding(bottom = 20.dp) + ){ + if (lazyPagingItems.loadState.refresh == LoadState.Loading) { + item { + MomentListLoading() + } + } + items(count = lazyPagingItems.itemCount) { index -> + val item = lazyPagingItems[index] + if (item != null) { + ChatItem(item) + } + } + if (lazyPagingItems.loadState.append == LoadState.Loading) { + item { + MomentListLoading() + } + } + } + +} + +@Composable +fun MessageTopSwitchBtnGroup(){ + Column ( + modifier = Modifier + .fillMaxWidth() + .height(113.dp) + ) { + Row(modifier = Modifier.fillMaxSize()){ + val notificationBtnModifier = Modifier + .fillMaxHeight() + .weight(1f) + NotificationBtn(notificationBtnModifier,drawableId = R.drawable.rider_pro_like, + displayText = "LIKE") + NotificationBtn(notificationBtnModifier,drawableId = R.drawable.rider_pro_followers, + displayText = "FOLLOWERS") + NotificationBtn(notificationBtnModifier,drawableId = R.drawable.rider_pro_comments, + displayText = "COMMENTS") + } + } +} + +@Composable +fun MessageBarrierLine(){ + Box(modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .padding(start = 24.dp, end = 24.dp) + .border(width = 1.dp, Color(0f, 0f, 0f, 0.1f)) + ) +} + +@Composable +fun NotificationBtn(modifier: Modifier, drawableId: Int, displayText: String){ + Box(modifier = modifier, + contentAlignment = Alignment.Center){ + Column(modifier = Modifier + .size(width = 79.dp, height = 88.dp), + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.CenterHorizontally){ + Box(modifier = Modifier + .padding(top = 8.dp) + .size(width = 55.dp, height = 55.dp) + .shadow( + spotColor = Color.White, + ambientColor = Color(0f, 0f, 0f, 0.4f), + elevation = 12.dp, + ), + contentAlignment = Alignment.Center, + ){ + Image( + modifier = Modifier + .size(width = 24.dp, height = 24.dp), + painter = painterResource(id = drawableId), + contentDescription = "" + ) + } + Text( + modifier = Modifier.padding(top = 8.dp), + text = displayText, + fontSize = 12.sp, style = TextStyle(fontWeight = FontWeight.Bold) + ) + } + } +} + +@Composable +fun MessageNotification(){ + Row(modifier = Modifier + .fillMaxWidth() + .height(88.dp) + .padding(start = 22.dp, top = 20.dp, bottom = 20.dp, end = 24.dp), + verticalAlignment = Alignment.CenterVertically){ + Box(modifier = Modifier + .size(width = 48.dp, height = 48.dp) + .border(width = 1.dp, Color(0f, 0f, 0f, 0.1f), RoundedCornerShape(2.dp)), + contentAlignment = Alignment.Center){ + Icon( + modifier = Modifier + .size(width = 24.dp, height = 24.dp), + painter = painterResource(R.drawable.rider_pro_notification), + contentDescription = "" + ) + } + Text(text = "NOTIFICATIONS", fontSize = 18.sp, modifier = Modifier.padding(start = 12.dp), style = TextStyle(fontWeight = FontWeight.Bold)) + Box(modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.CenterEnd){ + Box(modifier = Modifier + .height(18.dp) + .clip(RoundedCornerShape(10.dp)) + .background(Color.Red), + contentAlignment = Alignment.Center){ + Text(text = "18", fontSize = 10.sp, color = Color.White, modifier = Modifier.padding(start = 6.dp, end = 6.dp, top = 2.dp, bottom = 2.dp)) + } + } + } +} + +@Composable +fun ChatItem(chatNotificationData: ChatNotificationData){ + Row(modifier = Modifier + .fillMaxWidth() + .height(88.dp) + .padding(start = 22.dp, top = 20.dp, bottom = 20.dp, end = 24.dp), + verticalAlignment = Alignment.CenterVertically){ + Image(modifier = Modifier + .size(width = 48.dp, height = 48.dp) + .clip(RoundedCornerShape(2.dp)), + painter = painterResource(chatNotificationData.avatar), + contentDescription = "") + Column ( + modifier = Modifier.fillMaxHeight().padding(start = 12.dp), + verticalArrangement = Arrangement.SpaceAround + ){ + Text(text = chatNotificationData.name, fontSize = 18.sp, style = TextStyle(fontWeight = FontWeight.Bold)) + Text(text = chatNotificationData.message, fontSize = 14.sp, + color = Color(0f, 0f, 0f, 0.6f)) + } + + Box(modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.CenterEnd){ + Column ( + modifier = Modifier.fillMaxHeight(), + verticalArrangement = Arrangement.SpaceAround, + horizontalAlignment = Alignment.End + ){ + Text(text = chatNotificationData.time, fontSize = 12.sp,color = Color(0f, 0f, 0f, 0.4f)) + Box(modifier = Modifier + .height(18.dp) + .clip(RoundedCornerShape(10.dp)) + .background(Color.Red), + contentAlignment = Alignment.Center){ + Text(text = chatNotificationData.unread.toString(), fontSize = 10.sp, color = Color.White, modifier = Modifier.padding(start = 6.dp, end = 6.dp, top = 2.dp, bottom = 2.dp)) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/MomentItem.kt b/app/src/main/java/com/aiosman/riderpro/MomentItem.kt new file mode 100644 index 0000000..75bdc50 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/MomentItem.kt @@ -0,0 +1,74 @@ +package com.aiosman.riderpro + +import androidx.annotation.DrawableRes + +data class MomentItem( + val id: Int, + @DrawableRes val avatar: Int, + val nickname: String, + val location: String, + val time: String, + val followStatus: Boolean, + val momentTextContent: String, + @DrawableRes val momentPicture: Int, + val likeCount: Int, + val commentCount: Int, + val shareCount: Int, + val favoriteCount: Int +) + +val momentTestItem = MomentItem( + id = 1, + avatar = R.drawable.default_avatar, + nickname = "Onyama Limba", + location = "Japan", + time = "2023.02.02 11:23", + followStatus = false, + momentTextContent = "By strongarming Ducati into giving him the factory seat.Marquez effectively …", + momentPicture = R.drawable.default_moment_img, + likeCount = 21, + commentCount = 43, + shareCount = 33, + favoriteCount = 211) + +val profileMomentItems = listOf( + MomentItem( + id = 1, + avatar = R.drawable.default_avatar, + nickname = "Onyama Limba", + location = "Japan", + time = "2024.06.08 12:23", + followStatus = false, + momentTextContent = "Modifications that are made to make your motorbike more like you", + momentPicture = R.drawable.rider_pro_moment_demo_1, + likeCount = 2345, + commentCount = 12, + shareCount = 33, + favoriteCount = 211), + MomentItem( + id = 1, + avatar = R.drawable.default_avatar, + nickname = "Onyama Limba", + location = "Japan", + time = "2024.03.03 12:31", + followStatus = false, + momentTextContent = "At least 500 units will be made, to meet homologation requirements.", + momentPicture = R.drawable.rider_pro_moment_demo_2, + likeCount = 211, + commentCount = 33, + shareCount = 33, + favoriteCount = 211), + MomentItem( + id = 1, + avatar = R.drawable.default_avatar, + nickname = "Onyama Limba", + location = "Japan", + time = "2024.02.02 11:23", + followStatus = false, + momentTextContent = "The bike is already FIM legal (and soon-to-be MotoAmerica legal as well).", + momentPicture = R.drawable.rider_pro_moment_demo_3, + likeCount = 987, + commentCount = 21, + shareCount = 33, + favoriteCount = 211) +) diff --git a/app/src/main/java/com/aiosman/riderpro/NavigationItem.kt b/app/src/main/java/com/aiosman/riderpro/NavigationItem.kt new file mode 100644 index 0000000..a858ca6 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/NavigationItem.kt @@ -0,0 +1,23 @@ +package com.aiosman.riderpro + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountCircle +import androidx.compose.material.icons.filled.Email +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Place +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.vectorResource + +sealed class NavigationItem(val route:String, val icon: @Composable () -> ImageVector){ + data object Home : NavigationItem("Home", + { ImageVector.vectorResource(R.drawable.rider_pro_home) }) + data object Street : NavigationItem("Street", + { ImageVector.vectorResource(R.drawable.rider_pro_street) }) + data object Add : NavigationItem("Add", + { ImageVector.vectorResource(R.drawable.rider_pro_moment_add) }) + data object Message : NavigationItem("Message", + { ImageVector.vectorResource(R.drawable.rider_pro_message) }) + data object Profile : NavigationItem("Profile", + { ImageVector.vectorResource(R.drawable.rider_pro_profile) }) +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/PagingSimple.kt b/app/src/main/java/com/aiosman/riderpro/PagingSimple.kt new file mode 100644 index 0000000..5af4125 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/PagingSimple.kt @@ -0,0 +1,236 @@ +package com.aiosman.riderpro +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.PlatformTextStyle +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.LineHeightStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em +import androidx.compose.ui.unit.sp +import androidx.paging.LoadState +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.compose.collectAsLazyPagingItems + +private val DATA = (0..60).toList().map { momentTestItem} + +@Composable +fun PagingBackendSample() { + val myBackend = remember { TestBackend(DATA) } + val pager = remember { + Pager( + PagingConfig( + pageSize = myBackend.DataBatchSize, + enablePlaceholders = true, + maxSize = 200 + ) + ) { + myBackend.getAllData() + } + } + val lazyPagingItems = pager.flow.collectAsLazyPagingItems() + + LazyColumn { + if (lazyPagingItems.loadState.refresh == LoadState.Loading) { + item { + MomentListLoading() + } + } + items(count = lazyPagingItems.itemCount) { index -> + val item = lazyPagingItems[index] + if (item != null) { + MomentCard(item) + } + } + if (lazyPagingItems.loadState.append == LoadState.Loading) { + item { + MomentListLoading() + } + } + } +} + +@Composable +fun MomentCard(momentItem: MomentItem){ + Column( + modifier = Modifier.fillMaxWidth() + ){ + MomentTopRowGroup(momentItem = momentItem) + MomentContentGroup(momentItem = momentItem) + val momentOperateBtnBoxModifier = Modifier.fillMaxHeight().weight(1f) + MomentBottomOperateRowGroup(momentOperateBtnBoxModifier) + } +} + +@Composable +fun MomentName(name: String){ + Text( + modifier = Modifier, + textAlign = TextAlign.Start, + text = name, + color = Color(0f,0f,0f), + fontSize = 16.sp, style = TextStyle(fontWeight = FontWeight.Bold)) +} + +@Composable +fun MomentFollowBtn(){ + Box(modifier = Modifier + .size(width = 53.dp, height = 18.dp) + .padding(start = 8.dp), + contentAlignment = Alignment.Center){ + Image( + modifier = Modifier + .fillMaxSize(), + painter = painterResource(id = R.drawable.follow_bg), + contentDescription = "" + ) + Text(text = "Follow", + color = Color.White, + fontSize = 12.sp) + } +} + +@Composable +fun MomentPostLocation(location: String){ + Text(text = location, + color = Color(0f,0f,0f,0.6f), + fontSize = 12.sp) +} + +@Composable +fun MomentPostTime(time: String){ + Text(modifier = Modifier.padding(start = 8.dp), + text = time, color = Color(0f,0f,0f,0.6f), + fontSize = 12.sp + ) +} + +@Composable +fun MomentTopRowGroup(momentItem: MomentItem){ + Row (modifier = Modifier + .height(40.dp) + .padding(top = 0.dp, bottom = 0.dp, start = 24.dp, end = 24.dp) + ){ + Image( + painter = painterResource(id = momentItem.avatar), + contentDescription = "" + ) + Column( + modifier = Modifier + .defaultMinSize() + .padding(start = 12.dp, end = 12.dp) + ) { + Row (modifier = Modifier + .fillMaxWidth() + .height(22.dp), + verticalAlignment = Alignment.CenterVertically + ){ + MomentName(momentItem.nickname) + MomentFollowBtn() + } + Row (modifier = Modifier + .fillMaxWidth() + .height(21.dp), + verticalAlignment = Alignment.CenterVertically + ){ + MomentPostLocation(momentItem.location) + MomentPostTime(momentItem.time) + } + } + } +} + +@Composable +fun MomentContentGroup(momentItem: MomentItem){ + Text(text = momentItem.momentTextContent, + modifier = Modifier + .fillMaxWidth() + .padding(top = 22.dp, bottom = 16.dp, start = 24.dp, end = 24.dp), + fontSize = 16.sp + ) + Image( + modifier = Modifier + .fillMaxWidth(), + painter = painterResource(id = momentItem.momentPicture), + contentDescription = "" + ) +} + +@Composable +fun MomentOperateBtn(@DrawableRes icon: Int, count: String){ + Row (verticalAlignment = Alignment.CenterVertically){ + Image( + modifier = Modifier + .size(width = 24.dp, height = 24.dp), + painter = painterResource(id = icon), + contentDescription = "") + Text(text = count, + modifier = Modifier.padding(start = 7.dp), + fontSize = 12.sp,) + } +} +@Composable +fun MomentBottomOperateRowGroup(modifier: Modifier){ + Row (modifier = Modifier + .fillMaxWidth() + .height(56.dp)){ + Box(modifier = modifier, + contentAlignment = Alignment.Center + ){ + MomentOperateBtn(icon = R.drawable.rider_pro_like, count = "21") + } + Box(modifier = modifier, + contentAlignment = Alignment.Center + ){ + MomentOperateBtn(icon = R.drawable.rider_pro_moment_comment, count = "43") + } + Box(modifier = modifier, + contentAlignment = Alignment.Center + ){ + MomentOperateBtn(icon = R.drawable.rider_pro_share, count = "33") + } + Box(modifier = modifier, + contentAlignment = Alignment.Center + ){ + MomentOperateBtn(icon = R.drawable.rider_pro_favoriate, count = "211") + } + } +} + +@Composable +fun MomentListLoading(){ + CircularProgressIndicator( + modifier = + Modifier + .fillMaxWidth() + .wrapContentWidth(Alignment.CenterHorizontally), + color = Color.Red + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/Profile.kt b/app/src/main/java/com/aiosman/riderpro/Profile.kt new file mode 100644 index 0000000..ead245f --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/Profile.kt @@ -0,0 +1,305 @@ +package com.aiosman.riderpro + +import android.widget.ScrollView +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + + +@Composable +fun ProfilePage(){ + Column ( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(bottom = 150.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top, + ){ + CarGroup() + UserInformation() + RidingStyle() + UserMoment() + } +} + +@Composable +fun CarGroup(){ + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 54.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + CarTopInformation() + CarTopPicture() + } +} + +@Composable +fun CarTopInformation(){ + Row{ + Text(text = "BMW", color = Color.Black, fontSize = 12.sp, style = TextStyle(fontWeight = FontWeight.Bold)) + Text(modifier = Modifier.padding(start = 4.dp), text = "/", color = Color.Gray, fontSize = 12.sp) + Text(modifier = Modifier.padding(start = 4.dp), text = "M1000RR", color = Color.Gray, fontSize = 12.sp) + } +} + +@Composable +fun CarTopPicture(){ + Image( + modifier = Modifier + .size(width = 336.dp, height = 224.dp) + .padding(top = 42.dp), + painter = painterResource(id = R.drawable.default_profile_moto), contentDescription = "") +} + +@Composable +fun UserInformation(){ + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp, start = 33.dp, end = 33.dp), + horizontalAlignment = Alignment.CenterHorizontally){ + Row (modifier = Modifier.fillMaxWidth()){ + val userInfoModifier = Modifier.weight(1f) + UserInformationFollowers(userInfoModifier) + UserInformationBasic(userInfoModifier) + UserInformationFollowing(userInfoModifier) + } + UserInformationSlogan() + CommunicationOperatorGroup() + } +} + +@Composable +fun UserInformationFollowers(modifier: Modifier){ + Column(modifier = modifier.padding(top = 31.dp)) { + Text(modifier = Modifier.padding(bottom = 5.dp),text = "183", fontSize = 24.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + Spacer( + modifier = Modifier + .size(width = 88.83.dp, height = 1.dp) + .border(width = 1.dp, color = Color.Gray) + .padding(top = 5.dp, bottom = 5.dp) + ) + Text(modifier = Modifier.padding(top = 5.dp),text = "FOLLOWERS", fontSize = 12.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + } +} + +@Composable +fun UserInformationBasic(modifier: Modifier){ + Column( + horizontalAlignment = Alignment.CenterHorizontally) { + Box(modifier = Modifier.size(width = 112.dp, height = 112.dp), + contentAlignment = Alignment.Center + ){ + Image( + modifier = Modifier.fillMaxSize(), + painter = painterResource(id = R.drawable.avatar_bold), contentDescription = "") + Image( + modifier = Modifier + .size(width = 88.dp, height = 88.dp) + .clip( + RoundedCornerShape(88.dp) + ), + painter = painterResource(id = R.drawable.default_avatar), contentDescription = "") + + } + Text(modifier = Modifier.padding(top = 8.dp), text = "Atom", fontSize = 32.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + Text(modifier = Modifier.padding(top = 4.dp), text = "America", fontSize = 12.sp, color = Color.Gray) + Text(modifier = Modifier.padding(top = 4.dp), text = "Member since Jun 4.2019", fontSize = 12.sp, color = Color.Gray) + } +} + +@Composable +fun UserInformationFollowing(modifier: Modifier){ + Column(modifier = modifier.padding(top = 6.dp), + horizontalAlignment = Alignment.End) { + Text(modifier = Modifier.padding(bottom = 5.dp), text = "306", fontSize = 24.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + Box( + modifier = Modifier + .size(width = 88.83.dp, height = 1.dp) + .border(width = 1.dp, color = Color.Gray) + + ) + Text(modifier = Modifier.padding(top = 5.dp),text = "FOLLOWING", fontSize = 12.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + } +} + +@Composable +fun UserInformationSlogan(){ + Text(modifier = Modifier.padding(top = 23.dp),text = "Ridering shooting fishing not much more", fontSize = 13.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) +} + +@Composable +fun CommunicationOperatorGroup(){ + Row (modifier = Modifier + .fillMaxWidth() + .padding(top = 16.dp), horizontalArrangement = Arrangement.Center){ + Box(modifier = Modifier.size(width = 142.dp, height = 40.dp), + contentAlignment = Alignment.Center){ + Image(modifier = Modifier.fillMaxSize(), painter = painterResource(id = R.drawable.rider_pro_profile_follow), contentDescription = "") + Text(text = "FOLLOW", fontSize = 16.sp, color = Color.White, style = TextStyle(fontWeight = FontWeight.Bold)) + } + Box(modifier = Modifier + .size(width = 142.dp, height = 40.dp) + .padding(start = 6.dp), + contentAlignment = Alignment.Center){ + Image(modifier = Modifier.fillMaxSize(),painter = painterResource(id = R.drawable.rider_pro_profile_message), contentDescription = "") + Text(text = "MESSAGE", fontSize = 16.sp, color = Color.White, style = TextStyle(fontWeight = FontWeight.Bold)) + } + } +} + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun RidingStyle(){ + Column(modifier = Modifier + .fillMaxWidth() + .padding(start = 24.dp, top = 40.dp, end = 24.dp), + horizontalAlignment = Alignment.Start) { + Text(text = "RIDING STYLES", fontSize = 18.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + Image(modifier = Modifier + .padding(top = 4.dp) + .height(8.dp),painter = painterResource(id = R.drawable.rider_pro_profile_line), contentDescription = "") + FlowRow (modifier = Modifier + .fillMaxWidth() + .padding(top = 24.dp)){ + RidingStyleItem(styleContent = "Cruiser") + RidingStyleItem(styleContent = "Bobber") + RidingStyleItem(styleContent = "Cafe") + RidingStyleItem(styleContent = "Chopper") + RidingStyleItem(styleContent = "Sport") + RidingStyleItem(styleContent = "Vintage") + RidingStyleItem(styleContent = "Trike") + RidingStyleItem(styleContent = "Touring") + } + } +} + +@Composable +fun RidingStyleItem(styleContent: String){ + Box(modifier = Modifier.padding(bottom = 8.dp, end = 8.dp), + contentAlignment = Alignment.Center) { + Image(modifier = Modifier.shadow( + ambientColor = Color.Gray, + spotColor = Color(0f,0f,0f,0.2f), + elevation = 20.dp, + ), painter = painterResource(id = R.drawable.rider_pro_style_wrapper), contentDescription = "") + Text(modifier = Modifier.padding(start = 5.dp, end = 5.dp), text = styleContent, fontSize = 12.sp, color = Color.Gray, style = TextStyle(fontWeight = FontWeight.Bold)) + } +} + +@Composable +fun UserMoment(){ + profileMomentItems.forEach( + action = { MomentPostUnit(it) } + ) +} + +@Composable +fun MomentPostUnit(momentItem: MomentItem){ + TimeGroup(momentItem.time) + MomentCard(momentItem.momentTextContent, + momentItem.momentPicture, + momentItem.likeCount.toString(), + momentItem.commentCount.toString()) +} + +@Composable +fun TimeGroup(time: String = "2024.06.08 12:23"){ + Row(modifier = Modifier + .fillMaxWidth() + .padding(start = 24.dp, top = 40.dp, end = 24.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically){ + Image( + modifier = Modifier.padding(end = 12.dp), + painter = painterResource(id = R.drawable.rider_pro_moment_time_flag), contentDescription = "") + Text(text = time,fontSize = 22.sp, color = Color.Black, style = TextStyle(fontWeight = FontWeight.Bold)) + } +} + +@Composable +fun MomentCard(content: String,@DrawableRes picture: Int, like: String, comment: String){ + Column(modifier = Modifier + .fillMaxWidth() + .padding(start = 48.dp, top = 18.dp, end = 24.dp) + .border(width = 1.dp, color = Color(0f,0f,0f,0.1f), shape = RoundedCornerShape(6.dp)) + ){ + MomentCardTopContent(content) + MomentCardPicture(picture) + MomentCardOperation(like,comment) + } +} + +@Composable +fun MomentCardTopContent(content: String){ + Row(modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically){ + Text( + modifier = Modifier.padding(16.dp), + text = content,fontSize = 16.sp, color = Color.Black) + } +} + +@Composable +fun MomentCardPicture(@DrawableRes drawable: Int){ + Image(modifier = Modifier + .fillMaxSize() + .padding(16.dp), painter = painterResource(id = drawable), contentDescription = "") + +} + +@Composable +fun MomentCardOperation(like: String, comment: String){ + Row(modifier = Modifier + .fillMaxWidth() + .height(56.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically){ + Spacer(modifier = Modifier.weight(1f)) + MomentCardOperationItem(drawable = R.drawable.rider_pro_like, number = like, modifier = Modifier.weight(1f)) + MomentCardOperationItem(drawable = R.drawable.rider_pro_moment_comment, number = comment, modifier = Modifier.weight(1f)) + } +} + +@Composable +fun MomentCardOperationItem(@DrawableRes drawable: Int, number: String, modifier: Modifier){ + Row(modifier = modifier, + verticalAlignment = Alignment.CenterVertically){ + Image(modifier = Modifier.padding(start = 16.dp, end = 8.dp), + painter = painterResource(id = drawable), contentDescription = "") + Text(text = number) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/SimpleUtils.kt b/app/src/main/java/com/aiosman/riderpro/SimpleUtils.kt new file mode 100644 index 0000000..cf3aa83 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/SimpleUtils.kt @@ -0,0 +1,50 @@ +package com.aiosman.riderpro + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import kotlin.math.ceil +import kotlinx.coroutines.delay + +internal class TestBackend( + private val backendDataList: List, + private val loadDelay: Long = 500, +) { + val DataBatchSize = 5 + class DesiredLoadResultPageResponse(val data: List) + /** Returns [DataBatchSize] items for a key */ + fun searchItemsByKey(key: Int): DesiredLoadResultPageResponse { + val maxKey = ceil(backendDataList.size.toFloat() / DataBatchSize).toInt() + if (key >= maxKey) { + return DesiredLoadResultPageResponse(emptyList()) + } + val from = key * DataBatchSize + val to = minOf((key + 1) * DataBatchSize, backendDataList.size) + val currentSublist = backendDataList.subList(from, to) + return DesiredLoadResultPageResponse(currentSublist) + } + fun getAllData() = TestPagingSource(this, loadDelay) +} +internal class TestPagingSource( + private val backend: TestBackend, + private val loadDelay: Long, +) : PagingSource() { + override suspend fun load(params: LoadParams): LoadResult { + // Simulate latency + delay(loadDelay) + val pageNumber = params.key ?: 0 + val response = backend.searchItemsByKey(pageNumber) + // Since 0 is the lowest page number, return null to signify no more pages should + // be loaded before it. + val prevKey = if (pageNumber > 0) pageNumber - 1 else null + // This API defines that it's out of data when a page returns empty. When out of + // data, we return `null` to signify no more pages should be loaded + val nextKey = if (response.data.isNotEmpty()) pageNumber + 1 else null + return LoadResult.Page(data = response.data, prevKey = prevKey, nextKey = nextKey) + } + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition?.let { + state.closestPageToPosition(it)?.prevKey?.plus(1) + ?: state.closestPageToPosition(it)?.nextKey?.minus(1) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/Street.kt b/app/src/main/java/com/aiosman/riderpro/Street.kt new file mode 100644 index 0000000..d7d3014 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/Street.kt @@ -0,0 +1,38 @@ +package com.aiosman.riderpro + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import com.google.android.gms.maps.model.CameraPosition +import com.google.android.gms.maps.model.LatLng +import com.google.maps.android.compose.GoogleMap +import com.google.maps.android.compose.MarkerComposable +import com.google.maps.android.compose.MarkerState +import com.google.maps.android.compose.rememberCameraPositionState + +@Composable +fun StreetPage(){ + val cameraPositionState = rememberCameraPositionState { + position = CameraPosition.fromLatLngZoom( + LatLng(countries[1].lat, countries[1].lng), + 4f) + } + GoogleMap( + modifier = Modifier.fillMaxSize(), + cameraPositionState = cameraPositionState + ) { + countries.forEach { position -> + MarkerComposable( + state = MarkerState(position = LatLng(position.lat, position.lng)), + ) { + Image( + painter = painterResource(id = R.drawable.rider_pro_map_mark), + contentDescription = "", + ) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/TestStreetMap.kt b/app/src/main/java/com/aiosman/riderpro/TestStreetMap.kt new file mode 100644 index 0000000..f43357f --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/TestStreetMap.kt @@ -0,0 +1,28 @@ +package com.aiosman.riderpro + +data class StreetPosition( + val name:String, + val lat:Double, + val lng:Double +) +val countries = listOf( + StreetPosition("哈龙湾, 越南",16.5000, 107.1000), + StreetPosition("芽庄, 越南",12.2500, 109.0833), + StreetPosition("岘港, 越南",16.0667, 108.2167), + StreetPosition("美奈, 越南",11.9333, 108.9833), + StreetPosition("富国岛, 越南",10.0000, 104.0000), + StreetPosition("金三角, 泰国, 缅甸, 老挝",20.2500, 99.7500), + StreetPosition("普吉岛, 泰国",7.9444, 98.3000), + StreetPosition("苏梅岛, 泰国",9.5333, 99.9333), + StreetPosition("曼谷, 泰国",13.7500, 100.5000), + StreetPosition("马六甲, 马来西亚",2.2000, 102.2500), + StreetPosition("兰卡威群岛, 马来西亚",6.3000, 99.9000), + StreetPosition("沙巴, 马来西亚",6.0833, 116.0833), + StreetPosition("巴厘岛, 印度尼西亚",8.3333, 115.1000), + StreetPosition("龙目岛, 印度尼西亚",8.3333, 116.4000), + StreetPosition("婆罗洲, 印度尼西亚",3.0000, 114.0000), + StreetPosition("宿务, 菲律宾",10.3167, 123.8833), + StreetPosition("长滩岛, 菲律宾",11.5833, 121.9167), + StreetPosition("保和岛, 菲律宾",10.3000, 123.3333), + StreetPosition("科隆岛, 菲律宾",5.1167, 119.3333) +) diff --git a/app/src/main/java/com/aiosman/riderpro/ui/theme/Color.kt b/app/src/main/java/com/aiosman/riderpro/ui/theme/Color.kt new file mode 100644 index 0000000..30a93c9 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.aiosman.riderpro.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ui/theme/Theme.kt b/app/src/main/java/com/aiosman/riderpro/ui/theme/Theme.kt new file mode 100644 index 0000000..15e3246 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.aiosman.riderpro.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun RiderProTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/aiosman/riderpro/ui/theme/Type.kt b/app/src/main/java/com/aiosman/riderpro/ui/theme/Type.kt new file mode 100644 index 0000000..95a8a96 --- /dev/null +++ b/app/src/main/java/com/aiosman/riderpro/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.aiosman.riderpro.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/drawable/avatar_bold.png b/app/src/main/res/drawable/avatar_bold.png new file mode 100644 index 0000000..ad61107 Binary files /dev/null and b/app/src/main/res/drawable/avatar_bold.png differ diff --git a/app/src/main/res/drawable/default_avatar.jpeg b/app/src/main/res/drawable/default_avatar.jpeg new file mode 100644 index 0000000..86f1993 Binary files /dev/null and b/app/src/main/res/drawable/default_avatar.jpeg differ diff --git a/app/src/main/res/drawable/default_moment_img.png b/app/src/main/res/drawable/default_moment_img.png new file mode 100644 index 0000000..e234801 Binary files /dev/null and b/app/src/main/res/drawable/default_moment_img.png differ diff --git a/app/src/main/res/drawable/default_profile_moto.png b/app/src/main/res/drawable/default_profile_moto.png new file mode 100644 index 0000000..6c27d41 Binary files /dev/null and b/app/src/main/res/drawable/default_profile_moto.png differ diff --git a/app/src/main/res/drawable/follow_bg.png b/app/src/main/res/drawable/follow_bg.png new file mode 100644 index 0000000..e47f12c Binary files /dev/null and b/app/src/main/res/drawable/follow_bg.png differ diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rider_pro_comments.xml b/app/src/main/res/drawable/rider_pro_comments.xml new file mode 100644 index 0000000..f43cf5c --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_comments.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/drawable/rider_pro_favoriate.xml b/app/src/main/res/drawable/rider_pro_favoriate.xml new file mode 100644 index 0000000..3bdd1f4 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_favoriate.xml @@ -0,0 +1,22 @@ + + + + diff --git a/app/src/main/res/drawable/rider_pro_followers.xml b/app/src/main/res/drawable/rider_pro_followers.xml new file mode 100644 index 0000000..4f99b14 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_followers.xml @@ -0,0 +1,38 @@ + + + + + + diff --git a/app/src/main/res/drawable/rider_pro_home.xml b/app/src/main/res/drawable/rider_pro_home.xml new file mode 100644 index 0000000..35ee254 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_home.xml @@ -0,0 +1,22 @@ + + + + diff --git a/app/src/main/res/drawable/rider_pro_like.xml b/app/src/main/res/drawable/rider_pro_like.xml new file mode 100644 index 0000000..1d37203 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_like.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/drawable/rider_pro_map_mark.png b/app/src/main/res/drawable/rider_pro_map_mark.png new file mode 100644 index 0000000..cf12fde Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_map_mark.png differ diff --git a/app/src/main/res/drawable/rider_pro_message.xml b/app/src/main/res/drawable/rider_pro_message.xml new file mode 100644 index 0000000..9c54dc9 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_message.xml @@ -0,0 +1,14 @@ + + + diff --git a/app/src/main/res/drawable/rider_pro_message_comments.xml b/app/src/main/res/drawable/rider_pro_message_comments.xml new file mode 100644 index 0000000..a52d8ab --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_message_comments.xml @@ -0,0 +1,38 @@ + + + + + + + diff --git a/app/src/main/res/drawable/rider_pro_message_fans.xml b/app/src/main/res/drawable/rider_pro_message_fans.xml new file mode 100644 index 0000000..f31dcb3 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_message_fans.xml @@ -0,0 +1,50 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/rider_pro_message_like.xml b/app/src/main/res/drawable/rider_pro_message_like.xml new file mode 100644 index 0000000..484aa1d --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_message_like.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/app/src/main/res/drawable/rider_pro_moment_add.xml b/app/src/main/res/drawable/rider_pro_moment_add.xml new file mode 100644 index 0000000..2cca8eb --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_moment_add.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/rider_pro_moment_comment.xml b/app/src/main/res/drawable/rider_pro_moment_comment.xml new file mode 100644 index 0000000..778e3a4 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_moment_comment.xml @@ -0,0 +1,14 @@ + + + diff --git a/app/src/main/res/drawable/rider_pro_moment_demo_1.jpg b/app/src/main/res/drawable/rider_pro_moment_demo_1.jpg new file mode 100644 index 0000000..01e5e7c Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_moment_demo_1.jpg differ diff --git a/app/src/main/res/drawable/rider_pro_moment_demo_2.jpg b/app/src/main/res/drawable/rider_pro_moment_demo_2.jpg new file mode 100644 index 0000000..916f6bb Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_moment_demo_2.jpg differ diff --git a/app/src/main/res/drawable/rider_pro_moment_demo_3.jpg b/app/src/main/res/drawable/rider_pro_moment_demo_3.jpg new file mode 100644 index 0000000..02625f1 Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_moment_demo_3.jpg differ diff --git a/app/src/main/res/drawable/rider_pro_moment_time_flag.xml b/app/src/main/res/drawable/rider_pro_moment_time_flag.xml new file mode 100644 index 0000000..756242e --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_moment_time_flag.xml @@ -0,0 +1,18 @@ + + + + diff --git a/app/src/main/res/drawable/rider_pro_notification.xml b/app/src/main/res/drawable/rider_pro_notification.xml new file mode 100644 index 0000000..22bff98 --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_notification.xml @@ -0,0 +1,14 @@ + + + diff --git a/app/src/main/res/drawable/rider_pro_profile.xml b/app/src/main/res/drawable/rider_pro_profile.xml new file mode 100644 index 0000000..7633f6d --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_profile.xml @@ -0,0 +1,22 @@ + + + + diff --git a/app/src/main/res/drawable/rider_pro_profile_follow.png b/app/src/main/res/drawable/rider_pro_profile_follow.png new file mode 100644 index 0000000..b9bc9ba Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_profile_follow.png differ diff --git a/app/src/main/res/drawable/rider_pro_profile_line.xml b/app/src/main/res/drawable/rider_pro_profile_line.xml new file mode 100644 index 0000000..1b854dc --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_profile_line.xml @@ -0,0 +1,36 @@ + + + + + + + diff --git a/app/src/main/res/drawable/rider_pro_profile_message.png b/app/src/main/res/drawable/rider_pro_profile_message.png new file mode 100644 index 0000000..c3b903c Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_profile_message.png differ diff --git a/app/src/main/res/drawable/rider_pro_share.xml b/app/src/main/res/drawable/rider_pro_share.xml new file mode 100644 index 0000000..3a4cbfe --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_share.xml @@ -0,0 +1,46 @@ + + + + + + + diff --git a/app/src/main/res/drawable/rider_pro_street.xml b/app/src/main/res/drawable/rider_pro_street.xml new file mode 100644 index 0000000..4e1468a --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_street.xml @@ -0,0 +1,30 @@ + + + + + diff --git a/app/src/main/res/drawable/rider_pro_style_line.png b/app/src/main/res/drawable/rider_pro_style_line.png new file mode 100644 index 0000000..917c8a8 Binary files /dev/null and b/app/src/main/res/drawable/rider_pro_style_line.png differ diff --git a/app/src/main/res/drawable/rider_pro_style_wrapper.xml b/app/src/main/res/drawable/rider_pro_style_wrapper.xml new file mode 100644 index 0000000..21910ba --- /dev/null +++ b/app/src/main/res/drawable/rider_pro_style_wrapper.xml @@ -0,0 +1,12 @@ + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/rider_pro_log.xml b/app/src/main/res/mipmap-anydpi-v26/rider_pro_log.xml new file mode 100644 index 0000000..0f72421 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/rider_pro_log.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/rider_pro_log_round.xml b/app/src/main/res/mipmap-anydpi-v26/rider_pro_log_round.xml new file mode 100644 index 0000000..0f72421 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/rider_pro_log_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-hdpi/rider_pro_log.webp b/app/src/main/res/mipmap-hdpi/rider_pro_log.webp new file mode 100644 index 0000000..aa034ff Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/rider_pro_log.webp differ diff --git a/app/src/main/res/mipmap-hdpi/rider_pro_log_foreground.webp b/app/src/main/res/mipmap-hdpi/rider_pro_log_foreground.webp new file mode 100644 index 0000000..6673b8f Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/rider_pro_log_foreground.webp differ diff --git a/app/src/main/res/mipmap-hdpi/rider_pro_log_round.webp b/app/src/main/res/mipmap-hdpi/rider_pro_log_round.webp new file mode 100644 index 0000000..e4743cb Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/rider_pro_log_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-mdpi/rider_pro_log.webp b/app/src/main/res/mipmap-mdpi/rider_pro_log.webp new file mode 100644 index 0000000..6c50b9e Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/rider_pro_log.webp differ diff --git a/app/src/main/res/mipmap-mdpi/rider_pro_log_foreground.webp b/app/src/main/res/mipmap-mdpi/rider_pro_log_foreground.webp new file mode 100644 index 0000000..4d84f7e Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/rider_pro_log_foreground.webp differ diff --git a/app/src/main/res/mipmap-mdpi/rider_pro_log_round.webp b/app/src/main/res/mipmap-mdpi/rider_pro_log_round.webp new file mode 100644 index 0000000..ae74c0f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/rider_pro_log_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/rider_pro_log.webp b/app/src/main/res/mipmap-xhdpi/rider_pro_log.webp new file mode 100644 index 0000000..647da8c Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/rider_pro_log.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/rider_pro_log_foreground.webp b/app/src/main/res/mipmap-xhdpi/rider_pro_log_foreground.webp new file mode 100644 index 0000000..d919cc9 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/rider_pro_log_foreground.webp differ diff --git a/app/src/main/res/mipmap-xhdpi/rider_pro_log_round.webp b/app/src/main/res/mipmap-xhdpi/rider_pro_log_round.webp new file mode 100644 index 0000000..a11ad99 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/rider_pro_log_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/rider_pro_log.webp b/app/src/main/res/mipmap-xxhdpi/rider_pro_log.webp new file mode 100644 index 0000000..00fd127 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/rider_pro_log.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/rider_pro_log_foreground.webp b/app/src/main/res/mipmap-xxhdpi/rider_pro_log_foreground.webp new file mode 100644 index 0000000..2272676 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/rider_pro_log_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxhdpi/rider_pro_log_round.webp b/app/src/main/res/mipmap-xxhdpi/rider_pro_log_round.webp new file mode 100644 index 0000000..0129736 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/rider_pro_log_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/rider_pro_log.webp b/app/src/main/res/mipmap-xxxhdpi/rider_pro_log.webp new file mode 100644 index 0000000..5044acc Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/rider_pro_log.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/rider_pro_log_foreground.webp b/app/src/main/res/mipmap-xxxhdpi/rider_pro_log_foreground.webp new file mode 100644 index 0000000..730a2f0 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/rider_pro_log_foreground.webp differ diff --git a/app/src/main/res/mipmap-xxxhdpi/rider_pro_log_round.webp b/app/src/main/res/mipmap-xxxhdpi/rider_pro_log_round.webp new file mode 100644 index 0000000..47c3aa3 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/rider_pro_log_round.webp differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/rider_pro_log_background.xml b/app/src/main/res/values/rider_pro_log_background.xml new file mode 100644 index 0000000..778f8e1 --- /dev/null +++ b/app/src/main/res/values/rider_pro_log_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..cf9de1f --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + RiderPro + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..7ddf15c --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +