├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ └── com
│ │ └── conf
│ │ └── mad
│ │ └── todo
│ │ ├── App.kt
│ │ ├── MainActivity.kt
│ │ └── TodoApp.kt
│ └── res
│ ├── drawable
│ ├── ic_launcher_background.xml
│ └── ic_launcher_foreground.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.webp
│ ├── ic_launcher_foreground.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-mdpi
│ ├── ic_launcher.webp
│ ├── ic_launcher_foreground.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xhdpi
│ ├── ic_launcher.webp
│ ├── ic_launcher_foreground.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.webp
│ ├── ic_launcher_foreground.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.webp
│ ├── ic_launcher_foreground.webp
│ └── ic_launcher_round.webp
│ ├── values
│ ├── colors.xml
│ ├── ic_launcher_background.xml
│ ├── strings.xml
│ └── themes.xml
│ └── xml
│ ├── backup_rules.xml
│ └── data_extraction_rules.xml
├── build-logic
├── .gitignore
├── README.md
├── build.gradle.kts
├── gradle.properties
├── settings.gradle
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── conf
│ └── mad
│ └── todo
│ ├── convention
│ ├── AndroidFeaturePlugin.kt
│ └── PureKotlinPlugin.kt
│ ├── dsl
│ ├── AndroidGradleDsl.kt
│ ├── GradleDsl.kt
│ ├── KotlinGradleDsl.kt
│ └── VersionCatalogDsl.kt
│ └── primitive
│ ├── AndroidApplicationPlugin.kt
│ ├── AndroidComposePlugin.kt
│ ├── AndroidHiltPlugin.kt
│ ├── AndroidKotlinPlugin.kt
│ ├── AndroidPlugin.kt
│ ├── AndroidRoomPlugin.kt
│ └── KotlinSerializationPlugin.kt
├── build.gradle.kts
├── core
├── common
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── conf
│ │ └── mad
│ │ └── todo
│ │ └── common
│ │ ├── TodoDispatchers.kt
│ │ └── di
│ │ └── DispatchersModule.kt
├── database
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ ├── schemas
│ │ └── com.conf.mad.todo.database.TodoDatabase
│ │ │ └── 1.json
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── conf
│ │ └── mad
│ │ └── todo
│ │ └── database
│ │ ├── TaskDao.kt
│ │ ├── TodoDatabase.kt
│ │ ├── di
│ │ └── DatabaseModule.kt
│ │ └── entity
│ │ └── TaskEntity.kt
├── designsystem
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── conf
│ │ │ └── mad
│ │ │ └── todo
│ │ │ └── designsystem
│ │ │ ├── Color.kt
│ │ │ ├── Theme.kt
│ │ │ ├── Type.kt
│ │ │ └── preview
│ │ │ ├── ComponentPreview.kt
│ │ │ └── DevicePreview.kt
│ │ └── res
│ │ ├── drawable
│ │ ├── ic_add_task.xml
│ │ ├── ic_clear.xml
│ │ ├── ic_star_default.xml
│ │ ├── ic_star_filled.xml
│ │ └── ic_title_home.xml
│ │ └── font
│ │ ├── pretendard_medium.otf
│ │ ├── pretendard_regular.otf
│ │ ├── pretendard_semibold.otf
│ │ └── stretch_pro.otf
└── ui
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── conf
│ └── mad
│ └── todo
│ └── ui
│ └── Clickable.kt
├── data
└── task
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── conf
│ └── mad
│ └── todo
│ └── data
│ └── task
│ ├── di
│ └── TaskModule.kt
│ ├── mapper
│ └── Task.kt
│ └── repository
│ └── DefaultTaskRepository.kt
├── domain
└── task
│ ├── .gitignore
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── java
│ └── com
│ └── conf
│ └── mad
│ └── todo
│ └── task
│ ├── model
│ └── Task.kt
│ └── repository
│ └── TaskRepository.kt
├── feature
├── home
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── conf
│ │ │ └── mad
│ │ │ └── todo
│ │ │ └── home
│ │ │ ├── HomeScreen.kt
│ │ │ ├── HomeViewModel.kt
│ │ │ ├── component
│ │ │ ├── CompletedTaskVisibilityToggleButton.kt
│ │ │ ├── DeleteTaskDialog.kt
│ │ │ ├── EmptyTaskView.kt
│ │ │ ├── HomeBottomAppBar.kt
│ │ │ ├── HomeTopAppBar.kt
│ │ │ └── TaskItem.kt
│ │ │ └── model
│ │ │ ├── HomeMenu.kt
│ │ │ ├── HomeUiState.kt
│ │ │ ├── TaskStatus.kt
│ │ │ └── TaskUiModel.kt
│ │ └── res
│ │ └── drawable
│ │ ├── ic_clip.xml
│ │ ├── ic_navi_add.xml
│ │ ├── ic_navi_favorite_default.xml
│ │ ├── ic_navi_favorite_selected.xml
│ │ ├── ic_navi_task_default.xml
│ │ ├── ic_navi_task_selected.xml
│ │ ├── ic_star_home_default.xml
│ │ ├── ic_star_home_filled.xml
│ │ ├── ic_task_completed.xml
│ │ ├── ic_task_default.xml
│ │ └── ic_task_done.xml
└── post
│ ├── .gitignore
│ ├── build.gradle.kts
│ ├── consumer-rules.pro
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── conf
│ └── mad
│ └── todo
│ └── post
│ ├── PostScreen.kt
│ ├── PostViewModel.kt
│ ├── component
│ ├── AddTaskTopAppBar.kt
│ └── TaskTextField.kt
│ └── model
│ └── PostUiState.kt
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── renovate.json
├── settings.gradle.kts
└── spotless
├── .editorconfig
├── spotless.license.kt
└── spotless.license.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/kotlin,android,jetbrains,gradle
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=kotlin,android,jetbrains,gradle
3 |
4 | ### Android ###
5 | # Gradle files
6 | .gradle/
7 | build/
8 | .kotlin
9 |
10 | # Local configuration file (sdk path, etc)
11 | local.properties
12 |
13 | # Log/OS Files
14 | *.log
15 |
16 | # Android Studio generated files and folders
17 | captures/
18 | .externalNativeBuild/
19 | .cxx/
20 | *.apk
21 | output.json
22 | report
23 |
24 | # IntelliJ
25 | *.iml
26 | .idea/
27 | misc.xml
28 | deploymentTargetDropDown.xml
29 | render.experimental.xml
30 |
31 | # Keystore files
32 | *.jks
33 | *.keystore
34 |
35 | # Google Services (e.g. APIs or Firebase)
36 | google-services.json
37 |
38 | # Android Profiling
39 | *.hprof
40 |
41 | ### Android Patch ###
42 | gen-external-apklibs
43 |
44 | # Replacement of .externalNativeBuild directories introduced
45 | # with Android Studio 3.5.
46 |
47 | ### JetBrains ###
48 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
49 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
50 |
51 | # User-specific stuff
52 | .idea/**/workspace.xml
53 | .idea/**/tasks.xml
54 | .idea/**/usage.statistics.xml
55 | .idea/**/dictionaries
56 | .idea/**/shelf
57 |
58 | # AWS User-specific
59 | .idea/**/aws.xml
60 |
61 | # Generated files
62 | .idea/**/contentModel.xml
63 |
64 | # Sensitive or high-churn files
65 | .idea/**/dataSources/
66 | .idea/**/dataSources.ids
67 | .idea/**/dataSources.local.xml
68 | .idea/**/sqlDataSources.xml
69 | .idea/**/dynamic.xml
70 | .idea/**/uiDesigner.xml
71 | .idea/**/dbnavigator.xml
72 |
73 | # Gradle
74 | .idea/**/gradle.xml
75 | .idea/**/libraries
76 |
77 | # Gradle and Maven with auto-import
78 | # When using Gradle or Maven with auto-import, you should exclude module files,
79 | # since they will be recreated, and may cause churn. Uncomment if using
80 | # auto-import.
81 | # .idea/artifacts
82 | # .idea/compiler.xml
83 | # .idea/jarRepositories.xml
84 | # .idea/modules.xml
85 | # .idea/*.iml
86 | # .idea/modules
87 | # *.iml
88 | # *.ipr
89 |
90 | # CMake
91 | cmake-build-*/
92 |
93 | # Mongo Explorer plugin
94 | .idea/**/mongoSettings.xml
95 |
96 | # File-based project format
97 | *.iws
98 |
99 | # IntelliJ
100 | out/
101 |
102 | # mpeltonen/sbt-idea plugin
103 | .idea_modules/
104 |
105 | # JIRA plugin
106 | atlassian-ide-plugin.xml
107 |
108 | # Cursive Clojure plugin
109 | .idea/replstate.xml
110 |
111 | # SonarLint plugin
112 | .idea/sonarlint/
113 |
114 | # Crashlytics plugin (for Android Studio and IntelliJ)
115 | com_crashlytics_export_strings.xml
116 | crashlytics.properties
117 | crashlytics-build.properties
118 | fabric.properties
119 |
120 | # Editor-based Rest Client
121 | .idea/httpRequests
122 |
123 | # Android studio 3.1+ serialized cache file
124 | .idea/caches/build_file_checksums.ser
125 |
126 | ### JetBrains Patch ###
127 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
128 |
129 | # *.iml
130 | # modules.xml
131 | # .idea/misc.xml
132 | # *.ipr
133 |
134 | # Sonarlint plugin
135 | # https://plugins.jetbrains.com/plugin/7973-sonarlint
136 | .idea/**/sonarlint/
137 |
138 | # SonarQube Plugin
139 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
140 | .idea/**/sonarIssues.xml
141 |
142 | # Markdown Navigator plugin
143 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
144 | .idea/**/markdown-navigator.xml
145 | .idea/**/markdown-navigator-enh.xml
146 | .idea/**/markdown-navigator/
147 |
148 | # Cache file creation bug
149 | # See https://youtrack.jetbrains.com/issue/JBR-2257
150 | .idea/$CACHE_FILE$
151 |
152 | # CodeStream plugin
153 | # https://plugins.jetbrains.com/plugin/12206-codestream
154 | .idea/codestream.xml
155 |
156 | # Azure Toolkit for IntelliJ plugin
157 | # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
158 | .idea/**/azureSettings.xml
159 |
160 | ### Kotlin ###
161 | # Compiled class file
162 | *.class
163 |
164 | # Log file
165 |
166 | # BlueJ files
167 | *.ctxt
168 |
169 | # Mobile Tools for Java (J2ME)
170 | .mtj.tmp/
171 |
172 | # Package Files #
173 | *.jar
174 | *.war
175 | *.nar
176 | *.ear
177 | *.zip
178 | *.tar.gz
179 | *.rar
180 |
181 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
182 | hs_err_pid*
183 | replay_pid*
184 |
185 | ### Gradle ###
186 | .gradle
187 | **/build/
188 | !src/**/build/
189 |
190 | # Ignore Gradle GUI config
191 | gradle-app.setting
192 |
193 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
194 | !gradle-wrapper.jar
195 |
196 | # Avoid ignore Gradle wrappper properties
197 | !gradle-wrapper.properties
198 |
199 | # Cache of project
200 | .gradletasknamecache
201 |
202 | # Eclipse Gradle plugin generated files
203 | # Eclipse Core
204 | .project
205 | # JDT-specific (Eclipse Java Development Tools)
206 | .classpath
207 |
208 | ### Gradle Patch ###
209 | # Java heap dump
210 |
211 | # End of https://www.toptal.com/developers/gitignore/api/kotlin,android,jetbrains,gradle
212 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-2024 MADConference
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
To-Do Sample Application
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Android Sample App for Mobile App Developer Conference(MADC)
10 |
11 |
12 | Download
13 |
14 | Go to the [Releases](https://github.com/MobileAppDeveloperConference/android/releases) to download
15 | the latest APK.
16 |
17 | Tech Stack
18 |
19 | - 100% Kotlin + Jetpack Compose
20 | - Kotlinx Libraries
21 | - kotlinx.coroutines
22 | - kotlinx.serialization
23 | - Jetpack
24 | - Startup
25 | - ViewModel
26 | - Navigation
27 | - Room + ksp
28 | - Dagger-Hilt + ksp
29 | - Timber
30 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.primitive.android.application")
25 | id("conf.mad.primitive.android.kotlin")
26 | id("conf.mad.primitive.android.compose")
27 | id("conf.mad.primitive.android.hilt")
28 | id("conf.mad.primitive.kotlin.serialization")
29 | }
30 |
31 | android {
32 | namespace = "com.conf.mad.todo"
33 |
34 | defaultConfig {
35 | applicationId = "com.conf.mad.todo"
36 | versionCode = libs.versions.versionCode.get().toInt()
37 | versionName = libs.versions.appVersion.get()
38 |
39 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
40 | vectorDrawables {
41 | useSupportLibrary = true
42 | }
43 | }
44 |
45 | signingConfigs {
46 | getByName("debug") {
47 | keyAlias = "androiddebugkey"
48 | keyPassword = "android"
49 | storeFile = File("${project.rootDir.absolutePath}/keystore/debug.keystore")
50 | storePassword = "android"
51 | }
52 | }
53 |
54 | buildTypes {
55 | release {
56 | isMinifyEnabled = true
57 | isShrinkResources = true
58 | proguardFiles(
59 | getDefaultProguardFile("proguard-android-optimize.txt"),
60 | "proguard-rules.pro"
61 | )
62 | signingConfig = signingConfigs.getByName("debug")
63 | }
64 | }
65 | buildFeatures {
66 | buildConfig = true
67 | }
68 | }
69 |
70 | dependencies {
71 | implementation(projects.core.common)
72 | implementation(projects.core.database)
73 | implementation(projects.core.designsystem)
74 | implementation(projects.`data`.task)
75 | implementation(projects.feature.home)
76 | implementation(projects.feature.post)
77 | testImplementation(libs.junit)
78 | androidTestImplementation(libs.androidx.test.junit)
79 | androidTestImplementation(libs.androidx.test.espresso)
80 | androidTestImplementation(platform(libs.androidx.compose.bom))
81 | }
82 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
27 |
28 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/com/conf/mad/todo/App.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo
24 |
25 | import android.app.Application
26 | import dagger.hilt.android.HiltAndroidApp
27 |
28 | @HiltAndroidApp
29 | class App : Application()
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/conf/mad/todo/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo
24 |
25 | import android.os.Bundle
26 | import androidx.activity.ComponentActivity
27 | import androidx.activity.SystemBarStyle
28 | import androidx.activity.compose.setContent
29 | import androidx.activity.enableEdgeToEdge
30 | import androidx.compose.runtime.DisposableEffect
31 | import com.conf.mad.todo.designsystem.TodoTheme
32 | import dagger.hilt.android.AndroidEntryPoint
33 |
34 | @AndroidEntryPoint
35 | class MainActivity : ComponentActivity() {
36 | override fun onCreate(savedInstanceState: Bundle?) {
37 | super.onCreate(savedInstanceState)
38 | setContent {
39 | DisposableEffect(true) {
40 | enableEdgeToEdge(
41 | statusBarStyle = SystemBarStyle.light(
42 | android.graphics.Color.TRANSPARENT,
43 | android.graphics.Color.TRANSPARENT
44 | )
45 | )
46 | onDispose {}
47 | }
48 | TodoTheme {
49 | TodoApp()
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/com/conf/mad/todo/TodoApp.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo
24 |
25 | import androidx.compose.runtime.Composable
26 | import androidx.navigation.NavHostController
27 | import androidx.navigation.compose.NavHost
28 | import androidx.navigation.compose.rememberNavController
29 | import com.conf.mad.todo.designsystem.TodoTheme
30 | import com.conf.mad.todo.home.HOME_SCREEN_ROUTE
31 | import com.conf.mad.todo.home.homeScreen
32 | import com.conf.mad.todo.post.POST_SCREEN_ROUTE
33 | import com.conf.mad.todo.post.POST_SCREEN_TASK_DEFAULT_ID
34 | import com.conf.mad.todo.post.postScreen
35 |
36 | @Composable
37 | fun TodoApp(navController: NavHostController = rememberNavController()) {
38 | TodoTheme {
39 | NavHost(
40 | navController = navController,
41 | startDestination = HOME_SCREEN_ROUTE
42 | ) {
43 | homeScreen(
44 | onPost = {
45 | navController.navigate("${POST_SCREEN_ROUTE}/${POST_SCREEN_TASK_DEFAULT_ID}")
46 | }
47 | )
48 | postScreen(
49 | onCancel = { navController.popBackStack() },
50 | onComplete = {
51 | navController.navigate(HOME_SCREEN_ROUTE) {
52 | launchSingleTop = true
53 | }
54 | }
55 | )
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
31 |
32 |
33 |
39 |
42 |
45 |
46 |
47 |
48 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 | #FFBB86FC
27 | #FF6200EE
28 | #FF3700B3
29 | #FF03DAC5
30 | #FF018786
31 | #FF000000
32 | #FFFFFFFF
33 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 | #000000
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 | TodoMad
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
31 |
32 |
38 |
--------------------------------------------------------------------------------
/build-logic/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/build-logic/README.md:
--------------------------------------------------------------------------------
1 | # Build logic rules
2 |
3 | ○ module -> convention
4 | ○ module -> primitive
5 | ○ convention -> primitive
6 | ✗ convention -> convention
7 | ○ primitive -> primitive
8 | ✗ primitive -> convention
9 |
--------------------------------------------------------------------------------
/build-logic/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2 |
3 | plugins {
4 | `kotlin-dsl`
5 | }
6 |
7 | group = "com.conf.mad.todo.buildlogic"
8 |
9 | repositories {
10 | google()
11 | mavenCentral()
12 | gradlePluginPortal()
13 | }
14 |
15 | val compileKotlin: KotlinCompile by tasks
16 | compileKotlin.kotlinOptions.jvmTarget = "17"
17 |
18 | java {
19 | sourceCompatibility = JavaVersion.VERSION_17
20 | targetCompatibility = JavaVersion.VERSION_17
21 | }
22 |
23 | dependencies {
24 | compileOnly(libs.kotlin.gradle.plugin)
25 | compileOnly(libs.android.gradle.plugin)
26 | compileOnly(libs.kotlin.compose.compiler.gradle.plugin)
27 | // https://github.com/google/dagger/issues/3068#issuecomment-1470534930
28 | compileOnly(libs.java.poet)
29 | }
30 |
31 | gradlePlugin {
32 | plugins {
33 | // primitives
34 | register("androidApplication") {
35 | id = "conf.mad.primitive.android.application"
36 | implementationClass = "com.conf.mad.todo.primitive.AndroidApplicationPlugin"
37 | }
38 | register("androidCompose") {
39 | id = "conf.mad.primitive.android.compose"
40 | implementationClass = "com.conf.mad.todo.primitive.AndroidComposePlugin"
41 | }
42 | register("androidHilt") {
43 | id = "conf.mad.primitive.android.hilt"
44 | implementationClass = "com.conf.mad.todo.primitive.AndroidHiltPlugin"
45 | }
46 | register("androidRoom") {
47 | id = "conf.mad.primitive.android.room"
48 | implementationClass = "com.conf.mad.todo.primitive.AndroidRoomPlugin"
49 | }
50 | register("androidKotlin") {
51 | id = "conf.mad.primitive.android.kotlin"
52 | implementationClass = "com.conf.mad.todo.primitive.AndroidKotlinPlugin"
53 | }
54 | register("android") {
55 | id = "conf.mad.primitive.android"
56 | implementationClass = "com.conf.mad.todo.primitive.AndroidPlugin"
57 | }
58 | register("kotlinSerialization") {
59 | id = "conf.mad.primitive.kotlin.serialization"
60 | implementationClass = "com.conf.mad.todo.primitive.KotlinSerializationPlugin"
61 | }
62 | // convention
63 | register("androidFeature") {
64 | id = "conf.mad.convention.android.feature"
65 | implementationClass = "com.conf.mad.todo.convention.AndroidFeaturePlugin"
66 | }
67 | register("pureKotlin") {
68 | id = "conf.mad.convention.kotlin"
69 | implementationClass = "com.conf.mad.todo.convention.PureKotlinPlugin"
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/build-logic/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.configureondemand=true
2 | org.gradle.caching=true
3 | org.gradle.parallel=true
--------------------------------------------------------------------------------
/build-logic/settings.gradle:
--------------------------------------------------------------------------------
1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
2 |
3 | dependencyResolutionManagement {
4 | repositories {
5 | google()
6 | mavenCentral()
7 | }
8 | versionCatalogs {
9 | create("libs") {
10 | from(files("../gradle/libs.versions.toml"))
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/convention/AndroidFeaturePlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.convention
2 |
3 | import org.gradle.api.Plugin
4 | import org.gradle.api.Project
5 |
6 | class AndroidFeaturePlugin : Plugin {
7 | override fun apply(target: Project) {
8 | with(target) {
9 | with(pluginManager) {
10 | apply("conf.mad.primitive.android")
11 | apply("conf.mad.primitive.android.kotlin")
12 | apply("conf.mad.primitive.android.compose")
13 | apply("conf.mad.primitive.android.hilt")
14 | }
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/convention/PureKotlinPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.convention
2 |
3 | import com.conf.mad.todo.dsl.implementation
4 | import com.conf.mad.todo.dsl.library
5 | import com.conf.mad.todo.dsl.libs
6 | import org.gradle.api.Plugin
7 | import org.gradle.api.Project
8 | import org.gradle.kotlin.dsl.dependencies
9 |
10 | class PureKotlinPlugin : Plugin {
11 | override fun apply(target: Project) = with(target) {
12 | with(pluginManager) {
13 | apply("java-library")
14 | apply("org.jetbrains.kotlin.jvm")
15 | }
16 | dependencies {
17 | implementation(libs.library("javax-inject"))
18 | implementation(libs.library("kotlinx-coroutines-core"))
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/dsl/AndroidGradleDsl.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.dsl
2 |
3 | import com.android.build.gradle.LibraryExtension
4 | import com.android.build.gradle.TestedExtension
5 | import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
6 | import org.gradle.api.JavaVersion
7 | import org.gradle.api.Project
8 | import org.gradle.kotlin.dsl.configure
9 | import org.gradle.kotlin.dsl.dependencies
10 |
11 | fun Project.androidApplication(action: BaseAppModuleExtension.() -> Unit) {
12 | extensions.configure(action)
13 | }
14 |
15 | fun Project.androidLibrary(action: LibraryExtension.() -> Unit) {
16 | extensions.configure(action)
17 | }
18 |
19 | fun Project.android(action: TestedExtension.() -> Unit) {
20 | extensions.configure(action)
21 | }
22 |
23 | fun Project.setupAndroid() {
24 | android {
25 | namespace?.let {
26 | this.namespace = it
27 | }
28 | compileSdkVersion(35)
29 |
30 | defaultConfig {
31 | minSdk = 28
32 | targetSdk = 35
33 | }
34 |
35 | compileOptions {
36 | sourceCompatibility = JavaVersion.VERSION_17
37 | targetCompatibility = JavaVersion.VERSION_17
38 | isCoreLibraryDesugaringEnabled = true
39 | }
40 | dependencies {
41 | add("coreLibraryDesugaring", libs.library("android-desugar-libs"))
42 | }
43 | testOptions {
44 | unitTests {
45 | isIncludeAndroidResources = true
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/dsl/GradleDsl.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.dsl
2 |
3 | import org.gradle.api.artifacts.MinimalExternalModuleDependency
4 | import org.gradle.kotlin.dsl.DependencyHandlerScope
5 |
6 | fun DependencyHandlerScope.implementation(
7 | artifact: MinimalExternalModuleDependency,
8 | ) {
9 | add("implementation", artifact)
10 | }
11 |
12 | fun DependencyHandlerScope.debugImplementation(
13 | artifact: MinimalExternalModuleDependency,
14 | ) {
15 | add("debugImplementation", artifact)
16 | }
17 |
18 | fun DependencyHandlerScope.androidTestImplementation(
19 | artifact: MinimalExternalModuleDependency,
20 | ) {
21 | add("androidTestImplementation", artifact)
22 | }
23 |
24 | fun DependencyHandlerScope.testImplementation(
25 | artifact: MinimalExternalModuleDependency,
26 | ) {
27 | add("testImplementation", artifact)
28 | }
29 |
30 | fun DependencyHandlerScope.implementationPlatform(
31 | artifact: MinimalExternalModuleDependency,
32 | ) {
33 | add("implementation", platform(artifact))
34 | }
35 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/dsl/KotlinGradleDsl.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.dsl
2 |
3 | import com.android.build.gradle.TestedExtension
4 | import org.gradle.api.artifacts.MinimalExternalModuleDependency
5 | import org.gradle.api.plugins.ExtensionAware
6 | import org.gradle.kotlin.dsl.DependencyHandlerScope
7 | import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
8 |
9 | fun TestedExtension.kotlinOptions(block: KotlinJvmOptions.() -> Unit) {
10 | (this as ExtensionAware).extensions.configure("kotlinOptions", block)
11 | }
12 |
13 | fun DependencyHandlerScope.ksp(
14 | artifact: MinimalExternalModuleDependency,
15 | ) {
16 | add("ksp", artifact)
17 | }
18 |
19 | fun DependencyHandlerScope.kaptTest(
20 | artifact: MinimalExternalModuleDependency,
21 | ) {
22 | add("kaptTest", artifact)
23 | }
24 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/dsl/VersionCatalogDsl.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.dsl
2 |
3 | import org.gradle.api.Project
4 | import org.gradle.api.artifacts.ExternalModuleDependencyBundle
5 | import org.gradle.api.artifacts.MinimalExternalModuleDependency
6 | import org.gradle.api.artifacts.VersionCatalog
7 | import org.gradle.api.artifacts.VersionCatalogsExtension
8 | import org.gradle.kotlin.dsl.getByType
9 | import org.gradle.plugin.use.PluginDependency
10 |
11 | internal val Project.libs: VersionCatalog
12 | get() = extensions.getByType().named("libs")
13 |
14 | internal fun VersionCatalog.version(name: String): String {
15 | return findVersion(name).get().requiredVersion
16 | }
17 |
18 | internal fun VersionCatalog.library(name: String): MinimalExternalModuleDependency {
19 | return findLibrary(name).get().get()
20 | }
21 |
22 | internal fun VersionCatalog.plugin(name: String): PluginDependency {
23 | return findPlugin(name).get().get()
24 | }
25 |
26 | internal fun VersionCatalog.bundle(name: String): ExternalModuleDependencyBundle {
27 | return findBundle(name).get().get()
28 | }
29 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/AndroidApplicationPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.androidApplication
4 | import com.conf.mad.todo.dsl.setupAndroid
5 | import org.gradle.api.Plugin
6 | import org.gradle.api.Project
7 |
8 | @Suppress("unused")
9 | class AndroidApplicationPlugin : Plugin {
10 | override fun apply(target: Project) {
11 | with(target) {
12 | with(pluginManager) {
13 | apply("com.android.application")
14 | }
15 |
16 | androidApplication {
17 | setupAndroid()
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/AndroidComposePlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.debugImplementation
4 | import com.conf.mad.todo.dsl.implementation
5 | import com.conf.mad.todo.dsl.implementationPlatform
6 | import com.conf.mad.todo.dsl.library
7 | import com.conf.mad.todo.dsl.libs
8 | import org.gradle.api.Plugin
9 | import org.gradle.api.Project
10 | import org.gradle.kotlin.dsl.dependencies
11 | import org.gradle.kotlin.dsl.getByType
12 | import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension
13 | import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
14 |
15 | @Suppress("unused")
16 | class AndroidComposePlugin : Plugin {
17 | override fun apply(target: Project) {
18 | with(target) {
19 | with(pluginManager) {
20 | apply("org.jetbrains.kotlin.plugin.compose")
21 | }
22 |
23 | val projectPath = rootProject.file(".").absolutePath
24 |
25 | extensions.getByType().apply {
26 | compilerOptions {
27 | freeCompilerArgs.set(
28 | freeCompilerArgs.getOrElse(emptyList()) + listOf(
29 | "-P",
30 | "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$projectPath/report/compose-metrics"
31 | ) + listOf(
32 | "-P",
33 | "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$projectPath/report/compose-reports"
34 | )
35 | )
36 | }
37 | }
38 |
39 | extensions.getByType().apply {
40 | enableStrongSkippingMode.set(true)
41 | includeSourceInformation.set(true)
42 | }
43 |
44 | dependencies {
45 | implementation(libs.library("androidx-core"))
46 | implementationPlatform(libs.library("androidx-compose-bom"))
47 | implementation(libs.library("androidx-compose-activity"))
48 | implementation(libs.library("androidx-compose-hilt-navigation"))
49 | implementation(libs.library("androidx-compose-lifecycle"))
50 | implementation(libs.library("androidx-compose-navigation"))
51 | implementation(libs.library("androidx-compose-ui"))
52 | implementation(libs.library("androidx-compose-ui-foundation"))
53 | implementation(libs.library("androidx-compose-material3"))
54 | implementation(libs.library("androidx-lifecycle-runtime"))
55 | implementation(libs.library("androidx-compose-ui-tooling"))
56 | debugImplementation(libs.library("androidx-compose-ui-test-manifest"))
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/AndroidHiltPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.android
4 | import com.conf.mad.todo.dsl.implementation
5 | import com.conf.mad.todo.dsl.ksp
6 | import com.conf.mad.todo.dsl.library
7 | import com.conf.mad.todo.dsl.libs
8 | import org.gradle.api.Plugin
9 | import org.gradle.api.Project
10 | import org.gradle.kotlin.dsl.dependencies
11 |
12 | @Suppress("unused")
13 | class AndroidHiltPlugin : Plugin {
14 | override fun apply(target: Project) {
15 | with(target) {
16 | with(pluginManager) {
17 | apply("com.google.devtools.ksp")
18 | apply("dagger.hilt.android.plugin")
19 | }
20 |
21 | android {
22 | packagingOptions {
23 | resources {
24 | excludes += "META-INF/gradle/incremental.annotation.processors"
25 | }
26 | }
27 | }
28 | dependencies {
29 | implementation(libs.library("hilt"))
30 | ksp(libs.library("hilt-compiler"))
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/AndroidKotlinPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.implementation
4 | import com.conf.mad.todo.dsl.library
5 | import com.conf.mad.todo.dsl.libs
6 | import org.gradle.api.Plugin
7 | import org.gradle.api.Project
8 | import org.gradle.kotlin.dsl.dependencies
9 | import org.gradle.kotlin.dsl.getByType
10 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget
11 | import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
12 |
13 | @Suppress("unused")
14 | class AndroidKotlinPlugin : Plugin {
15 | override fun apply(target: Project) {
16 | with(target) {
17 | with(pluginManager) {
18 | apply("org.jetbrains.kotlin.android")
19 | }
20 |
21 | extensions.getByType().apply {
22 | compilerOptions {
23 | jvmTarget.set(JvmTarget.JVM_17)
24 |
25 | freeCompilerArgs.set(
26 | freeCompilerArgs.getOrElse(emptyList()) + listOf(
27 | "-opt-in=kotlin.RequiresOptIn",
28 | "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
29 | "-Xcontext-receivers"
30 | )
31 | )
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation(libs.library("kotlinx-coroutines-core"))
37 | implementation(libs.library("kotlinx-collections-immutable"))
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/AndroidPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.androidLibrary
4 | import com.conf.mad.todo.dsl.setupAndroid
5 | import org.gradle.api.Plugin
6 | import org.gradle.api.Project
7 |
8 | @Suppress("unused")
9 | class AndroidPlugin : Plugin {
10 | override fun apply(target: Project) {
11 | with(target) {
12 | with(pluginManager) {
13 | apply("com.android.library")
14 | }
15 |
16 | androidLibrary {
17 | setupAndroid()
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/AndroidRoomPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.android
4 | import com.conf.mad.todo.dsl.implementation
5 | import com.conf.mad.todo.dsl.ksp
6 | import com.conf.mad.todo.dsl.library
7 | import com.conf.mad.todo.dsl.libs
8 | import org.gradle.api.Plugin
9 | import org.gradle.api.Project
10 | import org.gradle.kotlin.dsl.dependencies
11 |
12 | class AndroidRoomPlugin : Plugin {
13 | override fun apply(target: Project) {
14 | with(target) {
15 | with(pluginManager) {
16 | apply("com.google.devtools.ksp")
17 | }
18 | android {
19 | defaultConfig {
20 | javaCompileOptions {
21 | annotationProcessorOptions {
22 | arguments += mapOf(
23 | "room.schemaLocation" to "$projectDir/schemas",
24 | "room.incremental" to "true"
25 | )
26 | }
27 | }
28 | }
29 | dependencies {
30 | implementation(libs.library("androidx-room"))
31 | ksp(libs.library("androidx-room-compiler"))
32 | implementation(libs.library("androidx-room-ktx"))
33 | }
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/build-logic/src/main/kotlin/com/conf/mad/todo/primitive/KotlinSerializationPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.conf.mad.todo.primitive
2 |
3 | import com.conf.mad.todo.dsl.implementation
4 | import com.conf.mad.todo.dsl.library
5 | import com.conf.mad.todo.dsl.libs
6 | import org.gradle.api.Plugin
7 | import org.gradle.api.Project
8 | import org.gradle.kotlin.dsl.dependencies
9 |
10 | @Suppress("unused")
11 | class KotlinSerializationPlugin : Plugin {
12 | override fun apply(target: Project) {
13 | with(target) {
14 | with(pluginManager) {
15 | apply("org.jetbrains.kotlin.plugin.serialization")
16 | }
17 | dependencies {
18 | implementation(libs.library("kotlinx-serialization-json"))
19 | }
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import com.diffplug.gradle.spotless.SpotlessExtension
2 |
3 | plugins {
4 | alias(libs.plugins.android.application) apply false
5 | alias(libs.plugins.android.library) apply false
6 | alias(libs.plugins.kotlinx.serialization) apply false
7 | alias(libs.plugins.kotlin.android) apply false
8 | alias(libs.plugins.dagger.hilt) apply false
9 | alias(libs.plugins.ksp) apply false
10 | alias(libs.plugins.junit5) apply false
11 | alias(libs.plugins.kotlin.jvm) apply false
12 | alias(libs.plugins.spotless)
13 | alias(libs.plugins.kotlin.compose.compiler) apply false
14 | }
15 |
16 | subprojects {
17 | apply(
18 | plugin =
19 | rootProject.libs.plugins.spotless
20 | .get()
21 | .pluginId,
22 | )
23 | extensions.configure {
24 | kotlin {
25 | target("**/*.kt")
26 | targetExclude("${layout.buildDirectory}/**/*.kt")
27 | ktlint()
28 | .setEditorConfigPath("${project.rootDir}/spotless/.editorconfig")
29 | licenseHeaderFile(rootProject.file("spotless/spotless.license.kt"))
30 | trimTrailingWhitespace()
31 | endWithNewline()
32 | }
33 | format("kts") {
34 | target("**/*.kts")
35 | targetExclude("${project.rootDir}/**/*.kts")
36 | licenseHeaderFile(
37 | rootProject.file("spotless/spotless.license.kt"),
38 | "(^(?![\\/ ]\\*).*$)",
39 | )
40 | }
41 | format("xml") {
42 | target("**/*.xml")
43 | targetExclude("**/build/**/*.xml")
44 | licenseHeaderFile(rootProject.file("spotless/spotless.license.xml"), "(<[^!?])")
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/core/common/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/common/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.primitive.android")
25 | id("conf.mad.primitive.android.kotlin")
26 | id("conf.mad.primitive.android.hilt")
27 | }
28 |
29 | android {
30 | namespace = "com.conf.mad.todo.common"
31 |
32 | defaultConfig {
33 | consumerProguardFiles("consumer-rules.pro")
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/core/common/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/common/consumer-rules.pro
--------------------------------------------------------------------------------
/core/common/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
--------------------------------------------------------------------------------
/core/common/src/main/java/com/conf/mad/todo/common/TodoDispatchers.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.common
24 |
25 | import javax.inject.Qualifier
26 |
27 | @Qualifier
28 | @Retention(AnnotationRetention.RUNTIME)
29 | annotation class Dispatcher(val dispatcherType: DispatcherType)
30 |
31 | enum class DispatcherType {
32 | DEFAULT,
33 | IO
34 | }
35 |
--------------------------------------------------------------------------------
/core/common/src/main/java/com/conf/mad/todo/common/di/DispatchersModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.common.di
24 |
25 | import com.conf.mad.todo.common.Dispatcher
26 | import com.conf.mad.todo.common.DispatcherType
27 | import dagger.Module
28 | import dagger.Provides
29 | import dagger.hilt.InstallIn
30 | import dagger.hilt.components.SingletonComponent
31 | import kotlinx.coroutines.CoroutineDispatcher
32 | import kotlinx.coroutines.Dispatchers
33 |
34 | @Module
35 | @InstallIn(SingletonComponent::class)
36 | object DispatchersModule {
37 | @Provides
38 | @Dispatcher(DispatcherType.IO)
39 | fun providesIODispatcher(): CoroutineDispatcher = Dispatchers.IO
40 |
41 | @Provides
42 | @Dispatcher(DispatcherType.DEFAULT)
43 | fun providesDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default
44 | }
45 |
--------------------------------------------------------------------------------
/core/database/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/database/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.android.feature")
25 | id("conf.mad.primitive.android.room")
26 | }
27 |
28 | android {
29 | namespace = "com.conf.mad.todo.database"
30 |
31 | defaultConfig {
32 | ksp {
33 | arg("room.schemaLocation", "$projectDir/schemas")
34 | }
35 | consumerProguardFiles("consumer-rules.pro")
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/core/database/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/database/consumer-rules.pro
--------------------------------------------------------------------------------
/core/database/schemas/com.conf.mad.todo.database.TodoDatabase/1.json:
--------------------------------------------------------------------------------
1 | {
2 | "formatVersion": 1,
3 | "database": {
4 | "version": 1,
5 | "identityHash": "14c98d2441e8d6c0dbce69d9758bcb88",
6 | "entities": [
7 | {
8 | "tableName": "TaskEntity",
9 | "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER, `title` TEXT NOT NULL, `description` TEXT NOT NULL, `is_completed` INTEGER NOT NULL, `is_favorite` INTEGER NOT NULL, PRIMARY KEY(`id`))",
10 | "fields": [
11 | {
12 | "fieldPath": "id",
13 | "columnName": "id",
14 | "affinity": "INTEGER",
15 | "notNull": false
16 | },
17 | {
18 | "fieldPath": "title",
19 | "columnName": "title",
20 | "affinity": "TEXT",
21 | "notNull": true
22 | },
23 | {
24 | "fieldPath": "description",
25 | "columnName": "description",
26 | "affinity": "TEXT",
27 | "notNull": true
28 | },
29 | {
30 | "fieldPath": "isCompleted",
31 | "columnName": "is_completed",
32 | "affinity": "INTEGER",
33 | "notNull": true
34 | },
35 | {
36 | "fieldPath": "isFavorite",
37 | "columnName": "is_favorite",
38 | "affinity": "INTEGER",
39 | "notNull": true
40 | }
41 | ],
42 | "primaryKey": {
43 | "autoGenerate": false,
44 | "columnNames": [
45 | "id"
46 | ]
47 | },
48 | "indices": [],
49 | "foreignKeys": []
50 | }
51 | ],
52 | "views": [],
53 | "setupQueries": [
54 | "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
55 | "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '14c98d2441e8d6c0dbce69d9758bcb88')"
56 | ]
57 | }
58 | }
--------------------------------------------------------------------------------
/core/database/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/conf/mad/todo/database/TaskDao.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.database
24 |
25 | import androidx.room.Dao
26 | import androidx.room.Delete
27 | import androidx.room.Insert
28 | import androidx.room.OnConflictStrategy
29 | import androidx.room.Query
30 | import com.conf.mad.todo.database.entity.TaskEntity
31 | import kotlinx.coroutines.flow.Flow
32 |
33 | @Dao
34 | interface TaskDao {
35 | @Insert(onConflict = OnConflictStrategy.REPLACE)
36 | suspend fun insertTask(task: TaskEntity)
37 |
38 | /**
39 | * Get tasks by isCompleted is false
40 | */
41 | @Query("SELECT * FROM TaskEntity WHERE is_completed = 0")
42 | fun getTodoTasks(): Flow>
43 |
44 | /**
45 | * Get tasks by isCompleted is true
46 | */
47 | @Query("SELECT * FROM TaskEntity WHERE is_completed = 1")
48 | fun getCompletedTasks(): Flow>
49 |
50 | @Delete
51 | suspend fun deleteTask(task: TaskEntity)
52 |
53 | /**
54 | * Updating only isFavorite
55 | * By id
56 | */
57 | @Query("UPDATE TaskEntity SET is_favorite = :isFavorite WHERE id = :id")
58 | suspend fun updateFavorite(id: Long, isFavorite: Boolean)
59 |
60 | /**
61 | * Updating only isCompleted
62 | * By id
63 | */
64 | @Query("UPDATE TaskEntity SET is_completed = :isCompleted WHERE id = :id")
65 | suspend fun updateCompleted(id: Long, isCompleted: Boolean)
66 | }
67 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/conf/mad/todo/database/TodoDatabase.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.database
24 |
25 | import androidx.room.Database
26 | import androidx.room.RoomDatabase
27 | import com.conf.mad.todo.database.entity.TaskEntity
28 |
29 | @Database(entities = [TaskEntity::class], version = 1, exportSchema = true)
30 | abstract class TodoDatabase : RoomDatabase() {
31 | abstract fun taskDao(): TaskDao
32 | }
33 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/conf/mad/todo/database/di/DatabaseModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.database.di
24 |
25 | import android.content.Context
26 | import androidx.room.Room
27 | import com.conf.mad.todo.database.TaskDao
28 | import com.conf.mad.todo.database.TodoDatabase
29 | import dagger.Module
30 | import dagger.Provides
31 | import dagger.hilt.InstallIn
32 | import dagger.hilt.android.qualifiers.ApplicationContext
33 | import dagger.hilt.components.SingletonComponent
34 | import javax.inject.Singleton
35 |
36 | @Module
37 | @InstallIn(SingletonComponent::class)
38 | object DatabaseModule {
39 | @Provides
40 | @Singleton
41 | fun provideTodoDatabase(@ApplicationContext context: Context): TodoDatabase = Room.databaseBuilder(context, TodoDatabase::class.java, "todo.db")
42 | .fallbackToDestructiveMigration(false)
43 | .build()
44 |
45 | @Provides
46 | @Singleton
47 | fun provideTaskDao(todoDatabase: TodoDatabase): TaskDao = todoDatabase.taskDao()
48 | }
49 |
--------------------------------------------------------------------------------
/core/database/src/main/java/com/conf/mad/todo/database/entity/TaskEntity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.database.entity
24 |
25 | import androidx.room.ColumnInfo
26 | import androidx.room.Entity
27 | import androidx.room.PrimaryKey
28 |
29 | @Entity
30 | data class TaskEntity(
31 | @PrimaryKey
32 | val id: Long? = null,
33 | val title: String,
34 | val description: String = "",
35 | @ColumnInfo("is_completed") val isCompleted: Boolean = false,
36 | @ColumnInfo("is_favorite") val isFavorite: Boolean = false
37 | )
38 |
--------------------------------------------------------------------------------
/core/designsystem/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/designsystem/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.android.feature")
25 | }
26 |
27 | android {
28 | namespace = "com.conf.mad.todo.designsystem"
29 | defaultConfig {
30 | consumerProguardFiles("consumer-rules.pro")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/core/designsystem/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/designsystem/consumer-rules.pro
--------------------------------------------------------------------------------
/core/designsystem/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/java/com/conf/mad/todo/designsystem/Color.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.designsystem
24 |
25 | import androidx.compose.ui.graphics.Color
26 |
27 | // Red Scale
28 | val Red = Color(0xFFFF3434)
29 | val Pink = Color(0xFFFFD2D2)
30 |
31 | // Blue Scale
32 | val Blue = Color(0xFF5182FF)
33 | val SkyBlue = Color(0xFFE2EFFF)
34 | val LightBlue = Color(0xFFF8FBFF)
35 | val AshBlue = Color(0xFFC9DBF0)
36 |
37 | // Gray Scale
38 | val Black = Color(0xFF000000)
39 | val Snow = Color(0xFFFFFFFF)
40 | val GrayGugu = Color(0xFF999999)
41 | val GrayAbby = Color(0xFFABABAB)
42 | val GrayCeci = Color(0xFFCCCCCC)
43 | val GrayEunbi = Color(0xFFEBEBEB)
44 | val GrayFry = Color(0xFFF6F6F6)
45 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/java/com/conf/mad/todo/designsystem/Type.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.designsystem
24 |
25 | import androidx.compose.runtime.Composable
26 | import androidx.compose.runtime.Stable
27 | import androidx.compose.runtime.getValue
28 | import androidx.compose.runtime.mutableStateOf
29 | import androidx.compose.runtime.setValue
30 | import androidx.compose.ui.text.TextStyle
31 | import androidx.compose.ui.text.font.Font
32 | import androidx.compose.ui.text.font.FontFamily
33 | import androidx.compose.ui.text.font.FontWeight
34 | import androidx.compose.ui.unit.sp
35 |
36 | val StretchPro = FontFamily(Font(R.font.stretch_pro, FontWeight.Bold))
37 | val PretendardMedium = FontFamily(Font(R.font.pretendard_medium, FontWeight.Medium))
38 | val PretendardRegular = FontFamily(Font(R.font.pretendard_regular, FontWeight.Normal))
39 | val PretendardSemiBold = FontFamily(Font(R.font.pretendard_semibold, FontWeight.SemiBold))
40 |
41 | @Stable
42 | class TodoTypography(
43 | title: TextStyle,
44 | semiBold: TextStyle,
45 | medium1: TextStyle,
46 | medium2: TextStyle,
47 | regular1: TextStyle,
48 | regular2: TextStyle
49 | ) {
50 | var title: TextStyle by mutableStateOf(title)
51 | private set
52 | var semiBold: TextStyle by mutableStateOf(semiBold)
53 | private set
54 | var medium1: TextStyle by mutableStateOf(medium1)
55 | private set
56 | var medium2: TextStyle by mutableStateOf(medium2)
57 | private set
58 | var regular1: TextStyle by mutableStateOf(regular1)
59 | private set
60 | var regular2: TextStyle by mutableStateOf(regular2)
61 | private set
62 |
63 | fun update(other: TodoTypography) {
64 | title = other.title
65 | semiBold = other.semiBold
66 | medium1 = other.medium1
67 | medium2 = other.medium2
68 | regular1 = other.regular1
69 | regular2 = other.regular2
70 | }
71 |
72 | fun copy(
73 | title: TextStyle = this.title,
74 | semiBold: TextStyle = this.semiBold,
75 | medium1: TextStyle = this.medium1,
76 | medium2: TextStyle = this.medium2,
77 | regular1: TextStyle = this.regular1,
78 | regular2: TextStyle = this.regular2
79 | ): TodoTypography = TodoTypography(title, semiBold, medium1, medium2, regular1, regular2)
80 | }
81 |
82 | @Composable
83 | fun TodoTypography(): TodoTypography {
84 | return TodoTypography(
85 | title = TextStyle(
86 | fontFamily = StretchPro,
87 | fontSize = 24.sp,
88 | lineHeight = 14.sp,
89 | fontWeight = FontWeight.Bold,
90 | letterSpacing = (-0.5).sp
91 | ),
92 | semiBold = TextStyle(
93 | fontFamily = PretendardSemiBold,
94 | fontSize = 16.sp,
95 | lineHeight = 14.sp,
96 | fontWeight = FontWeight.SemiBold,
97 | letterSpacing = (-0.5).sp
98 | ),
99 | medium1 = TextStyle(
100 | fontFamily = PretendardMedium,
101 | fontSize = 16.sp,
102 | lineHeight = 24.sp,
103 | fontWeight = FontWeight.Medium,
104 | letterSpacing = (-0.5).sp
105 | ),
106 | medium2 = TextStyle(
107 | fontFamily = PretendardMedium,
108 | fontSize = 13.sp,
109 | lineHeight = 14.sp,
110 | fontWeight = FontWeight.Medium,
111 | letterSpacing = (-0.5).sp
112 | ),
113 | regular1 = TextStyle(
114 | fontFamily = PretendardRegular,
115 | fontSize = 16.sp,
116 | lineHeight = 24.sp,
117 | fontWeight = FontWeight.Normal,
118 | letterSpacing = (-0.5).sp
119 | ),
120 | regular2 = TextStyle(
121 | fontFamily = PretendardRegular,
122 | fontSize = 12.sp,
123 | lineHeight = 14.sp,
124 | fontWeight = FontWeight.Normal
125 | )
126 | )
127 | }
128 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/java/com/conf/mad/todo/designsystem/preview/ComponentPreview.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.designsystem.preview
24 |
25 | import androidx.compose.ui.tooling.preview.Preview
26 |
27 | @Preview(showBackground = true)
28 | annotation class ComponentPreview
29 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/java/com/conf/mad/todo/designsystem/preview/DevicePreview.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.designsystem.preview
24 |
25 | import androidx.compose.ui.tooling.preview.Preview
26 |
27 | @Preview(
28 | name = "Galaxy S23 Ultra",
29 | showBackground = true,
30 | device = "spec:width=360dp,height=772dp,dpi=411"
31 | )
32 | @Preview(
33 | name = "Galaxy S23",
34 | showBackground = true,
35 | device = "spec:width=360dp,height=800dp,dpi=500"
36 | )
37 | annotation class DevicePreview
38 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/drawable/ic_add_task.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/drawable/ic_clear.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
39 |
45 |
46 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/drawable/ic_star_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/drawable/ic_star_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/drawable/ic_title_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/font/pretendard_medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/designsystem/src/main/res/font/pretendard_medium.otf
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/font/pretendard_regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/designsystem/src/main/res/font/pretendard_regular.otf
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/font/pretendard_semibold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/designsystem/src/main/res/font/pretendard_semibold.otf
--------------------------------------------------------------------------------
/core/designsystem/src/main/res/font/stretch_pro.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/designsystem/src/main/res/font/stretch_pro.otf
--------------------------------------------------------------------------------
/core/ui/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/core/ui/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.android.feature")
25 | }
26 |
27 | android {
28 | namespace = "com.conf.mad.todo.ui"
29 |
30 | defaultConfig {
31 | consumerProguardFiles("consumer-rules.pro")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/core/ui/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/core/ui/consumer-rules.pro
--------------------------------------------------------------------------------
/core/ui/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
--------------------------------------------------------------------------------
/core/ui/src/main/java/com/conf/mad/todo/ui/Clickable.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.ui
24 |
25 | import androidx.compose.foundation.clickable
26 | import androidx.compose.foundation.interaction.MutableInteractionSource
27 | import androidx.compose.runtime.Composable
28 | import androidx.compose.runtime.remember
29 | import androidx.compose.ui.Modifier
30 |
31 | @Composable
32 | inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit): Modifier = then(
33 | clickable(
34 | indication = null,
35 | interactionSource = remember { MutableInteractionSource() }
36 | ) {
37 | onClick()
38 | }
39 | )
40 |
--------------------------------------------------------------------------------
/data/task/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/data/task/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.android.feature")
25 | }
26 |
27 | android {
28 | namespace = "com.conf.mad.todo.data.task"
29 |
30 | defaultConfig {
31 | consumerProguardFiles("consumer-rules.pro")
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation(projects.core.common)
37 | implementation(projects.core.database)
38 | implementation(projects.domain.task)
39 | }
40 |
--------------------------------------------------------------------------------
/data/task/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/data/task/consumer-rules.pro
--------------------------------------------------------------------------------
/data/task/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
--------------------------------------------------------------------------------
/data/task/src/main/java/com/conf/mad/todo/data/task/di/TaskModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.data.task.di
24 |
25 | import com.conf.mad.todo.data.task.repository.DefaultTaskRepository
26 | import com.conf.mad.todo.task.repository.TaskRepository
27 | import dagger.Binds
28 | import dagger.Module
29 | import dagger.hilt.InstallIn
30 | import dagger.hilt.components.SingletonComponent
31 | import javax.inject.Singleton
32 |
33 | @Module
34 | @InstallIn(SingletonComponent::class)
35 | interface TaskModule {
36 | @Binds
37 | @Singleton
38 | fun bindTaskLocalDataSource(source: DefaultTaskRepository): TaskRepository
39 | }
40 |
--------------------------------------------------------------------------------
/data/task/src/main/java/com/conf/mad/todo/data/task/mapper/Task.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.data.task.mapper
24 |
25 | import com.conf.mad.todo.database.entity.TaskEntity
26 | import com.conf.mad.todo.task.model.Task
27 |
28 | fun TaskEntity.asDomain(): Task = Task(
29 | id = id,
30 | title = title,
31 | description = description,
32 | isCompleted = isCompleted,
33 | isFavorite = isFavorite
34 | )
35 |
36 | fun List.asDomain(): List = map { it.asDomain() }
37 |
38 | fun Task.toEntity(): TaskEntity = TaskEntity(
39 | id = id,
40 | title = title,
41 | isCompleted = isCompleted,
42 | isFavorite = isFavorite
43 | )
44 |
--------------------------------------------------------------------------------
/data/task/src/main/java/com/conf/mad/todo/data/task/repository/DefaultTaskRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.data.task.repository
24 |
25 | import com.conf.mad.todo.common.Dispatcher
26 | import com.conf.mad.todo.common.DispatcherType.DEFAULT
27 | import com.conf.mad.todo.data.task.mapper.asDomain
28 | import com.conf.mad.todo.data.task.mapper.toEntity
29 | import com.conf.mad.todo.database.TaskDao
30 | import com.conf.mad.todo.task.model.Task
31 | import com.conf.mad.todo.task.repository.TaskRepository
32 | import javax.inject.Inject
33 | import kotlinx.coroutines.CoroutineDispatcher
34 | import kotlinx.coroutines.flow.Flow
35 | import kotlinx.coroutines.flow.map
36 | import kotlinx.coroutines.withContext
37 |
38 | class DefaultTaskRepository @Inject constructor(
39 | private val taskDao: TaskDao,
40 | @Dispatcher(DEFAULT) private val dispatcher: CoroutineDispatcher
41 | ) : TaskRepository {
42 | override fun getTodoTasks(): Flow> {
43 | return taskDao.getTodoTasks().map {
44 | withContext(dispatcher) {
45 | it.asDomain()
46 | }
47 | }
48 | }
49 |
50 | override fun getCompletedTasks(): Flow> {
51 | return taskDao.getCompletedTasks().map {
52 | withContext(dispatcher) {
53 | it.asDomain()
54 | }
55 | }
56 | }
57 |
58 | override suspend fun insertTask(task: Task) {
59 | taskDao.insertTask(task.toEntity())
60 | }
61 |
62 | override suspend fun deleteTask(task: Task) {
63 | taskDao.deleteTask(task.toEntity())
64 | }
65 |
66 | override suspend fun updateFavorite(id: Long, isFavorite: Boolean) {
67 | taskDao.updateFavorite(id, isFavorite)
68 | }
69 |
70 | override suspend fun updateCompleted(id: Long, isCompleted: Boolean) {
71 | taskDao.updateCompleted(id, isCompleted)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/domain/task/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/domain/task/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.kotlin")
25 | }
26 |
--------------------------------------------------------------------------------
/domain/task/src/main/java/com/conf/mad/todo/task/model/Task.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.task.model
24 |
25 | data class Task(
26 | val id: Long? = null,
27 | val title: String,
28 | val description: String,
29 | val isCompleted: Boolean = false,
30 | val isFavorite: Boolean
31 | ) {
32 | companion object {
33 | const val UNDEFINED_ID = -1L
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/domain/task/src/main/java/com/conf/mad/todo/task/repository/TaskRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.task.repository
24 |
25 | import com.conf.mad.todo.task.model.Task
26 | import kotlinx.coroutines.flow.Flow
27 |
28 | interface TaskRepository {
29 | fun getTodoTasks(): Flow>
30 | fun getCompletedTasks(): Flow>
31 | suspend fun insertTask(task: Task)
32 | suspend fun deleteTask(task: Task)
33 | suspend fun updateFavorite(id: Long, isFavorite: Boolean)
34 | suspend fun updateCompleted(id: Long, isCompleted: Boolean)
35 | }
36 |
--------------------------------------------------------------------------------
/feature/home/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/feature/home/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.android.feature")
25 | }
26 |
27 | android {
28 | namespace = "com.conf.mad.todo.home"
29 |
30 | defaultConfig {
31 | consumerProguardFiles("consumer-rules.pro")
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation(projects.core.designsystem)
37 | implementation(projects.core.ui)
38 | implementation(projects.domain.task)
39 | }
40 |
--------------------------------------------------------------------------------
/feature/home/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/feature/home/consumer-rules.pro
--------------------------------------------------------------------------------
/feature/home/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/HomeViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home
24 |
25 | import androidx.lifecycle.ViewModel
26 | import androidx.lifecycle.viewModelScope
27 | import com.conf.mad.todo.home.model.HomeMenu
28 | import com.conf.mad.todo.home.model.HomeUiState
29 | import com.conf.mad.todo.home.model.TaskStatus
30 | import com.conf.mad.todo.home.model.TaskUiModel
31 | import com.conf.mad.todo.task.repository.TaskRepository
32 | import dagger.hilt.android.lifecycle.HiltViewModel
33 | import javax.inject.Inject
34 | import kotlinx.collections.immutable.toPersistentList
35 | import kotlinx.coroutines.delay
36 | import kotlinx.coroutines.flow.MutableStateFlow
37 | import kotlinx.coroutines.flow.asStateFlow
38 | import kotlinx.coroutines.flow.combine
39 | import kotlinx.coroutines.flow.update
40 | import kotlinx.coroutines.launch
41 |
42 | @HiltViewModel
43 | class HomeViewModel @Inject constructor(
44 | private val repository: TaskRepository
45 | ) : ViewModel() {
46 | private val _uiState = MutableStateFlow(HomeUiState())
47 | val uiState = _uiState.asStateFlow()
48 |
49 | init {
50 | viewModelScope.launch {
51 | combine(
52 | repository.getTodoTasks(),
53 | repository.getCompletedTasks(),
54 | uiState
55 | ) { todoTasks, completedTasks, uiState ->
56 | Triple(todoTasks, completedTasks, uiState)
57 | }.collect { (todos, completed, uiState) ->
58 | _uiState.update {
59 | it.copy(
60 | todoTasks = todos.filter { task ->
61 | if (!uiState.isOnlyFavoriteTaskVisible) {
62 | return@filter true
63 | }
64 | task.isFavorite
65 | }.map(TaskUiModel::of).map { task ->
66 | if (it.doneTasks.find { doneTask -> doneTask.id == task.id } != null) {
67 | task.copy(status = TaskStatus.DONE)
68 | } else {
69 | task
70 | }
71 | }.toPersistentList(),
72 | completedTasks = completed.filter { task ->
73 | if (!uiState.isOnlyFavoriteTaskVisible) {
74 | return@filter true
75 | }
76 | task.isFavorite
77 | }.map(TaskUiModel::of).toPersistentList()
78 | )
79 | }
80 | }
81 | }
82 | }
83 |
84 | fun onToggleCompletedTaskVisibility() {
85 | _uiState.update {
86 | it.copy(isCompletedTaskVisible = !it.isCompletedTaskVisible)
87 | }
88 | }
89 |
90 | fun onTaskChanged(item: HomeMenu) {
91 | _uiState.update {
92 | it.copy(currentDestination = item)
93 | }
94 | }
95 |
96 | fun onFavoriteChanged(id: Long, isFavorite: Boolean) {
97 | viewModelScope.launch {
98 | repository.updateFavorite(id, isFavorite)
99 | }
100 | }
101 |
102 | fun onCompletedChanged(id: Long, isCompleted: Boolean) {
103 | if (isCompleted) {
104 | _uiState.update {
105 | val task = it.todoTasks.find { task -> task.id == id } ?: return@update it
106 | it.copy(
107 | doneTasks = (it.doneTasks + task).toPersistentList()
108 | )
109 | }
110 | }
111 | viewModelScope.launch {
112 | if (isCompleted) {
113 | delay(500)
114 | }
115 | repository.updateCompleted(id, isCompleted)
116 | _uiState.update {
117 | it.copy(
118 | doneTasks = it.doneTasks.filter { task -> task.id != id }.toPersistentList()
119 | )
120 | }
121 | }
122 | }
123 |
124 | fun onSelectTaskToDelete(task: TaskUiModel) {
125 | _uiState.update {
126 | it.copy(taskToDelete = task)
127 | }
128 | }
129 |
130 | fun onDeleteTask() {
131 | viewModelScope.launch {
132 | val task = uiState.value.taskToDelete ?: return@launch
133 | repository.deleteTask(task.asDomain())
134 | _uiState.update {
135 | it.copy(taskToDelete = null)
136 | }
137 | }
138 | }
139 |
140 | fun onDismissDeleteDialog() {
141 | _uiState.update {
142 | it.copy(taskToDelete = null)
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/component/CompletedTaskVisibilityToggleButton.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.component
24 |
25 | import androidx.compose.foundation.background
26 | import androidx.compose.foundation.layout.padding
27 | import androidx.compose.foundation.layout.width
28 | import androidx.compose.foundation.shape.RoundedCornerShape
29 | import androidx.compose.material3.Text
30 | import androidx.compose.runtime.Composable
31 | import androidx.compose.runtime.getValue
32 | import androidx.compose.runtime.mutableStateOf
33 | import androidx.compose.runtime.remember
34 | import androidx.compose.runtime.setValue
35 | import androidx.compose.ui.Modifier
36 | import androidx.compose.ui.text.style.TextAlign
37 | import androidx.compose.ui.unit.dp
38 | import com.conf.mad.todo.designsystem.TodoTheme
39 | import com.conf.mad.todo.designsystem.preview.ComponentPreview
40 | import com.conf.mad.todo.ui.noRippleClickable
41 |
42 | @Composable
43 | internal fun CompletedTaskVisibilityToggleButton(isVisible: Boolean, onToggle: () -> Unit) {
44 | Text(
45 | text = if (isVisible) {
46 | "완료 숨기기"
47 | } else {
48 | "완료 보기"
49 | },
50 | style = TodoTheme.typography.medium2,
51 | color = TodoTheme.colors.onSurfaceContainerHigh,
52 | modifier = Modifier
53 | .background(
54 | color = if (isVisible) {
55 | TodoTheme.colors.surfaceContainerHigh
56 | } else {
57 | TodoTheme.colors.primary
58 | },
59 | shape = RoundedCornerShape(4.dp)
60 | )
61 | .noRippleClickable(onClick = onToggle)
62 | .width(77.dp)
63 | .padding(vertical = 8.dp),
64 | textAlign = TextAlign.Center
65 | )
66 | }
67 |
68 | @ComponentPreview
69 | @Composable
70 | private fun CompletedTaskVisibilityToggleButtonPreview() {
71 | var isVisible by remember {
72 | mutableStateOf(true)
73 | }
74 | TodoTheme {
75 | CompletedTaskVisibilityToggleButton(
76 | isVisible = isVisible,
77 | onToggle = { isVisible = !isVisible }
78 | )
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/component/DeleteTaskDialog.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.component
24 |
25 | import androidx.compose.foundation.layout.Arrangement
26 | import androidx.compose.foundation.layout.Column
27 | import androidx.compose.foundation.layout.Row
28 | import androidx.compose.foundation.layout.Spacer
29 | import androidx.compose.foundation.layout.fillMaxSize
30 | import androidx.compose.foundation.layout.fillMaxWidth
31 | import androidx.compose.foundation.layout.height
32 | import androidx.compose.foundation.layout.padding
33 | import androidx.compose.foundation.layout.width
34 | import androidx.compose.foundation.shape.RoundedCornerShape
35 | import androidx.compose.material3.Card
36 | import androidx.compose.material3.CardDefaults
37 | import androidx.compose.material3.Text
38 | import androidx.compose.material3.TextButton
39 | import androidx.compose.runtime.Composable
40 | import androidx.compose.ui.Alignment
41 | import androidx.compose.ui.Modifier
42 | import androidx.compose.ui.unit.dp
43 | import androidx.compose.ui.unit.sp
44 | import androidx.compose.ui.window.Dialog
45 | import com.conf.mad.todo.designsystem.TodoTheme
46 | import com.conf.mad.todo.designsystem.preview.DevicePreview
47 |
48 | @Composable
49 | internal fun DeleteTaskDialog(onDismissRequest: () -> Unit, onConfirm: () -> Unit) {
50 | Dialog(onDismissRequest = onDismissRequest) {
51 | Card(
52 | modifier = Modifier
53 | .padding(16.dp)
54 | .height(240.dp)
55 | .fillMaxWidth(),
56 | shape = RoundedCornerShape(4.dp),
57 | colors = CardDefaults.cardColors(containerColor = TodoTheme.colors.surface)
58 | ) {
59 | Column(
60 | modifier = Modifier
61 | .fillMaxSize()
62 | .padding(24.dp),
63 | verticalArrangement = Arrangement.SpaceBetween
64 | ) {
65 | Column(modifier = Modifier.fillMaxWidth()) {
66 | Text(
67 | text = "투두를 삭제할까요?",
68 | style = TodoTheme.typography.medium1.copy(fontSize = 20.sp),
69 | color = TodoTheme.colors.onSurface60
70 | )
71 | Spacer(modifier = Modifier.height(16.dp))
72 | Text(
73 | text = "삭제하면 되돌릴 수 없어요.",
74 | style = TodoTheme.typography.regular1,
75 | color = TodoTheme.colors.onSurface50
76 | )
77 | }
78 | Row(
79 | modifier = Modifier.fillMaxWidth(),
80 | horizontalArrangement = Arrangement.End,
81 | verticalAlignment = Alignment.Bottom
82 | ) {
83 | TextButton(
84 | onClick = onDismissRequest
85 | ) {
86 | Text(
87 | text = "취소",
88 | style = TodoTheme.typography.medium1,
89 | color = TodoTheme.colors.onSurface60
90 | )
91 | }
92 | Spacer(modifier = Modifier.width(8.dp))
93 | TextButton(
94 | onClick = onConfirm
95 | ) {
96 | Text(
97 | text = "삭제하기",
98 | style = TodoTheme.typography.medium1,
99 | color = TodoTheme.colors.primary
100 | )
101 | }
102 | }
103 | }
104 | }
105 | }
106 | }
107 |
108 | @DevicePreview
109 | @Composable
110 | private fun DeleteTaskDialogPreview() {
111 | TodoTheme {
112 | DeleteTaskDialog(
113 | onDismissRequest = {},
114 | onConfirm = {}
115 | )
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/component/EmptyTaskView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.component
24 |
25 | import androidx.compose.foundation.Image
26 | import androidx.compose.foundation.background
27 | import androidx.compose.foundation.layout.Column
28 | import androidx.compose.foundation.layout.Spacer
29 | import androidx.compose.foundation.layout.fillMaxWidth
30 | import androidx.compose.foundation.layout.height
31 | import androidx.compose.foundation.layout.padding
32 | import androidx.compose.material3.Text
33 | import androidx.compose.runtime.Composable
34 | import androidx.compose.ui.Alignment
35 | import androidx.compose.ui.Modifier
36 | import androidx.compose.ui.res.painterResource
37 | import androidx.compose.ui.unit.dp
38 | import com.conf.mad.todo.designsystem.AshBlue
39 | import com.conf.mad.todo.designsystem.SkyBlue
40 | import com.conf.mad.todo.designsystem.TodoTheme
41 | import com.conf.mad.todo.designsystem.preview.ComponentPreview
42 | import com.conf.mad.todo.home.R
43 |
44 | @Composable
45 | internal fun EmptyTaskView(modifier: Modifier = Modifier) {
46 | Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
47 | Image(
48 | painter = painterResource(id = R.drawable.ic_clip),
49 | contentDescription = "Empty View",
50 | modifier = Modifier.padding(vertical = 18.dp)
51 | )
52 | Spacer(modifier = Modifier.height(4.dp))
53 | Text(
54 | text = "투두를 추가해보세요",
55 | style = TodoTheme.typography.medium2,
56 | color = AshBlue
57 | )
58 | }
59 | }
60 |
61 | @ComponentPreview
62 | @Composable
63 | private fun EmptyTaskPreview() {
64 | TodoTheme {
65 | EmptyTaskView(
66 | modifier = Modifier
67 | .background(SkyBlue.copy(alpha = 0.3f))
68 | .fillMaxWidth()
69 | .padding(top = 20.dp)
70 | .height(128.dp)
71 | )
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/component/HomeBottomAppBar.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023-2024 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.component
24 |
25 | import androidx.compose.foundation.Image
26 | import androidx.compose.foundation.clickable
27 | import androidx.compose.foundation.layout.padding
28 | import androidx.compose.foundation.shape.RoundedCornerShape
29 | import androidx.compose.material3.BottomAppBar
30 | import androidx.compose.material3.FloatingActionButton
31 | import androidx.compose.material3.FloatingActionButtonDefaults
32 | import androidx.compose.runtime.Composable
33 | import androidx.compose.runtime.mutableStateOf
34 | import androidx.compose.runtime.remember
35 | import androidx.compose.ui.Modifier
36 | import androidx.compose.ui.draw.clip
37 | import androidx.compose.ui.graphics.ColorFilter
38 | import androidx.compose.ui.graphics.vector.ImageVector
39 | import androidx.compose.ui.res.vectorResource
40 | import androidx.compose.ui.unit.dp
41 | import com.conf.mad.todo.designsystem.TodoTheme
42 | import com.conf.mad.todo.designsystem.preview.ComponentPreview
43 | import com.conf.mad.todo.home.R
44 | import com.conf.mad.todo.home.model.HomeMenu
45 |
46 | @Composable
47 | internal fun HomeBottomAppBar(currentDestination: HomeMenu, onMenuSelected: (HomeMenu) -> Unit) {
48 | val onPress = remember(onMenuSelected) {
49 | { onMenuSelected(HomeMenu.POST) }
50 | }
51 | BottomAppBar(
52 | actions = {
53 | Image(
54 | imageVector = ImageVector.vectorResource(
55 | id = if (currentDestination == HomeMenu.TASK) {
56 | R.drawable.ic_navi_task_selected
57 | } else {
58 | R.drawable.ic_navi_task_default
59 | }
60 | ),
61 | contentDescription = "Task List Button",
62 | modifier = Modifier
63 | .clip(RoundedCornerShape(24.dp))
64 | .clickable { onMenuSelected(HomeMenu.TASK) }
65 | .padding(12.dp)
66 | )
67 | Image(
68 | imageVector = ImageVector.vectorResource(
69 | id = if (currentDestination == HomeMenu.FAVORITE) {
70 | R.drawable.ic_navi_favorite_selected
71 | } else {
72 | R.drawable.ic_navi_favorite_default
73 | }
74 | ),
75 | contentDescription = "Task List Button",
76 | modifier = Modifier
77 | .clip(RoundedCornerShape(24.dp))
78 | .clickable { onMenuSelected(HomeMenu.FAVORITE) }
79 | .padding(12.dp)
80 | )
81 | },
82 | floatingActionButton = {
83 | FloatingActionButton(
84 | onClick = onPress,
85 | containerColor = TodoTheme.colors.onPrimary,
86 | elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
87 | ) {
88 | Image(
89 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_navi_add),
90 | contentDescription = "Task Post Button",
91 | colorFilter = ColorFilter.tint(TodoTheme.colors.primary)
92 | )
93 | }
94 | },
95 | containerColor = TodoTheme.colors.surface
96 | )
97 | }
98 |
99 | @ComponentPreview
100 | @Composable
101 | private fun HomeBottomAppBarPreview() {
102 | val (currentDestination, onNavigate) = remember {
103 | mutableStateOf(HomeMenu.TASK)
104 | }
105 | TodoTheme {
106 | HomeBottomAppBar(
107 | currentDestination = currentDestination,
108 | onMenuSelected = onNavigate
109 | )
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/component/HomeTopAppBar.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023-2024 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.component
24 |
25 | import androidx.compose.foundation.Image
26 | import androidx.compose.foundation.layout.Spacer
27 | import androidx.compose.foundation.layout.width
28 | import androidx.compose.material3.ExperimentalMaterial3Api
29 | import androidx.compose.material3.TopAppBar
30 | import androidx.compose.runtime.Composable
31 | import androidx.compose.runtime.getValue
32 | import androidx.compose.runtime.mutableStateOf
33 | import androidx.compose.runtime.remember
34 | import androidx.compose.runtime.setValue
35 | import androidx.compose.ui.Modifier
36 | import androidx.compose.ui.res.painterResource
37 | import androidx.compose.ui.unit.dp
38 | import com.conf.mad.todo.designsystem.TodoTheme
39 | import com.conf.mad.todo.designsystem.preview.ComponentPreview
40 |
41 | internal typealias CommonDrawable = com.conf.mad.todo.designsystem.R.drawable
42 |
43 | @OptIn(ExperimentalMaterial3Api::class)
44 | @Composable
45 | internal fun HomeTopAppBar(isCompletedTaskVisible: Boolean, onToggleCompletedTaskVisibility: () -> Unit) {
46 | val onToggle = remember(onToggleCompletedTaskVisibility) {
47 | { onToggleCompletedTaskVisibility() }
48 | }
49 | TopAppBar(
50 | title = {
51 | Image(
52 | painter = painterResource(id = CommonDrawable.ic_title_home),
53 | contentDescription = "Home Title: Star"
54 | )
55 | },
56 | actions = {
57 | CompletedTaskVisibilityToggleButton(
58 | isVisible = isCompletedTaskVisible,
59 | onToggle = onToggle
60 | )
61 | Spacer(modifier = Modifier.width(12.dp))
62 | }
63 | )
64 | }
65 |
66 | @ComponentPreview
67 | @Composable
68 | private fun HomeTopAppBarPreview() {
69 | var visibility by remember {
70 | mutableStateOf(true)
71 | }
72 | TodoTheme {
73 | HomeTopAppBar(
74 | isCompletedTaskVisible = visibility,
75 | onToggleCompletedTaskVisibility = { visibility = !visibility }
76 | )
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/component/TaskItem.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.component
24 |
25 | import androidx.compose.foundation.ExperimentalFoundationApi
26 | import androidx.compose.foundation.Image
27 | import androidx.compose.foundation.background
28 | import androidx.compose.foundation.combinedClickable
29 | import androidx.compose.foundation.layout.Arrangement
30 | import androidx.compose.foundation.layout.Row
31 | import androidx.compose.foundation.layout.Spacer
32 | import androidx.compose.foundation.layout.fillMaxWidth
33 | import androidx.compose.foundation.layout.padding
34 | import androidx.compose.foundation.layout.width
35 | import androidx.compose.material3.Text
36 | import androidx.compose.runtime.Composable
37 | import androidx.compose.ui.Alignment
38 | import androidx.compose.ui.Modifier
39 | import androidx.compose.ui.res.painterResource
40 | import androidx.compose.ui.unit.dp
41 | import com.conf.mad.todo.designsystem.TodoTheme
42 | import com.conf.mad.todo.designsystem.preview.ComponentPreview
43 | import com.conf.mad.todo.home.R
44 | import com.conf.mad.todo.home.model.TaskStatus
45 | import com.conf.mad.todo.ui.noRippleClickable
46 |
47 | @OptIn(ExperimentalFoundationApi::class)
48 | @Composable
49 | internal fun TaskItem(
50 | title: String,
51 | status: TaskStatus,
52 | isFavorite: Boolean,
53 | onCompletedValueChange: () -> Unit,
54 | onFavoriteValueChange: () -> Unit,
55 | onDeleteDialogShow: () -> Unit,
56 | modifier: Modifier = Modifier
57 | ) {
58 | Row(
59 | modifier = modifier
60 | .background(color = TodoTheme.colors.surface),
61 | horizontalArrangement = Arrangement.SpaceBetween,
62 | verticalAlignment = Alignment.CenterVertically
63 | ) {
64 | Row(
65 | modifier = Modifier
66 | .combinedClickable(
67 | onClick = onCompletedValueChange,
68 | onLongClick = onDeleteDialogShow
69 | ).weight(1f),
70 | verticalAlignment = Alignment.CenterVertically
71 | ) {
72 | Image(
73 | painter = painterResource(
74 | id = when (status) {
75 | TaskStatus.TODO -> R.drawable.ic_task_default
76 | TaskStatus.DONE -> R.drawable.ic_task_done
77 | TaskStatus.COMPLETED -> R.drawable.ic_task_completed
78 | }
79 | ),
80 | contentDescription = "Task Completed Button",
81 | modifier = Modifier
82 | .padding(9.dp)
83 | .noRippleClickable(onClick = onCompletedValueChange)
84 | )
85 | Spacer(modifier = Modifier.width(16.dp))
86 | Text(
87 | text = title,
88 | style = TodoTheme.typography.regular1,
89 | color = if (status == TaskStatus.COMPLETED) {
90 | TodoTheme.colors.onSurface30
91 | } else {
92 | TodoTheme.colors.onSurface60
93 | }
94 | )
95 | }
96 |
97 | if (status != TaskStatus.COMPLETED) {
98 | Image(
99 | painter = painterResource(
100 | id = if (isFavorite) {
101 | R.drawable.ic_star_home_filled
102 | } else {
103 | R.drawable.ic_star_home_default
104 | }
105 | ),
106 | contentDescription = "Task Favorite Button",
107 | modifier = Modifier
108 | .padding(12.dp)
109 | .noRippleClickable(onClick = onFavoriteValueChange)
110 | )
111 | }
112 | }
113 | }
114 |
115 | @ComponentPreview
116 | @Composable
117 | private fun TaskItemPreview() {
118 | TodoTheme {
119 | TaskItem(
120 | title = "Task Title",
121 | status = TaskStatus.DONE,
122 | isFavorite = false,
123 | onCompletedValueChange = {},
124 | onFavoriteValueChange = {},
125 | onDeleteDialogShow = {},
126 | modifier = Modifier.fillMaxWidth()
127 | )
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/model/HomeMenu.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.model
24 |
25 | enum class HomeMenu(val route: String) {
26 | TASK("task"),
27 | FAVORITE("favorite"),
28 | POST("post")
29 | }
30 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/model/HomeUiState.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.model
24 |
25 | import kotlinx.collections.immutable.ImmutableList
26 | import kotlinx.collections.immutable.persistentListOf
27 |
28 | data class HomeUiState(
29 | val isCompletedTaskVisible: Boolean = true,
30 | val currentDestination: HomeMenu = HomeMenu.TASK,
31 | val taskToDelete: TaskUiModel? = null,
32 | val todoTasks: ImmutableList = persistentListOf(),
33 | val completedTasks: ImmutableList = persistentListOf(),
34 | val doneTasks: ImmutableList = persistentListOf()
35 | ) {
36 | val isOnlyFavoriteTaskVisible
37 | get() = currentDestination == HomeMenu.FAVORITE
38 | }
39 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/model/TaskStatus.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.model
24 |
25 | enum class TaskStatus {
26 | TODO,
27 | DONE,
28 | COMPLETED
29 | }
30 |
--------------------------------------------------------------------------------
/feature/home/src/main/java/com/conf/mad/todo/home/model/TaskUiModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.home.model
24 |
25 | import com.conf.mad.todo.task.model.Task
26 |
27 | data class TaskUiModel(
28 | val id: Long?,
29 | val title: String,
30 | val description: String,
31 | val status: TaskStatus,
32 | val isFavorite: Boolean
33 | ) {
34 | val isCompleted
35 | get() = status == TaskStatus.COMPLETED
36 |
37 | private constructor(task: Task) : this(
38 | id = task.id,
39 | title = task.title,
40 | description = task.description,
41 | status = if (task.isCompleted) TaskStatus.COMPLETED else TaskStatus.TODO,
42 | isFavorite = task.isFavorite
43 | )
44 |
45 | fun asDomain() = Task(
46 | id = id,
47 | title = title,
48 | description = description,
49 | isFavorite = isFavorite,
50 | isCompleted = isCompleted
51 | )
52 |
53 | companion object {
54 | fun of(task: Task) = TaskUiModel(task)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_clip.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_navi_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
36 |
42 |
43 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_navi_task_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
35 |
36 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_navi_task_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
31 |
33 |
38 |
43 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_star_home_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_star_home_filled.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_task_completed.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
33 |
38 |
39 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_task_default.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
35 |
36 |
--------------------------------------------------------------------------------
/feature/home/src/main/res/drawable/ic_task_done.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
30 |
35 |
40 |
41 |
--------------------------------------------------------------------------------
/feature/post/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/feature/post/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | plugins {
24 | id("conf.mad.convention.android.feature")
25 | }
26 |
27 | android {
28 | namespace = "com.conf.mad.todo.post"
29 |
30 | defaultConfig {
31 | consumerProguardFiles("consumer-rules.pro")
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation(projects.core.designsystem)
37 | implementation(projects.core.ui)
38 | implementation(projects.domain.task)
39 | }
40 |
--------------------------------------------------------------------------------
/feature/post/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/feature/post/consumer-rules.pro
--------------------------------------------------------------------------------
/feature/post/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
--------------------------------------------------------------------------------
/feature/post/src/main/java/com/conf/mad/todo/post/PostViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.post
24 |
25 | import androidx.lifecycle.ViewModel
26 | import androidx.lifecycle.viewModelScope
27 | import com.conf.mad.todo.post.model.PostUiState
28 | import com.conf.mad.todo.task.repository.TaskRepository
29 | import dagger.hilt.android.lifecycle.HiltViewModel
30 | import javax.inject.Inject
31 | import kotlinx.coroutines.flow.MutableStateFlow
32 | import kotlinx.coroutines.flow.asStateFlow
33 | import kotlinx.coroutines.flow.update
34 | import kotlinx.coroutines.launch
35 |
36 | @HiltViewModel
37 | class PostViewModel @Inject constructor(
38 | private val repository: TaskRepository
39 | ) : ViewModel() {
40 | private val _uiState = MutableStateFlow(PostUiState())
41 | val uiState = _uiState.asStateFlow()
42 |
43 | fun onTitleChanged(title: String) {
44 | _uiState.update {
45 | it.copy(title = title)
46 | }
47 | }
48 |
49 | fun onDescriptionChanged(description: String) {
50 | _uiState.update {
51 | it.copy(description = description)
52 | }
53 | }
54 |
55 | fun onFavoriteChanged() {
56 | _uiState.update {
57 | it.copy(isFavorite = !it.isFavorite)
58 | }
59 | }
60 |
61 | fun onCreateNewTask() = viewModelScope.launch {
62 | repository.insertTask(uiState.value.asDomain())
63 | _uiState.update {
64 | it.copy(isSaved = true)
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/feature/post/src/main/java/com/conf/mad/todo/post/component/AddTaskTopAppBar.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023-2024 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.post.component
24 |
25 | import androidx.compose.foundation.Image
26 | import androidx.compose.foundation.layout.Row
27 | import androidx.compose.foundation.layout.padding
28 | import androidx.compose.material3.ExperimentalMaterial3Api
29 | import androidx.compose.material3.Text
30 | import androidx.compose.material3.TopAppBar
31 | import androidx.compose.runtime.Composable
32 | import androidx.compose.ui.Alignment
33 | import androidx.compose.ui.Modifier
34 | import androidx.compose.ui.graphics.vector.ImageVector
35 | import androidx.compose.ui.res.vectorResource
36 | import androidx.compose.ui.unit.dp
37 | import com.conf.mad.todo.designsystem.TodoTheme
38 | import com.conf.mad.todo.designsystem.preview.ComponentPreview
39 | import com.conf.mad.todo.ui.noRippleClickable
40 |
41 | typealias CommonDrawable = com.conf.mad.todo.designsystem.R.drawable
42 |
43 | @OptIn(ExperimentalMaterial3Api::class)
44 | @Composable
45 | internal fun AddTaskTopAppBar(
46 | isFavorite: Boolean,
47 | isPostEnabled: Boolean,
48 | onPressFavorite: () -> Unit,
49 | onCancel: () -> Unit,
50 | onComplete: () -> Unit,
51 | modifier: Modifier = Modifier
52 | ) {
53 | TopAppBar(
54 | title = {
55 | Row(
56 | verticalAlignment = Alignment.CenterVertically
57 | ) {
58 | Image(
59 | imageVector = ImageVector.vectorResource(id = CommonDrawable.ic_add_task),
60 | contentDescription = "Add Task Title"
61 | )
62 | Image(
63 | imageVector = ImageVector.vectorResource(
64 | id = if (isFavorite) {
65 | CommonDrawable.ic_star_filled
66 | } else {
67 | CommonDrawable.ic_star_default
68 | }
69 | ),
70 | contentDescription = "Add Task Title",
71 | modifier = Modifier
72 | .noRippleClickable(onClick = onPressFavorite)
73 | .padding(8.dp)
74 | )
75 | }
76 | },
77 | actions = {
78 | Text(
79 | text = "취소",
80 | color = TodoTheme.colors.onSurface50,
81 | style = TodoTheme.typography.medium1,
82 | modifier = Modifier
83 | .noRippleClickable(onClick = onCancel)
84 | .padding(16.dp)
85 | )
86 | Text(
87 | text = "완료",
88 | color = if (isPostEnabled) {
89 | TodoTheme.colors.primary
90 | } else {
91 | TodoTheme.colors.onSurface50
92 | },
93 | style = TodoTheme.typography.medium1,
94 | modifier = Modifier
95 | .then(
96 | if (isPostEnabled) {
97 | Modifier.noRippleClickable(onClick = onComplete)
98 | } else {
99 | Modifier
100 | }
101 | )
102 | .padding(16.dp)
103 | )
104 | },
105 | modifier = modifier
106 | )
107 | }
108 |
109 | @ComponentPreview
110 | @Composable
111 | private fun TodoTopAppBarPreview() {
112 | TodoTheme {
113 | AddTaskTopAppBar(
114 | isFavorite = true,
115 | isPostEnabled = true,
116 | onPressFavorite = {},
117 | onCancel = {},
118 | onComplete = {}
119 | )
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/feature/post/src/main/java/com/conf/mad/todo/post/model/PostUiState.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright 2023 MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 | package com.conf.mad.todo.post.model
24 |
25 | import com.conf.mad.todo.task.model.Task
26 |
27 | data class PostUiState(
28 | val title: String = "",
29 | val description: String = "",
30 | val isFavorite: Boolean = false,
31 | val isSaved: Boolean = false
32 | ) {
33 | fun asDomain() = Task(
34 | title = title,
35 | description = description,
36 | isFavorite = isFavorite
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
2 | org.gradle.parallel=true
3 | android.useAndroidX=true
4 | kotlin.code.style=official
5 | android.nonTransitiveRClass=true
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MobileAppDeveloperConference/android/bc050b2fa736aaabd1414edb83fcf1e847419a8c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["config:base", ":dependencyDashboard"]
4 | }
5 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
2 | pluginManagement {
3 | includeBuild("build-logic")
4 | repositories {
5 | google()
6 | mavenCentral()
7 | gradlePluginPortal()
8 | }
9 | }
10 | dependencyResolutionManagement {
11 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
12 | repositories {
13 | google()
14 | mavenCentral()
15 | }
16 | }
17 |
18 | rootProject.name = "TodoMad"
19 | include(
20 | ":app",
21 | ":core:common",
22 | ":core:database",
23 | ":core:designsystem",
24 | ":core:ui",
25 | ":data:task",
26 | ":domain:task",
27 | ":feature:home",
28 | ":feature:post"
29 | )
30 |
--------------------------------------------------------------------------------
/spotless/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_size = 4
6 | max_line_length = 160
7 |
8 | [*.{kt,kts}]
9 | max_line_length = 160
10 | ktlint_code_style = android_studio
11 | ktlint_standard_function-naming = disabled
12 | ktlint_standard_annotation = disabled
13 |
--------------------------------------------------------------------------------
/spotless/spotless.license.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | * Copyright $YEAR MADConference
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | */
23 |
--------------------------------------------------------------------------------
/spotless/spotless.license.xml:
--------------------------------------------------------------------------------
1 |
2 |
25 |
--------------------------------------------------------------------------------