Нормальная модульная структура

This commit is contained in:
Roman Pytkov
2024-11-01 22:34:08 +03:00
parent b95666789c
commit 09210ff6f4
38 changed files with 381 additions and 49 deletions

View File

@@ -35,11 +35,11 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = "17"
} }
buildFeatures { buildFeatures {
compose = true compose = true
@@ -81,6 +81,7 @@ dependencies {
androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4) androidTestImplementation(libs.androidx.ui.test.junit4)
implementation(project(":data"))
implementation(project(":domain")) implementation(project(":domain"))
implementation(project(":presentation"))
runtimeOnly(project(":data"))
} }

View File

@@ -18,7 +18,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.github.nullptroma.wallenc.app.ui.theme.WallencTheme import com.github.nullptroma.wallenc.presentation.screens.main.MainScreen
import com.github.nullptroma.wallenc.presentation.theme.WallencTheme
import com.yandex.authsdk.YandexAuthLoginOptions import com.yandex.authsdk.YandexAuthLoginOptions
import com.yandex.authsdk.YandexAuthOptions import com.yandex.authsdk.YandexAuthOptions
import com.yandex.authsdk.YandexAuthResult import com.yandex.authsdk.YandexAuthResult
@@ -29,10 +30,10 @@ import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enableEdgeToEdge() enableEdgeToEdge()
val sdk = YandexAuthSdk.create(YandexAuthOptions(applicationContext, true)) val sdk = YandexAuthSdk.create(YandexAuthOptions(applicationContext, true))
val launcher = val launcher =
registerForActivityResult(sdk.contract) { result -> handleResult(result) } registerForActivityResult(sdk.contract) { result -> handleResult(result) }
@@ -41,9 +42,14 @@ class MainActivity : ComponentActivity() {
setContent { setContent {
WallencTheme { WallencTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(Modifier.padding(innerPadding)) { // Greeting(Modifier.padding(innerPadding)) {
launcher.launch(loginOptions) // launcher.launch(loginOptions)
} // }
MainScreen(
Modifier.padding(
innerPadding
)
)
} }
} }
} }
@@ -76,7 +82,7 @@ fun Greeting(modifier: Modifier = Modifier, onClick: () -> Unit) {
@Preview(showBackground = true) @Preview(showBackground = true)
@Composable @Composable
fun GreetingPreview() { fun GreetingPreview() {
WallencTheme { com.github.nullptroma.wallenc.presentation.theme.WallencTheme {
Greeting(Modifier) { Greeting(Modifier) {
} }

View File

@@ -4,6 +4,4 @@ import android.app.Application
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp @HiltAndroidApp
class WallencApplication : Application() { class WallencApplication : Application()
}

View File

@@ -0,0 +1,21 @@
package com.github.nullptroma.wallenc.app.di.modules.domain
import com.github.nullptroma.wallenc.domain.models.IMetaInfo
import com.github.nullptroma.wallenc.domain.usecases.TestUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class UseCasesModule {
var count = 0
@Provides
@Singleton
fun provideTestUseCase(meta: IMetaInfo): TestUseCase {
return TestUseCase(meta, count++)
}
}

View File

@@ -1,3 +0,0 @@
package com.github.nullptroma.wallenc.app.ui.screens.main
data class MainScreenState(val value: String)

View File

@@ -1,11 +0,0 @@
package com.github.nullptroma.wallenc.app.ui.screens.main
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class MainViewModel @Inject constructor(
): ViewModel() {
val stateFlow = MainScreenState("hello")
}

View File

@@ -9,3 +9,9 @@ plugins {
alias(libs.plugins.ksp) apply false alias(libs.plugins.ksp) apply false
alias(libs.plugins.jetbrains.kotlin.jvm) apply false alias(libs.plugins.jetbrains.kotlin.jvm) apply false
} }
allprojects {
tasks.withType<JavaCompile> {
options.compilerArgs.addAll(listOf("-Xlint:unchecked", "-Xlint:deprecation"))
}
}

View File

@@ -26,11 +26,11 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }
kotlinOptions { kotlinOptions {
jvmTarget = "1.8" jvmTarget = "17"
} }
} }

View File

@@ -0,0 +1,20 @@
package com.github.nullptroma.wallenc.data
import com.github.nullptroma.wallenc.domain.models.IMetaInfo
import java.net.URI
import java.time.LocalDateTime
class TestImpl : IMetaInfo {
override val name: String
get() = "Hello225"
override val size: Int
get() = 10
override val isDeleted: Boolean
get() = true
override val isHidden: Boolean
get() = true
override val lastModified: LocalDateTime
get() = TODO("Not yet implemented")
override val path: URI
get() = URI("/Hello/path")
}

View File

@@ -0,0 +1,18 @@
package com.github.nullptroma.wallenc.data.di
import com.github.nullptroma.wallenc.data.TestImpl
import com.github.nullptroma.wallenc.domain.models.IMetaInfo
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
class SingletonModule {
@Provides
fun provideIMeta() : IMetaInfo {
return TestImpl()
}
}

View File

@@ -4,6 +4,11 @@ plugins {
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_21 toolchain {
targetCompatibility = JavaVersion.VERSION_21 languageVersion = JavaLanguageVersion.of(17)
}
}
dependencies {
implementation(libs.kotlinx.coroutines.core)
} }

