@jetstart/cli 1.7.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +133 -41
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +11 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/android-emulator.d.ts.map +1 -0
  6. package/dist/commands/android-emulator.js.map +1 -0
  7. package/dist/commands/build.d.ts +13 -1
  8. package/dist/commands/build.d.ts.map +1 -0
  9. package/dist/commands/build.js +279 -29
  10. package/dist/commands/build.js.map +1 -0
  11. package/dist/commands/clean.d.ts +23 -0
  12. package/dist/commands/clean.d.ts.map +1 -0
  13. package/dist/commands/clean.js +191 -0
  14. package/dist/commands/clean.js.map +1 -0
  15. package/dist/commands/create.d.ts.map +1 -0
  16. package/dist/commands/create.js +41 -0
  17. package/dist/commands/create.js.map +1 -0
  18. package/dist/commands/dev.d.ts.map +1 -0
  19. package/dist/commands/dev.js +51 -9
  20. package/dist/commands/dev.js.map +1 -0
  21. package/dist/commands/index.d.ts.map +1 -0
  22. package/dist/commands/index.js.map +1 -0
  23. package/dist/commands/install-audit.d.ts.map +1 -0
  24. package/dist/commands/install-audit.js.map +1 -0
  25. package/dist/commands/logs.d.ts.map +1 -0
  26. package/dist/commands/logs.js.map +1 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/types/index.d.ts.map +1 -0
  30. package/dist/types/index.js.map +1 -0
  31. package/dist/utils/android-sdk.d.ts.map +1 -0
  32. package/dist/utils/android-sdk.js +2 -2
  33. package/dist/utils/android-sdk.js.map +1 -0
  34. package/dist/utils/downloader.d.ts.map +1 -0
  35. package/dist/utils/downloader.js.map +1 -0
  36. package/dist/utils/emulator-deployer.d.ts.map +1 -0
  37. package/dist/utils/emulator-deployer.js.map +1 -0
  38. package/dist/utils/emulator.d.ts.map +1 -0
  39. package/dist/utils/emulator.js +5 -4
  40. package/dist/utils/emulator.js.map +1 -0
  41. package/dist/utils/index.d.ts.map +1 -0
  42. package/dist/utils/index.js.map +1 -0
  43. package/dist/utils/java.d.ts.map +1 -0
  44. package/dist/utils/java.js +5 -5
  45. package/dist/utils/java.js.map +1 -0
  46. package/dist/utils/logger.d.ts.map +1 -0
  47. package/dist/utils/logger.js.map +1 -0
  48. package/dist/utils/open.d.ts.map +1 -0
  49. package/dist/utils/open.js.map +1 -0
  50. package/dist/utils/prompt.d.ts.map +1 -0
  51. package/dist/utils/prompt.js.map +1 -0
  52. package/dist/utils/spinner.d.ts.map +1 -0
  53. package/dist/utils/spinner.js.map +1 -0
  54. package/dist/utils/system-tools.d.ts.map +1 -0
  55. package/dist/utils/system-tools.js.map +1 -0
  56. package/dist/utils/template.d.ts +13 -1
  57. package/dist/utils/template.d.ts.map +1 -0
  58. package/dist/utils/template.js +134 -1000
  59. package/dist/utils/template.js.map +1 -0
  60. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/1.0.0/com.jetstart.hot-reload.gradle.plugin-1.0.0.pom +15 -0
  61. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/1.0.0/com.jetstart.hot-reload.gradle.plugin-1.0.0.pom.md5 +1 -0
  62. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/1.0.0/com.jetstart.hot-reload.gradle.plugin-1.0.0.pom.sha1 +1 -0
  63. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/1.0.0/com.jetstart.hot-reload.gradle.plugin-1.0.0.pom.sha256 +1 -0
  64. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/1.0.0/com.jetstart.hot-reload.gradle.plugin-1.0.0.pom.sha512 +1 -0
  65. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/maven-metadata.xml +13 -0
  66. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/maven-metadata.xml.md5 +1 -0
  67. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/maven-metadata.xml.sha1 +1 -0
  68. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/maven-metadata.xml.sha256 +1 -0
  69. package/maven-repo/com/jetstart/hot-reload/com.jetstart.hot-reload.gradle.plugin/maven-metadata.xml.sha512 +1 -0
  70. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0-sources.jar +0 -0
  71. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0-sources.jar.md5 +1 -0
  72. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0-sources.jar.sha1 +1 -0
  73. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0-sources.jar.sha256 +1 -0
  74. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0-sources.jar.sha512 +1 -0
  75. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.aar +0 -0
  76. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.aar.md5 +1 -0
  77. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.aar.sha1 +1 -0
  78. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.aar.sha256 +1 -0
  79. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.aar.sha512 +1 -0
  80. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.module +124 -0
  81. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.module.md5 +1 -0
  82. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.module.sha1 +1 -0
  83. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.module.sha256 +1 -0
  84. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.module.sha512 +1 -0
  85. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.pom +46 -0
  86. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.pom.md5 +1 -0
  87. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.pom.sha1 +1 -0
  88. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.pom.sha256 +1 -0
  89. package/maven-repo/com/jetstart/hot-reload-runtime/1.0.0/hot-reload-runtime-1.0.0.pom.sha512 +1 -0
  90. package/maven-repo/com/jetstart/hot-reload-runtime/maven-metadata.xml +13 -0
  91. package/maven-repo/com/jetstart/hot-reload-runtime/maven-metadata.xml.md5 +1 -0
  92. package/maven-repo/com/jetstart/hot-reload-runtime/maven-metadata.xml.sha1 +1 -0
  93. package/maven-repo/com/jetstart/hot-reload-runtime/maven-metadata.xml.sha256 +1 -0
  94. package/maven-repo/com/jetstart/hot-reload-runtime/maven-metadata.xml.sha512 +1 -0
  95. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.jar +0 -0
  96. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.jar.md5 +1 -0
  97. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.jar.sha1 +1 -0
  98. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.jar.sha256 +1 -0
  99. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.jar.sha512 +1 -0
  100. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.module +103 -0
  101. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.module.md5 +1 -0
  102. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.module.sha1 +1 -0
  103. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.module.sha256 +1 -0
  104. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.module.sha512 +1 -0
  105. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.pom +38 -0
  106. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.pom.md5 +1 -0
  107. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.pom.sha1 +1 -0
  108. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.pom.sha256 +1 -0
  109. package/maven-repo/com/jetstart/jetstart-gradle-plugin/1.0.0/jetstart-gradle-plugin-1.0.0.pom.sha512 +1 -0
  110. package/maven-repo/com/jetstart/jetstart-gradle-plugin/maven-metadata.xml +13 -0
  111. package/maven-repo/com/jetstart/jetstart-gradle-plugin/maven-metadata.xml.md5 +1 -0
  112. package/maven-repo/com/jetstart/jetstart-gradle-plugin/maven-metadata.xml.sha1 +1 -0
  113. package/maven-repo/com/jetstart/jetstart-gradle-plugin/maven-metadata.xml.sha256 +1 -0
  114. package/maven-repo/com/jetstart/jetstart-gradle-plugin/maven-metadata.xml.sha512 +1 -0
  115. package/package.json +14 -5
  116. package/scripts/build-java.js +34 -0
  117. package/template/base/README.md +34 -0
  118. package/template/base/app/build.gradle +80 -0
  119. package/template/base/app/proguard-rules.pro +33 -0
  120. package/template/base/app/src/main/AndroidManifest.xml +33 -0
  121. package/template/base/app/src/main/java/__PACKAGE_PATH__/MainActivity.kt +64 -0
  122. package/template/base/app/src/main/java/__PACKAGE_PATH__/data/AppDatabase.kt +46 -0
  123. package/template/base/app/src/main/java/__PACKAGE_PATH__/data/Note.kt +12 -0
  124. package/template/base/app/src/main/java/__PACKAGE_PATH__/data/NoteDao.kt +23 -0
  125. package/template/base/app/src/main/java/__PACKAGE_PATH__/logic/TaggingEngine.kt +26 -0
  126. package/template/base/app/src/main/java/__PACKAGE_PATH__/ui/NotesScreen.kt +185 -0
  127. package/template/base/app/src/main/java/__PACKAGE_PATH__/ui/NotesViewModel.kt +58 -0
  128. package/template/base/app/src/main/java/__PACKAGE_PATH__/ui/TestScreen.kt +12 -0
  129. package/template/base/app/src/main/res/values/colors.xml +10 -0
  130. package/template/base/app/src/main/res/values/strings.xml +4 -0
  131. package/template/base/app/src/main/res/values/themes.xml +9 -0
  132. package/template/base/app/src/main/res/xml/network_security_config.xml +8 -0
  133. package/template/base/app/src/main/res/xml/provider_paths.xml +4 -0
  134. package/template/base/build.gradle +28 -0
  135. package/template/base/gradle/wrapper/gradle-wrapper.jar +0 -0
  136. package/template/base/gradle/wrapper/gradle-wrapper.properties +7 -0
  137. package/template/base/gradle.properties +13 -0
  138. package/template/base/gradlew +248 -0
  139. package/template/base/gradlew.bat +92 -0
  140. package/template/base/jetstart.config.json +11 -0
  141. package/template/base/settings.gradle +20 -0
  142. package/.eslintrc.json +0 -6
  143. package/src/cli.ts +0 -99
  144. package/src/commands/android-emulator.ts +0 -304
  145. package/src/commands/build.ts +0 -60
  146. package/src/commands/create.ts +0 -232
  147. package/src/commands/dev.ts +0 -198
  148. package/src/commands/index.ts +0 -10
  149. package/src/commands/install-audit.ts +0 -227
  150. package/src/commands/logs.ts +0 -117
  151. package/src/index.ts +0 -17
  152. package/src/types/index.ts +0 -53
  153. package/src/utils/android-sdk.ts +0 -512
  154. package/src/utils/downloader.ts +0 -201
  155. package/src/utils/emulator-deployer.ts +0 -210
  156. package/src/utils/emulator.ts +0 -463
  157. package/src/utils/index.ts +0 -8
  158. package/src/utils/java.ts +0 -369
  159. package/src/utils/logger.ts +0 -42
  160. package/src/utils/open.ts +0 -36
  161. package/src/utils/prompt.ts +0 -56
  162. package/src/utils/spinner.ts +0 -25
  163. package/src/utils/system-tools.ts +0 -648
  164. package/src/utils/template.ts +0 -1214
  165. package/tests/create.test.ts +0 -33
  166. package/tests/utils.test.ts +0 -17
  167. package/tsconfig.json +0 -25
