Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
58 changes: 58 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
}

android {
namespace = "com.example.bookon"
compileSdk {
version = release(36) {
minorApiLevel = 1
}
}

defaultConfig {
applicationId = "com.example.bookon"
minSdk = 34
targetSdk = 36
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
buildFeatures {
compose = true
}
}

dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
testImplementation(libs.junit)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(libs.androidx.junit)
debugImplementation(libs.androidx.compose.ui.test.manifest)
debugImplementation(libs.androidx.compose.ui.tooling)
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.bookon

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.example.bookon", appContext.packageName)
}
}
27 changes: 27 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.BookOn">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.BookOn">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
47 changes: 47 additions & 0 deletions app/src/main/java/com/example/bookon/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.example.bookon

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.bookon.theme.BookOnTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BookOnTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
BookOnTheme {
Greeting("Android")
}
}
39 changes: 39 additions & 0 deletions app/src/main/java/com/example/bookon/theme/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.bookon.theme

import androidx.compose.ui.graphics.Color

val ButtonColor = Color(0xFF8DC73F)
val DisabledButtonColor = Color(0xFFEBEBEB)
val InputPlaceholderTextColor = Color(0xFFAEAEB2)
val InputTextColor = Color(0xFF000000)
val WarningTextColor = Color(0xFFB60000)
val DescriptionTextColor = Color(0xFFB60000)
val DarkGrayTextColor = Color(0xFF404040)
val ErrorBackgroundColor = Color(0xFFFFF1F1)

object BookOnColor {
val Primary = ButtonColor
val PrimaryDark = Color(0xFF72A21D)
val PrimaryPressed = Color(0xFF7BAB1F)
val PrimaryLight = Color(0xFFEFF6E3)
val PrimaryContainer = Color(0xFFF7F9EF)
val Disabled = DisabledButtonColor
val Background = Color(0xFFFBFBFC)
val Surface = Color(0xFFFFFFFF)
val SurfaceAlt = Color(0xFFF1F1F4)
val SurfaceBorder = Color(0xFFEAEAEC)
val Divider = Color(0xFFF2F2F4)
val TextPrimary = InputTextColor
val TextSecondary = Color(0xFF8E8E93)
val TextTertiary = Color(0xFF9A9AA1)
val TextPlaceholder = InputPlaceholderTextColor
val TextDarkGray = DarkGrayTextColor
val Error = WarningTextColor
val ErrorContainer = ErrorBackgroundColor
val NavigationInactive = Color(0xFFB0B0B5)
val SwitchOff = Color(0xFFD9D9D9)
val BookCoverPlaceholder = Color(0xFF6B4329)
val BookCoverSmallPlaceholder = Color(0xFFE8E0D8)
val IconContainer = Color(0xFFE8E8EA)
val StatusAvailableContainer = PrimaryLight
}
80 changes: 80 additions & 0 deletions app/src/main/java/com/example/bookon/theme/DesignToken.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.example.bookon.theme

import androidx.compose.ui.unit.dp

object AppSpacing {
val ScreenHorizontal = 24.dp
val HomeHorizontal = 28.dp
val ScreenVertical = 24.dp
val Section = 24.dp
val Content = 16.dp
val FieldHorizontal = 20.dp
val Item = 12.dp
val Small = 8.dp
val Tiny = 4.dp
}

object AppRadius {
val Button = 10.dp
val Field = 16.dp
val Search = 21.dp
val Card = 16.dp
val LargeCard = 20.dp
val Chip = 12.dp
val Small = 8.dp
val IconButton = 10.dp
val Progress = 8.dp
}

object AppElevation {
val None = 0.dp
val Field = 6.dp
val Button = 2.dp
val Card = 10.dp
val StrongCard = 20.dp
val BookCover = 4.dp
}

object AppIconSize {
val Small = 18.dp
val Default = 24.dp
val Medium = 30.dp
val Large = 32.dp
val XLarge = 36.dp
val Avatar = 64.dp
}

object AppComponentSize {
val MinTouchTarget = 48.dp
val ButtonHeight = 52.dp
val FieldHeight = 52.dp
val FieldBorderWidth = 1.dp
val HomeSearchHeight = 42.dp
val HomeActionButton = 36.dp
val TopBarHeight = 56.dp
val NavigationHeight = 89.dp
val ChipHeight = 34.dp
val SmallChipHeight = 24.dp
val BookCoverWidth = 132.dp
val BookCoverHeight = 177.dp
val HomeBookCoverWidth = 94.dp
val HomeBookCoverHeight = 160.dp
val HomeBookCardWidth = 112.dp
val LibraryBookCoverWidth = 166.dp
val LibraryBookCoverHeight = 234.dp
val LibrarySortToggleWidth = 130.dp
val LibrarySortToggleHeight = 36.dp
val LibrarySortOptionHeight = 30.dp
val BookListItemHeight = 88.dp
val BookListCoverWidth = 54.dp
val BookListCoverHeight = 68.dp
val PopularBookCoverWidth = 50.dp
val PopularBookCoverHeight = 64.dp
val RankingPedestalWidth = 100.dp
val RankingFirstPedestalHeight = 96.dp
val RankingSecondPedestalHeight = 76.dp
val RankingThirdPedestalHeight = 62.dp
val RankingListRowHeight = 64.dp
val StatSummaryCardHeight = 76.dp
val InfoCardIcon = 36.dp
}
73 changes: 73 additions & 0 deletions app/src/main/java/com/example/bookon/theme/Theme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.example.bookon.theme

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 = BookOnColor.Primary,
onPrimary = BookOnColor.Surface,
primaryContainer = BookOnColor.PrimaryContainer,
onPrimaryContainer = BookOnColor.TextPrimary,
secondary = BookOnColor.PrimaryPressed,
tertiary = BookOnColor.PrimaryLight,
background = BookOnColor.Background,
onBackground = BookOnColor.TextPrimary,
surface = BookOnColor.Surface,
onSurface = BookOnColor.TextPrimary,
surfaceVariant = BookOnColor.SurfaceAlt,
onSurfaceVariant = BookOnColor.TextSecondary,
outline = BookOnColor.SurfaceBorder,
error = BookOnColor.Error,
errorContainer = BookOnColor.ErrorContainer,
onErrorContainer = BookOnColor.Error,
)

private val LightColorScheme = lightColorScheme(
primary = BookOnColor.Primary,
onPrimary = BookOnColor.Surface,
primaryContainer = BookOnColor.PrimaryContainer,
onPrimaryContainer = BookOnColor.TextPrimary,
secondary = BookOnColor.PrimaryPressed,
tertiary = BookOnColor.PrimaryLight,
background = BookOnColor.Background,
onBackground = BookOnColor.TextPrimary,
surface = BookOnColor.Surface,
onSurface = BookOnColor.TextPrimary,
surfaceVariant = BookOnColor.SurfaceAlt,
onSurfaceVariant = BookOnColor.TextSecondary,
outline = BookOnColor.SurfaceBorder,
error = BookOnColor.Error,
errorContainer = BookOnColor.ErrorContainer,
onErrorContainer = BookOnColor.Error,
)

@Composable
fun BookOnTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = false,
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
)
}
Loading