View File

@@ -1,4 +0,0 @@
package com.github.nullptroma.wallenc.domain
class MyClass {
}

View File

@@ -0,0 +1,6 @@
package com.github.nullptroma.wallenc.domain.models
interface IDirectory {
val metaInfo: IMetaInfo
val elementsCount: Int
}

View File

@@ -0,0 +1,5 @@
package com.github.nullptroma.wallenc.domain.models
interface IFile {
val metaInfo: IMetaInfo
}

View File

@@ -0,0 +1,14 @@
package com.github.nullptroma.wallenc.domain.models
import java.net.URI
import java.time.LocalDateTime
interface IMetaInfo {
val name: String
val size: Int
val isDeleted: Boolean
val isHidden: Boolean
val lastModified: LocalDateTime
val path: URI
}

View File

@@ -0,0 +1,16 @@
package com.github.nullptroma.wallenc.domain.storage
import kotlinx.coroutines.flow.StateFlow
interface IStorage {
val size: StateFlow<Int>
val numberOfFiles: StateFlow<Int>
val uuid: String
val name: StateFlow<String>
val totalSpace: StateFlow<Int?>
val availableSpace: StateFlow<Int?>
val isAvailable: StateFlow<Boolean>
val accessor: IStorageAccessor
suspend fun rename(newName: String)
}

View File

@@ -0,0 +1,32 @@
package com.github.nullptroma.wallenc.domain.storage
import com.github.nullptroma.wallenc.domain.models.IDirectory
import com.github.nullptroma.wallenc.domain.models.IFile
import com.github.nullptroma.wallenc.domain.utils.DataPackage
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import java.net.URI
interface IStorageAccessor {
val isAvailable: StateFlow<Boolean>
val filesUpdates: SharedFlow<IFile>
val dirsUpdates: SharedFlow<IDirectory>
suspend fun getAllFiles(): List<IFile>
suspend fun getFiles(path: URI): List<IFile>
fun getFilesStream(path: URI): Flow<DataPackage<IFile>>
suspend fun getAllDirs(): List<IDirectory>
suspend fun getDirs(path: URI): List<IDirectory>
fun getDirsStream(path: URI): Flow<DataPackage<IDirectory>>
suspend fun touchFile(path: URI)
suspend fun touchDir(path: URI)
suspend fun delete(path: URI)
suspend fun getFileInfo(path: URI)
suspend fun getDirInfo(path: URI)
suspend fun openWrite(path: URI)
suspend fun openRead(path: URI)
suspend fun moveToTrash(path: URI)
}

View File

@@ -0,0 +1,7 @@
package com.github.nullptroma.wallenc.domain.usecases
import com.github.nullptroma.wallenc.domain.models.IMetaInfo
class TestUseCase (val meta: IMetaInfo, val id: Int) {
}

View File

@@ -0,0 +1,8 @@
package com.github.nullptroma.wallenc.domain.utils
open class DataPackage<T>(
val data: T,
val hasNext: Boolean? = false,
val isLoading: Boolean? = false,
val isError: Boolean? = false
)

View File

@@ -0,0 +1,7 @@
package com.github.nullptroma.wallenc.domain.utils
class DataPage<T>(
list: List<T>,
val pageLength: Int,
val pageNumber: Int
) : DataPackage<List<T>>(list)

View File