@@ -0,0 +1,34 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ A JetStart project with Kotlin and Jetpack Compose.
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ # Start development server
9
+ jetstart dev
10
+
11
+ # Build production APK
12
+ jetstart build
13
+
14
+ # View logs
15
+ jetstart logs
16
+ ```
17
+
18
+ ## Project Structure
19
+
20
+ ```
21
+ {{PROJECT_NAME}}/
22
+ ├── app/
23
+ │ └── src/
24
+ │ └── main/
25
+ │ ├── java/ # Kotlin source files
26
+ │ └── res/ # Resources
27
+ ├── jetstart.config.json # JetStart configuration
28
+ └── build.gradle # Gradle build file
29
+ ```
30
+
31
+ ## Learn More
32
+
33
+ - [JetStart Documentation](https://github.com/phantom/jetstart)
34
+ - [Jetpack Compose](https://developer.android.com/jetpack/compose)
@@ -0,0 +1,80 @@
1
+ plugins {
2
+ id 'com.android.application'
3
+ id 'org.jetbrains.kotlin.android'
4
+ id 'com.google.devtools.ksp'
5
+ id 'com.jetstart.hot-reload' version '1.0.0' // True hot reload instrumentation
6
+ id 'org.jetbrains.kotlin.plugin.compose'
7
+ }
8
+
9
+ android {
10
+ namespace '{{PACKAGE_NAME}}'
11
+ compileSdk 34
12
+
13
+ defaultConfig {
14
+ applicationId "{{PACKAGE_NAME}}"
15
+ minSdk 24
16
+ targetSdk 34
17
+ versionCode 1
18
+ versionName "1.0.0"
19
+
20
+ // JetStart injected fields
21
+ buildConfigField "String", "JETSTART_SERVER_URL", "\"\"" // injected by: jetstart dev
22
+ buildConfigField "String", "JETSTART_SESSION_ID", "\"\"" // injected by: jetstart dev
23
+ // End JetStart fields
24
+ }
25
+
26
+ buildTypes {
27
+ debug {
28
+ debuggable true
29
+ }
30
+ release {
31
+ debuggable false
32
+ minifyEnabled true
33
+ shrinkResources true
34
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
35
+ // Signing config is injected by `jetstart build --sign` via keystore.properties
36
+ }
37
+ }
38
+
39
+ compileOptions {
40
+ sourceCompatibility JavaVersion.VERSION_17
41
+ targetCompatibility JavaVersion.VERSION_17
42
+ }
43
+
44
+ kotlinOptions {
45
+ jvmTarget = '17'
46
+ }
47
+
48
+ buildFeatures {
49
+ compose true
50
+ buildConfig true // Required for JetStart hot reload
51
+ }
52
+
53
+
54
+ }
55
+
56
+ dependencies {
57
+ implementation 'androidx.core:core-ktx:1.12.0'
58
+ implementation 'androidx.appcompat:appcompat:1.6.1'
59
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
60
+ implementation 'androidx.activity:activity-compose:1.8.1'
61
+ implementation platform('androidx.compose:compose-bom:2023.10.01')
62
+ implementation 'androidx.compose.ui:ui'
63
+ implementation 'androidx.compose.ui:ui-graphics'
64
+ implementation 'androidx.compose.ui:ui-tooling-preview'
65
+ implementation 'androidx.compose.material3:material3'
66
+
67
+ // Room
68
+ implementation 'androidx.room:room-runtime:2.6.1'
69
+ implementation 'androidx.room:room-ktx:2.6.1'
70
+ ksp 'androidx.room:room-compiler:2.6.1'
71
+
72
+ // Gson
73
+ implementation 'com.google.code.gson:gson:2.10.1'
74
+
75
+ // JetStart Hot Reload Runtime
76
+ implementation 'com.jetstart:hot-reload-runtime:1.0.0'
77
+
78
+ implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2"
79
+
80
+ }
@@ -0,0 +1,33 @@
1
+ # JetStart default ProGuard/R8 rules
2
+ # Add your project-specific rules at the bottom.
3
+ # Kotlin
4
+ -keep class kotlin.** { *; }
5
+ -keepclassmembers class **$WhenMappings { <fields>; }
6
+ -dontwarn kotlin.**
7
+ # Jetpack Compose
8
+ -keep class androidx.compose.** { *; }
9
+ -keepclassmembers class androidx.compose.** { *; }
10
+ -dontwarn androidx.compose.**
11
+ # Room
12
+ -keep class * extends androidx.room.RoomDatabase { *; }
13
+ -keep @androidx.room.Entity class * { *; }
14
+ -keep @androidx.room.Dao class * { *; }
15
+ -dontwarn androidx.room.**
16
+ # Gson (JSON serialization)
17
+ -keepclassmembers class * {
18
+ @com.google.gson.annotations.SerializedName <fields>;
19
+ }
20
+ -keep class * implements com.google.gson.TypeAdapterFactory { *; }
21
+ # OkHttp + WebSocket
22
+ # Only used by HotReload (debug only). R8 strips the entire
23
+ # HotReload code path in release builds via BuildConfig.DEBUG = false.
24
+ -dontwarn okhttp3.**
25
+ -dontwarn okio.**
26
+ # DivKit
27
+ -keep class com.yandex.div.** { *; }
28
+ -dontwarn com.yandex.div.**
29
+ # Enum names (required for serialization)
30
+ -keepclassmembers enum * { *; }
31
+ # App data classes used by Room
32
+ -keep class {{PACKAGE_NAME}}.data.** { *; }
33
+ # Add your own keep rules below this line
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+
4
+ <uses-permission android:name="android.permission.INTERNET" />
5
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
6
+
7
+ <application
8
+ android:allowBackup="true"
9
+ android:label="@string/app_name"
10
+ android:theme="@style/Theme.{{THEME_NAME}}"
11
+ android:networkSecurityConfig="@xml/network_security_config">
12
+
13
+ <provider
14
+ android:name="androidx.core.content.FileProvider"
15
+ android:authorities="${applicationId}.fileprovider"
16
+ android:exported="false"
17
+ android:grantUriPermissions="true">
18
+ <meta-data
19
+ android:name="android.support.FILE_PROVIDER_PATHS"
20
+ android:resource="@xml/provider_paths" />
21
+ </provider>
22
+
23
+ <activity
24
+ android:name=".MainActivity"
25
+ android:exported="true">
26
+ <intent-filter>
27
+ <action android:name="android.intent.action.MAIN" />
28
+ <category android:name="android.intent.category.LAUNCHER" />
29
+ </intent-filter>
30
+ </activity>
31
+ </application>
32
+
33
+ </manifest>
@@ -0,0 +1,64 @@
1
+ package {{PACKAGE_NAME}}
2
+
3
+ import android.os.Bundle
4
+ import androidx.appcompat.app.AppCompatActivity
5
+ import androidx.activity.compose.setContent
6
+ import androidx.compose.foundation.layout.*
7
+ import androidx.compose.material3.*
8
+ import androidx.compose.runtime.*
9
+ import androidx.compose.ui.Alignment
10
+ import androidx.compose.ui.Modifier
11
+ import androidx.compose.ui.unit.dp
12
+ import {{PACKAGE_NAME}}.ui.NotesScreen
13
+ import com.jetstart.hotreload.HotReload
14
+
15
+ class MainActivity : AppCompatActivity() {
16
+ override fun onCreate(savedInstanceState: Bundle?) {
17
+ super.onCreate(savedInstanceState)
18
+
19
+ // Hot reload is ONLY active in debug builds.
20
+ // In release builds this block is completely eliminated by R8 (BuildConfig.DEBUG = false).
21
+ if (BuildConfig.DEBUG) {
22
+ try {
23
+ val serverUrl = BuildConfig.JETSTART_SERVER_URL
24
+ val sessionId = BuildConfig.JETSTART_SESSION_ID
25
+ if (serverUrl.isNotEmpty()) {
26
+ HotReload.connect(this, serverUrl, sessionId)
27
+ }
28
+ } catch (e: Exception) {
29
+ android.util.Log.w("MainActivity", "Hot reload not configured: ${e.message}")
30
+ }
31
+ }
32
+
33
+ setContent {
34
+ MaterialTheme {
35
+ Surface(
36
+ modifier = Modifier.fillMaxSize(),
37
+ color = MaterialTheme.colorScheme.background
38
+ ) {
39
+ // Observe reload version - forces recomposition when DEX hot reload happens
40
+ val reloadVersion by HotReload.reloadVersion.collectAsState()
41
+
42
+ // Use reloadVersion as key to force recomposition of entire tree
43
+ key(reloadVersion) {
44
+ // Normal mode: render actual Compose code
45
+ AppContent()
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ override fun onDestroy() {
53
+ super.onDestroy()
54
+ if (BuildConfig.DEBUG) { HotReload.disconnect() }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Main App Content
60
+ */
61
+ @Composable
62
+ fun AppContent() {
63
+ NotesScreen()
64
+ }
@@ -0,0 +1,46 @@
1
+ package {{PACKAGE_NAME}}.data
2
+
3
+ import android.content.Context
4
+ import androidx.room.Database
5
+ import androidx.room.Room
6
+ import androidx.room.RoomDatabase
7
+ import androidx.room.TypeConverter
8
+ import androidx.room.TypeConverters
9
+ import com.google.gson.Gson
10
+ import com.google.gson.reflect.TypeToken
11
+
12
+ @Database(entities = [Note::class], version = 1, exportSchema = false)
13
+ @TypeConverters(Converters::class)
14
+ abstract class AppDatabase : RoomDatabase() {
15
+ abstract fun noteDao(): NoteDao
16
+
17
+ companion object {
18
+ @Volatile
19
+ private var INSTANCE: AppDatabase? = null
20
+
21
+ fun getDatabase(context: Context): AppDatabase {
22
+ return INSTANCE ?: synchronized(this) {
23
+ val instance = Room.databaseBuilder(
24
+ context.applicationContext,
25
+ AppDatabase::class.java,
26
+ "note_database"
27
+ ).build()
28
+ INSTANCE = instance
29
+ instance
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ class Converters {
36
+ @TypeConverter
37
+ fun fromString(value: String): List<String> {
38
+ val listType = object : TypeToken<List<String>>() {}.type
39
+ return Gson().fromJson(value, listType)
40
+ }
41
+
42
+ @TypeConverter
43
+ fun fromList(list: List<String>): String {
44
+ return Gson().toJson(list)
45
+ }
46
+ }
@@ -0,0 +1,12 @@
1
+ package {{PACKAGE_NAME}}.data
2
+
3
+ import androidx.room.Entity
4
+ import androidx.room.PrimaryKey
5
+
6
+ @Entity(tableName = "notes")
7
+ data class Note(
8
+ @PrimaryKey(autoGenerate = true) val id: Int = 0,
9
+ val content: String,
10
+ val tags: List<String>,
11
+ val timestamp: Long = System.currentTimeMillis()
12
+ )
@@ -0,0 +1,23 @@
1
+ package {{PACKAGE_NAME}}.data
2
+
3
+ import androidx.room.Dao
4
+ import androidx.room.Delete
5
+ import androidx.room.Insert
6
+ import androidx.room.OnConflictStrategy
7
+ import androidx.room.Query
8
+ import kotlinx.coroutines.flow.Flow
9
+
10
+ @Dao
11
+ interface NoteDao {
12
+ @Query("SELECT * FROM notes ORDER BY timestamp DESC")
13
+ fun getAllNotes(): Flow<List<Note>>
14
+
15
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
16
+ suspend fun insertNote(note: Note)
17
+
18
+ @Delete
19
+ suspend fun deleteNote(note: Note)
20
+
21
+ @Query("SELECT * FROM notes WHERE content LIKE '%' || :query || '%'")
22
+ fun searchNotes(query: String): Flow<List<Note>>
23
+ }
@@ -0,0 +1,26 @@
1
+ package {{PACKAGE_NAME}}.logic
2
+
3
+ class TaggingEngine {
4
+ fun autoTag(content: String): List<String> {
5
+ val tags = mutableListOf<String>()
6
+ val lowerContent = content.lowercase()
7
+
8
+ if (lowerContent.contains("work") || lowerContent.contains("meeting") || lowerContent.contains("job")) {
9
+ tags.add("work")
10
+ }
11
+ if (lowerContent.contains("idea") || lowerContent.contains("concept") || lowerContent.contains("think")) {
12
+ tags.add("idea")
13
+ }
14
+ if (lowerContent.contains("money") || lowerContent.contains("cost") || lowerContent.contains("price") || lowerContent.contains("$") || lowerContent.contains("€")) {
15
+ tags.add("money")
16
+ }
17
+ if (lowerContent.contains("bug") || lowerContent.contains("fix") || lowerContent.contains("error") || lowerContent.contains("crash")) {
18
+ tags.add("bug")
19
+ }
20
+ if (lowerContent.contains("todo") || lowerContent.contains("must") || lowerContent.contains("should")) {
21
+ tags.add("todo")
22
+ }
23
+
24
+ return tags
25
+ }
26
+ }
@@ -0,0 +1,185 @@
1
+ package {{PACKAGE_NAME}}.ui
2
+
3
+ import androidx.compose.foundation.layout.*
4
+ import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
5
+ import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
6
+ import androidx.compose.foundation.lazy.staggeredgrid.items
7
+ import androidx.compose.foundation.rememberScrollState
8
+ import androidx.compose.foundation.horizontalScroll
9
+ import androidx.compose.material.icons.Icons
10
+ import androidx.compose.material.icons.filled.Add
11
+ import androidx.compose.material.icons.filled.Delete
12
+ import androidx.compose.material3.*
13
+ import androidx.compose.runtime.*
14
+ import androidx.compose.ui.Alignment
15
+ import androidx.compose.ui.Modifier
16
+ import androidx.compose.ui.unit.dp
17
+ import androidx.compose.ui.window.Dialog
18
+ import androidx.lifecycle.viewmodel.compose.viewModel
19
+ import {{PACKAGE_NAME}}.data.Note
20
+ import java.text.SimpleDateFormat
21
+ import java.util.*
22
+
23
+ import androidx.compose.ui.graphics.Color
24
+
25
+ @OptIn(ExperimentalMaterial3Api::class)
26
+ @Composable
27
+ fun NotesScreen(viewModel: NotesViewModel = viewModel()) {
28
+ val searchQuery by viewModel.searchQuery.collectAsState()
29
+ val searchResults by viewModel.searchResults.collectAsState()
30
+
31
+ var showAddDialog by remember { mutableStateOf(false) }
32
+
33
+ Scaffold(
34
+ floatingActionButton = {
35
+ FloatingActionButton(
36
+ onClick = { showAddDialog = true },
37
+ containerColor = MaterialTheme.colorScheme.primary
38
+ ) {
39
+ Icon(Icons.Default.Add, contentDescription = "Add Note")
40
+ }
41
+ }
42
+ ) { padding ->
43
+ Column(modifier = Modifier.padding(padding).fillMaxSize()) {
44
+ // Header
45
+ Text(
46
+ text = "✅ DESUGARING ! 🚀 HOT ",
47
+ style = MaterialTheme.typography.displaySmall,
48
+ modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 20.dp)
49
+ )
50
+
51
+ // Search Bar
52
+ OutlinedTextField(
53
+ value = searchQuery,
54
+ onValueChange = viewModel::onSearchQueryChanged,
55
+ placeholder = { Text("Search note or ...") },
56
+ modifier = Modifier
57
+ .fillMaxWidth()
58
+ .padding(horizontal = 16.dp, vertical = 8.dp),
59
+ shape = MaterialTheme.shapes.extraLarge,
60
+ colors = TextFieldDefaults.colors(
61
+ focusedIndicatorColor = Color.Transparent,
62
+ unfocusedIndicatorColor = Color.Transparent
63
+ )
64
+ )
65
+
66
+ LazyVerticalStaggeredGrid(
67
+ columns = StaggeredGridCells.Fixed(2),
68
+ contentPadding = PaddingValues(16.dp),
69
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
70
+ verticalItemSpacing = 12.dp
71
+ ) {
72
+ items(searchResults) { note ->
73
+ NoteItem(note = note, onDelete = { viewModel.deleteNote(note) })
74
+ }
75
+ }
76
+ }
77
+
78
+ if (showAddDialog) {
79
+ AddNoteDialog(
80
+ onDismiss = { showAddDialog = false },
81
+ onAdd = { content ->
82
+ viewModel.addNote(content)
83
+ showAddDialog = false
84
+ },
85
+ viewModel = viewModel
86
+ )
87
+ }
88
+ }
89
+ }
90
+
91
+ @Composable
92
+ fun NoteItem(note: Note, onDelete: () -> Unit) {
93
+ Card(
94
+ colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant),
95
+ shape = MaterialTheme.shapes.medium
96
+ ) {
97
+ Column(modifier = Modifier.padding(12.dp)) {
98
+ Text(
99
+ text = note.content,
100
+ style = MaterialTheme.typography.bodyLarge,
101
+ color = MaterialTheme.colorScheme.onSurfaceVariant
102
+ )
103
+
104
+ if (note.tags.isNotEmpty()) {
105
+ Spacer(modifier = Modifier.height(12.dp))
106
+ Row(
107
+ modifier = Modifier.horizontalScroll(rememberScrollState()),
108
+ horizontalArrangement = Arrangement.spacedBy(4.dp)
109
+ ) {
110
+ note.tags.forEach { tag ->
111
+ AssistChip(
112
+ onClick = {},
113
+ label = { Text("#$tag", style = MaterialTheme.typography.labelSmall) },
114
+ modifier = Modifier.height(24.dp)
115
+ )
116
+ }
117
+ }
118
+ }
119
+
120
+ // Timestamp (optional, maybe too much clutter)
121
+ }
122
+ }
123
+ }
124
+
125
+ @Composable
126
+ fun AddNoteDialog(onDismiss: () -> Unit, onAdd: (String) -> Unit, viewModel: NotesViewModel) {
127
+ var content by remember { mutableStateOf("") }
128
+ // Live tagging
129
+ val suggestedTags = viewModel.getSuggestedTags(content)
130
+
131
+ AlertDialog(
132
+ onDismissRequest = onDismiss,
133
+ title = { Text("New Note") },
134
+ text = {
135
+ Column {
136
+ OutlinedTextField(
137
+ value = content,
138
+ onValueChange = { content = it },
139
+ placeholder = { Text("Type something...") },
140
+ minLines = 3,
141
+ modifier = Modifier.fillMaxWidth()
142
+ )
143
+
144
+ Spacer(modifier = Modifier.height(16.dp))
145
+
146
+ Text("Detected Tags:", style = MaterialTheme.typography.labelMedium)
147
+ if (suggestedTags.isEmpty()) {
148
+ Text("None", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.outline)
149
+ } else {
150
+ Row(
151
+ modifier = Modifier.horizontalScroll(rememberScrollState()),
152
+ horizontalArrangement = Arrangement.spacedBy(4.dp)
153
+ ) {
154
+ suggestedTags.forEach { tag ->
155
+ SuggestionChip(
156
+ onClick = {},
157
+ label = { Text(tag) }
158
+ )
159
+ }
160
+ }
161
+ }
162
+ }
163
+ },
164
+ confirmButton = {
165
+ Button(
166
+ onClick = { onAdd(content) },
167
+ enabled = content.isNotBlank()
168
+ ) {
169
+ Text("Save")
170
+ }
171
+ },
172
+ dismissButton = {
173
+ TextButton(onClick = onDismiss) {
174
+ Text("Cancel")
175
+ }
176
+ }
177
+ )
178
+ }
179
+
180
+
181
+
182
+
183
+
184
+
185
+ // Trigger hot reload 10
@@ -0,0 +1,58 @@
1
+ package {{PACKAGE_NAME}}.ui
2
+
3
+ import android.app.Application
4
+ import androidx.lifecycle.AndroidViewModel
5
+ import androidx.lifecycle.viewModelScope
6
+ import {{PACKAGE_NAME}}.data.AppDatabase
7
+ import {{PACKAGE_NAME}}.data.Note
8
+ import {{PACKAGE_NAME}}.logic.TaggingEngine
9
+ import kotlinx.coroutines.flow.MutableStateFlow
10
+ import kotlinx.coroutines.flow.SharingStarted
11
+ import kotlinx.coroutines.flow.StateFlow
12
+ import kotlinx.coroutines.flow.asStateFlow
13
+ import kotlinx.coroutines.flow.combine
14
+ import kotlinx.coroutines.flow.stateIn
15
+ import kotlinx.coroutines.launch
16
+
17
+ class NotesViewModel(application: Application) : AndroidViewModel(application) {
18
+ private val dao = AppDatabase.getDatabase(application).noteDao()
19
+ private val taggingEngine = TaggingEngine()
20
+
21
+ // For search
22
+ private val _searchQuery = MutableStateFlow("")
23
+ val searchQuery = _searchQuery.asStateFlow()
24
+
25
+ // All notes from DB
26
+ val notes = dao.getAllNotes()
27
+ .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
28
+
29
+ // Search results: Use combine to filter locally for responsiveness, or use DAO search
30
+ val searchResults = combine(notes, _searchQuery) { list, query ->
31
+ if (query.isBlank()) list
32
+ else list.filter { it.content.contains(query, ignoreCase = true) || it.tags.any { tag -> tag.contains(query, ignoreCase = true) } }
33
+ }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
34
+
35
+ fun onSearchQueryChanged(query: String) {
36
+ _searchQuery.value = query
37
+ }
38
+
39
+ fun addNote(content: String) {
40
+ if (content.isBlank()) return
41
+ val tags = taggingEngine.autoTag(content)
42
+ val note = Note(content = content, tags = tags)
43
+ viewModelScope.launch {
44
+ dao.insertNote(note)
45
+ }
46
+ }
47
+
48
+ fun deleteNote(note: Note) {
49
+ viewModelScope.launch {
50
+ dao.deleteNote(note)
51
+ }
52
+ }
53
+
54
+ // Trigger full build for client update 7 (Fix Duplicate Renderers)
55
+ fun getSuggestedTags(content: String): List<String> {
56
+ return taggingEngine.autoTag(content)
57
+ }
58
+ }
@@ -0,0 +1,12 @@
1
+ package {{PACKAGE_NAME}}.ui
2
+
3
+ import androidx.compose.foundation.layout.Column
4
+ import androidx.compose.material3.Text
5
+ import androidx.compose.runtime.Composable
6
+
7
+ @Composable
8
+ fun TestScreen() {
9
+ Column {
10
+ Text("Hello Test 12 - HOT RELOAD TEST")
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <color name="purple_200">#FFBB86FC</color>
4
+ <color name="purple_500">#FF6200EE</color>
5
+ <color name="purple_700">#FF3700B3</color>
6
+ <color name="teal_200">#FF03DAC5</color>
7
+ <color name="teal_700">#FF018786</color>
8
+ <color name="black">#FF000000</color>
9
+ <color name="white">#FFFFFFFF</color>
10
+ </resources>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <string name="app_name">{{PROJECT_NAME}}</string>
4
+ </resources>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <style name="Theme.{{THEME_NAME}}" parent="Theme.AppCompat.Light.NoActionBar">
4
+ <!-- Customize your theme here -->
5
+ <item name="colorPrimary">@color/purple_500</item>
6
+ <item name="colorPrimaryDark">@color/purple_700</item>
7
+ <item name="colorAccent">@color/teal_200</item>
8
+ </style>
9
+ </resources>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <network-security-config>
3
+ <base-config cleartextTrafficPermitted="true">
4
+ <trust-anchors>
5
+ <certificates src="system" />
6
+ </trust-anchors>
7
+ </base-config>
8
+ </network-security-config>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <paths xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <cache-path name="cache" path="." />
4
+ </paths>