@@ -5,22 +5,25 @@ coreKtx = "1.15.0"
junit = "4.13.2" junit = "4.13.2"
junitVersion = "1.2.1" junitVersion = "1.2.1"
espressoCore = "3.6.1" espressoCore = "3.6.1"
kotlinxCoroutinesCore = "1.9.0"
lifecycleRuntimeKtx = "2.8.7" lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.9.3" activityCompose = "1.9.3"
composeBom = "2024.10.01" composeBom = "2024.10.01"
navigation = "2.8.3" navigation = "2.8.3"
hiltNavigation = "1.2.0" hiltNavigation = "1.2.0"
yandexAuthSdk = "3.1.1" yandexAuthSdk = "3.1.2"
daggerHilt = "2.51.1" daggerHilt = "2.52"
ksp = "2.0.20-1.0.25" ksp = "2.0.20-1.0.25"
room = "2.6.1" room = "2.6.1"
retrofit = "2.9.0" retrofit = "2.11.0"
gson = "2.10.1" gson = "2.11.0"
appcompat = "1.7.0" appcompat = "1.7.0"
material = "1.12.0" material = "1.12.0"
jetbrainsKotlinJvm = "2.0.20" jetbrainsKotlinJvm = "2.0.20"
runtimeAndroid = "1.7.5"
[libraries] [libraries]
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesCore" }
navigation = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } navigation = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
navigation-hilt-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigation" } navigation-hilt-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigation" }
@@ -59,6 +62,7 @@ androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-man
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" } material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" }
[plugins] [plugins]

1
lib/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

9
lib/build.gradle.kts Normal file
View File

@@ -0,0 +1,9 @@
plugins {
id("java-library")
alias(libs.plugins.jetbrains.kotlin.jvm)
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}

View File

@@ -0,0 +1,5 @@
package com.example.lib
class MyClass {
val test: java.time.LocalDate;
}

1
presentation/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,74 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.dagger.hilt)
alias(libs.plugins.ksp)
}
android {
namespace = "com.github.nullptroma.wallenc.presentation"
compileSdk = 34
defaultConfig {
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation(libs.navigation)
implementation(libs.navigation.hilt.compose)
// Hilt
implementation(libs.dagger.hilt)
ksp(libs.dagger.hilt.compiler)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
implementation(project(":domain"))
}

View File

21
presentation/proguard-rules.pro vendored Normal file
View File

@@ -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

View File

@@ -0,0 +1,24 @@
package com.github.nullptroma.wallenc.presentation
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.github.nullptroma.wallenc.presentation.test", appContext.packageName)
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -1,4 +1,4 @@
package com.github.nullptroma.wallenc.app.ui.screens.main package com.github.nullptroma.wallenc.presentation.screens.main
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -6,19 +6,21 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
@Composable @androidx.compose.runtime.Composable
fun MainScreen(modifier: Modifier = Modifier, viewModel: MainViewModel = hiltViewModel()) { fun MainScreen(modifier: Modifier = Modifier.Companion, viewModel: MainViewModel = hiltViewModel()) {
val state = viewModel.stateFlow val state = viewModel.stateFlow
Column(modifier = modifier.imePadding()) { Column(modifier = modifier.imePadding()) {
Text(text = state.value) Text(text = state.value)
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) { Box(
modifier = Modifier.Companion.fillMaxSize(),
contentAlignment = Alignment.Companion.BottomCenter
) {
TextField("", onValueChange = { TextField("", onValueChange = {
}) })

View File

@@ -0,0 +1,3 @@
package com.github.nullptroma.wallenc.presentation.screens.main
data class MainScreenState(val value: String)

View File

@@ -0,0 +1,14 @@
package com.github.nullptroma.wallenc.presentation.screens.main
import androidx.lifecycle.ViewModel
import com.github.nullptroma.wallenc.domain.usecases.TestUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
@HiltViewModel
class MainViewModel @javax.inject.Inject constructor(
testUseCase: TestUseCase,
testUseCase2: TestUseCase,
testUseCase3: TestUseCase,
): ViewModel() {
val stateFlow = MainScreenState("${testUseCase3.meta.name}, number ${testUseCase3.id}")
}

View File

@@ -1,4 +1,4 @@
package com.github.nullptroma.wallenc.app.ui.theme package com.github.nullptroma.wallenc.presentation.theme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@@ -1,4 +1,4 @@
package com.github.nullptroma.wallenc.app.ui.theme package com.github.nullptroma.wallenc.presentation.theme
import android.os.Build import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme

View File

@@ -1,4 +1,4 @@
package com.github.nullptroma.wallenc.app.ui.theme package com.github.nullptroma.wallenc.presentation.theme
import androidx.compose.material3.Typography import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle

View File

@@ -0,0 +1,17 @@
package com.github.nullptroma.wallenc.presentation
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@@ -23,3 +23,4 @@ rootProject.name = "Wallenc"
include(":app") include(":app")
include(":data") include(":data")
include(":domain") include(":domain")
include(":presentation")