From 4b3e9eae6f7d322ef49de60ff997b711ac86e386 Mon Sep 17 00:00:00 2001 From: Jack <231938068+digital-coder-jack@users.noreply.github.com> Date: Thu, 6 Aug 2026 09:42:38 +0530 Subject: [PATCH] Delete api/Android directory --- api/Android/.gitignore | 11 - api/Android/app/build.gradle.kts | 109 --- api/Android/app/proguard-rules.pro | 16 - api/Android/app/src/main/AndroidManifest.xml | 29 - .../java/com/ainotebook/app/AiNotebookApp.kt | 39 -- .../java/com/ainotebook/app/MainActivity.kt | 54 -- .../java/com/ainotebook/app/data/ApiClient.kt | 72 -- .../com/ainotebook/app/data/ApiService.kt | 93 --- .../java/com/ainotebook/app/data/Models.kt | 204 ------ .../com/ainotebook/app/data/NetworkMonitor.kt | 66 -- .../com/ainotebook/app/data/Repository.kt | 134 ---- .../com/ainotebook/app/data/SessionStore.kt | 51 -- .../com/ainotebook/app/data/StreamClient.kt | 414 ----------- .../ainotebook/app/data/ThemePreferences.kt | 61 -- .../java/com/ainotebook/app/ui/AppLocals.kt | 17 - .../main/java/com/ainotebook/app/ui/AppNav.kt | 223 ------ .../com/ainotebook/app/ui/AuthViewModel.kt | 100 --- .../com/ainotebook/app/ui/ChatViewModel.kt | 319 --------- .../ainotebook/app/ui/DashboardViewModel.kt | 39 -- .../com/ainotebook/app/ui/ProfileViewModel.kt | 79 --- .../com/ainotebook/app/ui/ToolsViewModel.kt | 58 -- .../com/ainotebook/app/ui/ViewModelFactory.kt | 23 - .../ainotebook/app/ui/components/Common.kt | 228 ------ .../ainotebook/app/ui/components/Effects.kt | 118 ---- .../ainotebook/app/ui/components/Markdown.kt | 429 ------------ .../ainotebook/app/ui/screens/ChatScreen.kt | 647 ------------------ .../ainotebook/app/ui/screens/ChatSheets.kt | 274 -------- .../app/ui/screens/DashboardScreen.kt | 362 ---------- .../ainotebook/app/ui/screens/LoginScreen.kt | 187 ----- .../app/ui/screens/ProfileScreen.kt | 348 ---------- .../ainotebook/app/ui/screens/SignupScreen.kt | 161 ----- .../ainotebook/app/ui/screens/ToolsScreen.kt | 328 --------- .../java/com/ainotebook/app/ui/theme/Theme.kt | 139 ---- .../src/main/res/drawable-nodpi/ss_logo.png | Bin 121222 -> 0 bytes .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 4047 -> 0 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 9285 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 4047 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2188 -> 0 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 4942 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2188 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 6415 -> 0 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 14214 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 6415 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 12029 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 25058 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 12029 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 17760 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 37769 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 17760 -> 0 bytes .../app/src/main/res/values/colors.xml | 6 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/themes.xml | 26 - api/Android/build.gradle.kts | 6 - api/Android/gradle.properties | 4 - api/Android/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - api/Android/gradlew | 249 ------- api/Android/gradlew.bat | 92 --- api/Android/settings.gradle.kts | 23 - 61 files changed, 5858 deletions(-) delete mode 100644 api/Android/.gitignore delete mode 100644 api/Android/app/build.gradle.kts delete mode 100644 api/Android/app/proguard-rules.pro delete mode 100644 api/Android/app/src/main/AndroidManifest.xml delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/AiNotebookApp.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/MainActivity.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/ApiClient.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/ApiService.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/Models.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/NetworkMonitor.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/Repository.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/SessionStore.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/StreamClient.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/data/ThemePreferences.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/AppLocals.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/AppNav.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/AuthViewModel.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/ChatViewModel.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/DashboardViewModel.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/ProfileViewModel.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/ToolsViewModel.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/ViewModelFactory.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/components/Common.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/components/Effects.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/components/Markdown.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatScreen.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatSheets.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/DashboardScreen.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/LoginScreen.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ProfileScreen.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/SignupScreen.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ToolsScreen.kt delete mode 100644 api/Android/app/src/main/java/com/ainotebook/app/ui/theme/Theme.kt delete mode 100644 api/Android/app/src/main/res/drawable-nodpi/ss_logo.png delete mode 100644 api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 api/Android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 api/Android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png delete mode 100644 api/Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 api/Android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 api/Android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png delete mode 100644 api/Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 api/Android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 api/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png delete mode 100644 api/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 api/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 api/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png delete mode 100644 api/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 api/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 api/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png delete mode 100644 api/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 api/Android/app/src/main/res/values/colors.xml delete mode 100644 api/Android/app/src/main/res/values/strings.xml delete mode 100644 api/Android/app/src/main/res/values/themes.xml delete mode 100644 api/Android/build.gradle.kts delete mode 100644 api/Android/gradle.properties delete mode 100644 api/Android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 api/Android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 api/Android/gradlew delete mode 100644 api/Android/gradlew.bat delete mode 100644 api/Android/settings.gradle.kts diff --git a/api/Android/.gitignore b/api/Android/.gitignore deleted file mode 100644 index fc783a2..0000000 --- a/api/Android/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# Android / Gradle build artifacts (machine-specific, never committed) -*.iml -.gradle/ -/local.properties -/.idea -.DS_Store -/build -app/build/ -captures/ -.externalNativeBuild/ -.cxx/ diff --git a/api/Android/app/build.gradle.kts b/api/Android/app/build.gradle.kts deleted file mode 100644 index 26c1d55..0000000 --- a/api/Android/app/build.gradle.kts +++ /dev/null @@ -1,109 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") - id("org.jetbrains.kotlin.plugin.serialization") -} - -android { - namespace = "com.ainotebook.app" - compileSdk = 34 - - defaultConfig { - applicationId = "com.ainotebook.app" - minSdk = 24 - targetSdk = 34 - versionCode = 2 - versionName = "1.1" - - vectorDrawables { - useSupportLibrary = true - } - - // Default backend URL. Override with the `apiBaseUrl` Gradle property - // (e.g. -PapiBaseUrl=https://your-backend.example.com) or per build - // type below. Falls back to the current production deployment. - val apiBaseUrl = (project.findProperty("apiBaseUrl") as String?) - ?: "https://study-sphere-ai-mwlq.vercel.app" - buildConfigField("String", "API_BASE_URL", "\"$apiBaseUrl\"") - } - - buildTypes { - debug { - // Point debug builds at your local/dev backend if you like. - val debugApiBaseUrl = (project.findProperty("apiBaseUrlDebug") as String?) - ?: (project.findProperty("apiBaseUrl") as String?) - ?: "https://study-sphere-ai-mwlq.vercel.app" - buildConfigField("String", "API_BASE_URL", "\"$debugApiBaseUrl\"") - } - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = "17" - } - buildFeatures { - compose = true - buildConfig = true - } - composeOptions { - kotlinCompilerExtensionVersion = "1.5.14" - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } -} - -dependencies { - val composeBom = platform("androidx.compose:compose-bom:2024.06.00") - implementation(composeBom) - - implementation("androidx.core:core-ktx:1.13.1") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.3") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.3") - implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.3") - implementation("androidx.activity:activity-compose:1.9.0") - - // Android 12+ Splash Screen API (backwards compatible) - implementation("androidx.core:core-splashscreen:1.0.1") - - // Compose - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-graphics") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3") - implementation("androidx.compose.material:material-icons-extended") - implementation("androidx.compose.animation:animation") - implementation("androidx.compose.animation:animation-graphics") - - // Navigation - implementation("androidx.navigation:navigation-compose:2.7.7") - - // Networking - implementation("com.squareup.okhttp3:okhttp:4.12.0") - implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") - implementation("com.squareup.retrofit2:retrofit:2.11.0") - - // JSON - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") - implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0") - - // Coroutines - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1") - - // DataStore for token persistence - implementation("androidx.datastore:datastore-preferences:1.1.1") - - debugImplementation("androidx.compose.ui:ui-tooling") -} diff --git a/api/Android/app/proguard-rules.pro b/api/Android/app/proguard-rules.pro deleted file mode 100644 index be634bf..0000000 --- a/api/Android/app/proguard-rules.pro +++ /dev/null @@ -1,16 +0,0 @@ -# Keep kotlinx.serialization --keepattributes *Annotation*, InnerClasses --dontnote kotlinx.serialization.AnnotationsKt --keepclassmembers class kotlinx.serialization.json.** { - *** Companion; -} --keepclasseswithmembers class kotlinx.serialization.json.** { - kotlinx.serialization.KSerializer serializer(...); -} --keep,includedescriptorclasses class com.ainotebook.app.**$$serializer { *; } --keepclassmembers class com.ainotebook.app.** { - *** Companion; -} --keepclasseswithmembers class com.ainotebook.app.** { - kotlinx.serialization.KSerializer serializer(...); -} diff --git a/api/Android/app/src/main/AndroidManifest.xml b/api/Android/app/src/main/AndroidManifest.xml deleted file mode 100644 index b93364d..0000000 --- a/api/Android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/api/Android/app/src/main/java/com/ainotebook/app/AiNotebookApp.kt b/api/Android/app/src/main/java/com/ainotebook/app/AiNotebookApp.kt deleted file mode 100644 index 660a180..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/AiNotebookApp.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.ainotebook.app - -import android.app.Application -import com.ainotebook.app.data.ApiClient -import com.ainotebook.app.data.NetworkMonitor -import com.ainotebook.app.data.Repository -import com.ainotebook.app.data.SessionStore -import com.ainotebook.app.data.ThemePreferences - -/** - * Application class that wires up the singletons (session store, API client, - * repository) used across the app. - */ -class AiNotebookApp : Application() { - - lateinit var session: SessionStore - private set - lateinit var repository: Repository - private set - lateinit var themePrefs: ThemePreferences - private set - lateinit var networkMonitor: NetworkMonitor - private set - - override fun onCreate() { - super.onCreate() - session = SessionStore(this) - ApiClient.init(session) - repository = Repository(session) - themePrefs = ThemePreferences(this) - networkMonitor = NetworkMonitor(this) - instance = this - } - - companion object { - lateinit var instance: AiNotebookApp - private set - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/MainActivity.kt b/api/Android/app/src/main/java/com/ainotebook/app/MainActivity.kt deleted file mode 100644 index e25eb0d..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/MainActivity.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.ainotebook.app - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.runtime.getValue -import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.ainotebook.app.data.ThemeMode -import com.ainotebook.app.ui.AppRoot -import com.ainotebook.app.ui.LocalAppPrefs -import com.ainotebook.app.ui.LocalNetworkMonitor -import com.ainotebook.app.ui.theme.AiNotebookTheme - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - // Install the AndroidX splash screen before super.onCreate() so the - // branded launch screen shows the official logo while the app warms up. - val splash = installSplashScreen() - super.onCreate(savedInstanceState) - enableEdgeToEdge() - - val app = application as AiNotebookApp - val repo = app.repository - val prefs = app.themePrefs - val network = app.networkMonitor - - // Keep the splash on-screen for a brief, deliberate beat (premium feel). - var keepSplash = true - splash.setKeepOnScreenCondition { keepSplash } - window.decorView.postDelayed({ keepSplash = false }, 350) - - setContent { - val mode by prefs.themeMode.collectAsStateWithLifecycle(initialValue = ThemeMode.DARK) - val dynamic by prefs.dynamicColor.collectAsStateWithLifecycle(initialValue = false) - - val dark = when (mode) { - ThemeMode.LIGHT -> false - ThemeMode.DARK -> true - ThemeMode.SYSTEM -> androidx.compose.foundation.isSystemInDarkTheme() - } - - AiNotebookTheme(darkTheme = dark, dynamicColor = dynamic) { - androidx.compose.runtime.CompositionLocalProvider( - LocalAppPrefs provides prefs, - LocalNetworkMonitor provides network - ) { - AppRoot(repo) - } - } - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/ApiClient.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/ApiClient.kt deleted file mode 100644 index 2b0b159..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/ApiClient.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.ainotebook.app.data - -import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import com.ainotebook.app.BuildConfig -import kotlinx.coroutines.runBlocking -import kotlinx.serialization.json.Json -import okhttp3.Interceptor -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import retrofit2.Retrofit -import java.util.concurrent.TimeUnit - -/** - * Builds the shared OkHttp + Retrofit stack. The auth interceptor injects the - * current JWT (read from [SessionStore]) into every request's Authorization - * header, matching the web app's `Bearer ` scheme. - */ -object ApiClient { - - private const val BASE = BuildConfig.API_BASE_URL - - val json = Json { - ignoreUnknownKeys = true - coerceInputValues = true - isLenient = true - } - - @Volatile - private var service: ApiService? = null - - @Volatile - lateinit var okHttp: OkHttpClient - private set - - fun baseUrl(): String = if (BASE.endsWith("/")) BASE else "$BASE/" - - fun init(session: SessionStore) { - val authInterceptor = Interceptor { chain -> - val token = runBlocking { session.token() } - val builder = chain.request().newBuilder() - if (!token.isNullOrBlank()) { - builder.addHeader("Authorization", "Bearer $token") - } - chain.proceed(builder.build()) - } - - val logging = HttpLoggingInterceptor().apply { - level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BASIC - else HttpLoggingInterceptor.Level.NONE - } - - okHttp = OkHttpClient.Builder() - .addInterceptor(authInterceptor) - .addInterceptor(logging) - .connectTimeout(30, TimeUnit.SECONDS) - .readTimeout(120, TimeUnit.SECONDS) // long for SSE streaming - .writeTimeout(30, TimeUnit.SECONDS) - .build() - - val contentType = "application/json".toMediaType() - service = Retrofit.Builder() - .baseUrl(baseUrl()) - .client(okHttp) - .addConverterFactory(json.asConverterFactory(contentType)) - .build() - .create(ApiService::class.java) - } - - val api: ApiService - get() = service ?: error("ApiClient.init() must be called first") -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/ApiService.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/ApiService.kt deleted file mode 100644 index 2159ad4..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/ApiService.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.ainotebook.app.data - -import retrofit2.http.Body -import retrofit2.http.DELETE -import retrofit2.http.GET -import retrofit2.http.POST -import retrofit2.http.PUT -import retrofit2.http.Path - -/** - * Retrofit declaration of the AI Notebook REST API. - * (Streaming chat is handled separately via raw OkHttp in [StreamClient].) - */ -interface ApiService { - - /* ---------- Auth ---------- */ - @POST("api/auth/login") - suspend fun login(@Body body: LoginRequest): AuthResponse - - @POST("api/auth/signup") - suspend fun signup(@Body body: SignupRequest): AuthResponse - - @POST("api/auth/guest") - suspend fun guest(): AuthResponse - - @GET("api/auth/me") - suspend fun me(): MeResponse - - @PUT("api/auth/profile") - suspend fun updateProfile(@Body body: ProfileRequest): MeResponse - - @PUT("api/auth/change-password") - suspend fun changePassword(@Body body: ChangePasswordRequest): MessageResponse - - @DELETE("api/auth/account") - suspend fun deleteAccount(): MessageResponse - - /* ---------- Chats (CRUD ONLY) ---------- - * - * SINGLE SOURCE OF TRUTH: - * Sending a message and receiving an AI reply is STREAMING-ONLY and lives - * exclusively in [StreamClient] via POST api/chats/{id}/stream (SSE). - * - * The backend exposes NO REST "send message" endpoint. Do NOT add a - * `@POST("api/chats/{id}")` here — that route only accepts GET/PUT/DELETE - * server-side and would fail with 405 Method Not Allowed / HTML fallback. - * Keep these declarations limited to chat metadata CRUD. - */ - @GET("api/chats") - suspend fun listChats(): ChatListResponse - - @POST("api/chats") - suspend fun newChat(@Body body: NewChatRequest): ChatResponse - - @GET("api/chats/{id}") - suspend fun getChat(@Path("id") id: Int): ChatDetailResponse - - @PUT("api/chats/{id}") - suspend fun renameChat(@Path("id") id: Int, @Body body: RenameChatRequest): ChatResponse - - @DELETE("api/chats/{id}") - suspend fun deleteChat(@Path("id") id: Int): Map - - /* ---------- AI model selection ---------- */ - @GET("api/ai/models") - suspend fun aiModels(): ModelsResponse - - @PUT("api/ai/model") - suspend fun setAiModel(@Body body: SetModelRequest): SetModelResponse - - /* ---------- Dashboard ---------- */ - @GET("api/stats") - suspend fun stats(): Stats - - /* ---------- Study tools ---------- */ - @POST("api/tools/notes") - suspend fun generateNotes(@Body body: TopicRequest): NotesResponse - - @POST("api/tools/quiz") - suspend fun generateQuiz(@Body body: QuizRequest): QuizGenResponse - - @POST("api/tools/flashcards") - suspend fun generateFlashcards(@Body body: FlashRequest): FlashResponse - - @POST("api/tools/plan") - suspend fun generatePlan(@Body body: PlanRequest): PlanResponse - - @POST("api/tools/summarize") - suspend fun summarize(@Body body: TextRequest): SummaryResponse - - @POST("api/tools/homework") - suspend fun homework(@Body body: QuestionRequest): HomeworkResponse -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/Models.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/Models.kt deleted file mode 100644 index 70f5ea4..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/Models.kt +++ /dev/null @@ -1,204 +0,0 @@ -package com.ainotebook.app.data - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.JsonElement - -/* ========================================================================= - * Data models that mirror the AI Notebook FastAPI backend contracts. - * ========================================================================= */ - -@Serializable -data class User( - val id: Int = 0, - val name: String = "", - val username: String? = null, - val email: String = "", - val created_at: String? = null, - val last_login: String? = null, - val is_guest: Boolean = false -) - -@Serializable -data class AuthResponse( - val token: String = "", - val user: User = User(), - val guest: Boolean = false -) - -@Serializable -data class MeResponse(val user: User = User()) - -@Serializable -data class MessageResponse(val message: String = "") - -/* ---------- Auth request bodies ---------- */ -@Serializable -data class LoginRequest(val identifier: String, val password: String) - -@Serializable -data class SignupRequest( - val name: String, - val username: String, - val email: String, - val password: String, - val confirm_password: String -) - -@Serializable -data class ProfileRequest(val name: String) - -@Serializable -data class ChangePasswordRequest( - val current_password: String, - val new_password: String -) - -/* ---------- Chat ---------- */ -@Serializable -data class Chat( - val id: Int = 0, - val title: String = "New Chat", - val created_at: String? = null, - val updated_at: String? = null -) - -@Serializable -data class ChatResponse(val chat: Chat = Chat()) - -@Serializable -data class ChatListResponse(val chats: List = emptyList()) - -@Serializable -data class ChatMessage( - val id: Int = 0, - val role: String = "user", - val content: String = "", - val created_at: String? = null -) - -@Serializable -data class ChatDetailResponse( - val chat: Chat = Chat(), - val messages: List = emptyList() -) - -@Serializable -data class NewChatRequest(val title: String? = null) - -@Serializable -data class RenameChatRequest(val title: String) - -@Serializable -data class StreamRequest( - val content: String, - val model: String? = null // optional per-message provider override -) - -/* ---------- AI model selection (matches /api/ai/models + /api/ai/model) ---------- */ -@Serializable -data class AiProvider( - val id: String = "", - @SerialName("label") - val name: String = "", // ← backend sends "label" not "name", this fixes it - val configured: Boolean = false -) - -@Serializable -data class ModelsResponse( - val selected: String = "auto", - val options: List = listOf("auto"), - val providers: List = emptyList(), - @SerialName("display_names") - val displayNames: Map = emptyMap() // ← ADD THIS -) - -@Serializable -data class SetModelRequest(val model: String) - -@Serializable -data class SetModelResponse(val selected: String = "auto") - -/* ---------- Dashboard stats ---------- */ -@Serializable -data class Stats( - val total_chats: Int = 0, - val total_messages: Int = 0, - val ai_responses: Int = 0, - val notes: Int = 0, - val quizzes: Int = 0, - val recent_chats: List = emptyList(), - val daily_activity: List = emptyList() -) - -@Serializable -data class DailyActivity( - val day: String = "", - val count: Int = 0 -) - -/* ---------- Study tools ---------- */ -@Serializable -data class TopicRequest(val topic: String) - -@Serializable -data class QuizRequest(val topic: String, val num_questions: Int = 5) - -@Serializable -data class FlashRequest(val topic: String, val num_cards: Int = 8) - -@Serializable -data class PlanRequest(val goal: String, val days: Int = 7) - -@Serializable -data class TextRequest(val text: String) - -@Serializable -data class QuestionRequest(val question: String) - -@Serializable -data class NotesResponse( - val id: Int = 0, - val topic: String = "", - val content: String = "" -) - -@Serializable -data class QuizQuestion( - val question: String = "", - val options: List = emptyList(), - val answer: Int = 0, - val explanation: String = "" -) - -@Serializable -data class QuizGenResponse( - val id: Int = 0, - val topic: String = "", - val questions: List = emptyList() -) - -@Serializable -data class Flashcard( - val front: String = "", - val back: String = "" -) - -@Serializable -data class FlashResponse( - val topic: String = "", - val cards: List = emptyList() -) - -@Serializable -data class PlanResponse( - val goal: String = "", - val days: Int = 0, - val content: String = "" -) - -@Serializable -data class SummaryResponse(val summary: String = "") - -@Serializable -data class HomeworkResponse(val answer: String = "") diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/NetworkMonitor.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/NetworkMonitor.kt deleted file mode 100644 index ab8f54d..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/NetworkMonitor.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.ainotebook.app.data - -import android.content.Context -import android.net.ConnectivityManager -import android.net.Network -import android.net.NetworkCapabilities -import android.net.NetworkRequest -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.distinctUntilChanged - -/** - * Observes the device's connectivity state and emits `true` while the app has a - * validated internet connection. Used to drive the in-app offline banner and to - * surface graceful "you're offline" states (premium reliability behaviour, like - * ChatGPT/Gemini), without changing any networking/API logic. - */ -class NetworkMonitor(context: Context) { - - private val connectivityManager = - context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - - val isOnline: Flow = callbackFlow { - val callback = object : ConnectivityManager.NetworkCallback() { - private val networks = mutableSetOf() - - override fun onAvailable(network: Network) { - networks += network - trySend(true) - } - - override fun onLost(network: Network) { - networks -= network - trySend(networks.isNotEmpty()) - } - - override fun onCapabilitiesChanged( - network: Network, - caps: NetworkCapabilities - ) { - val hasInternet = - caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && - caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) - if (hasInternet) networks += network else networks -= network - trySend(networks.isNotEmpty()) - } - } - - // Emit the current state immediately so the UI starts in the right state. - trySend(currentlyOnline()) - - val request = NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build() - connectivityManager.registerNetworkCallback(request, callback) - - awaitClose { connectivityManager.unregisterNetworkCallback(callback) } - }.distinctUntilChanged() - - fun currentlyOnline(): Boolean { - val active = connectivityManager.activeNetwork ?: return false - val caps = connectivityManager.getNetworkCapabilities(active) ?: return false - return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/Repository.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/Repository.kt deleted file mode 100644 index 262cf2e..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/Repository.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.ainotebook.app.data - -import kotlinx.coroutines.flow.Flow - -/** - * Thin repository wrapping [ApiClient] + [SessionStore]. Holds the session - * lifecycle so view models stay free of networking details. - * - * All network calls are suspend (main-safe via ApiClient's dispatcher); - * [streamMessage] intentionally returns a cold [Flow] and is NOT suspend. - */ -class Repository(private val session: SessionStore) { - - val tokenFlow get() = session.tokenFlow - val userFlow get() = session.userFlow - - suspend fun currentToken(): String? = session.token() - - /* ---------- Auth ---------- */ - suspend fun login(identifier: String, password: String): User { - val res = ApiClient.api.login(LoginRequest(identifier, password)) - session.save(res.token, res.user) - return res.user - } - - suspend fun signup( - name: String, username: String, email: String, - password: String, confirm: String - ): User { - val res = ApiClient.api.signup( - SignupRequest(name, username, email, password, confirm) - ) - session.save(res.token, res.user) - return res.user - } - - suspend fun guest(): User { - val res = ApiClient.api.guest() - // Persist the guest flag locally in case the backend omits it, - // but keep every other field exactly as the server returned it. - val guestUser = res.user.copy(is_guest = true) - session.save(res.token, guestUser) - return guestUser - } - - suspend fun me(): User { - val res = ApiClient.api.me() - session.saveUser(res.user) - return res.user - } - - suspend fun updateProfile(name: String): User { - val res = ApiClient.api.updateProfile(ProfileRequest(name)) - session.saveUser(res.user) - return res.user - } - - suspend fun changePassword(current: String, new: String): String = - ApiClient.api.changePassword(ChangePasswordRequest(current, new)).message - - /** - * Deletes the account server-side, then ALWAYS clears the local session. - * The session is cleared in a `finally` block so a failed/partial network - * call can never leave a stale token or user behind. - */ - suspend fun deleteAccount(): String { - return try { - ApiClient.api.deleteAccount().message - } finally { - session.clear() - } - } - - /** Clears the local session. Resilient: never propagates a clear failure. */ - suspend fun logout() { - session.clear() - } - - /* ---------- Chats ---------- */ - suspend fun listChats() = ApiClient.api.listChats().chats - - suspend fun newChat(title: String? = null) = - ApiClient.api.newChat(NewChatRequest(title)).chat - - suspend fun getChat(id: Int) = ApiClient.api.getChat(id) - - suspend fun renameChat(id: Int, title: String) = - ApiClient.api.renameChat(id, RenameChatRequest(title)).chat - - suspend fun deleteChat(id: Int) = ApiClient.api.deleteChat(id) - - /** - * Streams an assistant reply for [chatId]. Returns a cold [Flow] so the - * caller controls collection/cancellation. If [token] is null, the stored - * session token is used to keep streaming consistent with REST calls. - */ - suspend fun streamMessage( - chatId: Int, - content: String, - token: String? = null, - model: String? = null - ): Flow { - val authToken = token ?: session.token() - return StreamClient.streamMessage(chatId, content, authToken, model) - } - - /* ---------- AI model selection ---------- */ - suspend fun aiModels() = ApiClient.api.aiModels() - - suspend fun setAiModel(model: String) = - ApiClient.api.setAiModel(SetModelRequest(model)).selected - - /* ---------- Dashboard ---------- */ - suspend fun stats() = ApiClient.api.stats() - - /* ---------- Study tools ---------- */ - suspend fun generateNotes(topic: String) = - ApiClient.api.generateNotes(TopicRequest(topic)) - - suspend fun generateQuiz(topic: String, n: Int) = - ApiClient.api.generateQuiz(QuizRequest(topic, n)) - - suspend fun generateFlashcards(topic: String, n: Int) = - ApiClient.api.generateFlashcards(FlashRequest(topic, n)) - - suspend fun generatePlan(goal: String, days: Int) = - ApiClient.api.generatePlan(PlanRequest(goal, days)) - - suspend fun summarize(text: String) = - ApiClient.api.summarize(TextRequest(text)) - - suspend fun homework(question: String) = - ApiClient.api.homework(QuestionRequest(question)) -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/SessionStore.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/SessionStore.kt deleted file mode 100644 index 37495b1..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/SessionStore.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.ainotebook.app.data - -import android.content.Context -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.preferencesDataStore -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map -import kotlinx.serialization.json.Json - -private val Context.dataStore by preferencesDataStore(name = "ai_notebook_session") - -/** - * Persists the JWT token and the cached user profile using Jetpack DataStore. - */ -class SessionStore(private val context: Context) { - - companion object { - private val TOKEN_KEY = stringPreferencesKey("ss_token") - private val USER_KEY = stringPreferencesKey("ss_user") - private val json = Json { ignoreUnknownKeys = true } - } - - val tokenFlow: Flow = context.dataStore.data.map { it[TOKEN_KEY] } - - val userFlow: Flow = context.dataStore.data.map { prefs -> - prefs[USER_KEY]?.let { - runCatching { json.decodeFromString(it) }.getOrNull() - } - } - - suspend fun token(): String? = context.dataStore.data.first()[TOKEN_KEY] - - suspend fun save(token: String, user: User) { - context.dataStore.edit { prefs -> - prefs[TOKEN_KEY] = token - prefs[USER_KEY] = json.encodeToString(User.serializer(), user) - } - } - - suspend fun saveUser(user: User) { - context.dataStore.edit { prefs -> - prefs[USER_KEY] = json.encodeToString(User.serializer(), user) - } - } - - suspend fun clear() { - context.dataStore.edit { it.clear() } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/StreamClient.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/StreamClient.kt deleted file mode 100644 index 78bcf12..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/StreamClient.kt +++ /dev/null @@ -1,414 +0,0 @@ -package com.ainotebook.app.data - -import kotlinx.coroutines.currentCoroutineContext -import kotlinx.coroutines.isActive -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.channels.ProducerScope -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.flowOn -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonArray -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.booleanOrNull -import kotlinx.serialization.json.contentOrNull -import kotlinx.serialization.json.intOrNull -import kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import okhttp3.Call -import okhttp3.MediaType.Companion.toMediaType -import okhttp3.Request -import okhttp3.RequestBody.Companion.toRequestBody -import okio.BufferedSource -import java.io.IOException -import java.io.InterruptedIOException -import java.net.SocketTimeoutException -import java.util.concurrent.TimeUnit - -/** - * Consumes the backend's Server-Sent Events stream from - * POST /api/chats/{id}/stream and emits incremental tokens. - * - * Provider-agnostic: tolerates the slightly different SSE payload shapes used - * by Groq, Gemini and Kimi (and OpenAI-compatible gateways), e.g. - * data: {"token":"..."} - * data: {"delta":"..."} - * data: {"content":"..."} - * data: {"text":"..."} - * data: {"choices":[{"delta":{"content":"..."}}]} (OpenAI / Groq / Kimi) - * data: {"done":true,"message_id":123} - * data: [DONE] (OpenAI-style sentinel) - * - * Guarantees: - * - Always returns a clean Flow. - * - Never throws into the collector; failures are emitted as StreamEvent.Error. - * - Always reaches exactly one terminal event (Done or Error) before closing. - * - Cancels the underlying HTTP call on close so no socket leaks. - */ -sealed class StreamEvent { - data class Token(val text: String) : StreamEvent() - data class Done(val messageId: Int?) : StreamEvent() - data class Error(val message: String, val retryable: Boolean = false) : StreamEvent() -} - -object StreamClient { - - private val json = Json { ignoreUnknownKeys = true; isLenient = true } - - // Tuning knobs - private const val MAX_RETRIES = 2 - private const val INITIAL_BACKOFF_MS = 600L - private const val MAX_BACKOFF_MS = 4_000L - private const val CALL_TIMEOUT_SECONDS = 0L // 0 = no overall cap (streaming can be long) - private const val READ_TIMEOUT_SECONDS = 90L // idle read timeout between tokens - private const val CONNECT_TIMEOUT_SECONDS = 20L - - fun streamMessage( - chatId: Int, - content: String, - token: String?, - model: String? = null - ): Flow = callbackFlow { - // Tracks whether we already emitted Done/Error so close() is always clean. - var terminated = false - - fun emitTerminal(event: StreamEvent) { - if (terminated) return - terminated = true - if (!isClosedForSend) trySend(event) - } - - // ---- Build request once; reused across retries ---- - val url = ApiClient.baseUrl() + "api/chats/$chatId/stream" - val mediaType = "application/json".toMediaType() - // Only send an override when a concrete provider is chosen ("auto" - // lets the backend pick via the fallback chain, matching the web app). - val override = model?.takeIf { it.isNotBlank() && it != "auto" } - val payload = runCatching { - json.encodeToString(StreamRequest.serializer(), StreamRequest(content, override)) - }.getOrElse { - emitTerminal(StreamEvent.Error("Failed to build request: ${it.message}")) - close() - return@callbackFlow - } - - // Per-request OkHttp client with streaming-friendly timeouts. - val streamingClient = ApiClient.okHttp.newBuilder() - .callTimeout(CALL_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .connectTimeout(CONNECT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .readTimeout(READ_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .retryOnConnectionFailure(true) - .build() - - fun buildCall(): Call { - val reqBuilder = Request.Builder() - .url(url) - .addHeader("Accept", "text/event-stream") - .addHeader("Cache-Control", "no-cache") - .post(payload.toRequestBody(mediaType)) - if (!token.isNullOrBlank()) { - reqBuilder.addHeader("Authorization", "Bearer $token") - } - return streamingClient.newCall(reqBuilder.build()) - } - - // FIX 1: Removed the illegal nested `object StreamClient { ... }` block. - // `activeCall` is simply a local variable captured by the awaitClose lambda. - var activeCall: Call? = null - - // ---- Retry loop ---- - var attempt = 0 - var backoff = INITIAL_BACKOFF_MS - - while (attempt <= MAX_RETRIES && !terminated && currentCoroutineContext().isActive) { - - // Result of a single attempt: DONE = finished (terminal emitted or success), - // RETRY = retryable transient failure. - val attemptOutcome: AttemptResult = try { - - // FIX 2: Removed the duplicate `val call = buildCall()` declaration. - val call = buildCall() - activeCall = call - - call.execute().use { response -> - when { - response.code == 401 || response.code == 403 -> { - emitTerminal(StreamEvent.Error("Unauthorized (${response.code})", retryable = false)) - AttemptResult.DONE - } - response.code == 429 || response.code in 500..599 -> { - // Server-side transient — worth retrying. - AttemptResult.RETRY("Server busy (${response.code})") - } - !response.isSuccessful -> { - val errorBody = runCatching { - response.body?.string() - }.getOrNull() - - android.util.Log.e( - "API_ERROR", - "Code=${response.code} Body=$errorBody" - ) - - emitTerminal( - StreamEvent.Error( - "Request failed (${response.code}): $errorBody", - retryable = false - ) - ) - AttemptResult.DONE - } - else -> { - val source = response.body?.source() - if (source == null) { - emitTerminal(StreamEvent.Error("Empty response", retryable = false)) - AttemptResult.DONE - } else { - consumeStream(source, ::emitTerminal) { ev -> if (!isClosedForSend) trySend(ev) } - } - } - } - } - } catch (e: CancellationException) { - // Flow collector cancelled — do not emit, just stop. - throw e - } catch (e: SocketTimeoutException) { - AttemptResult.RETRY("Network timeout") - } catch (e: InterruptedIOException) { - AttemptResult.RETRY("Connection interrupted") - } catch (e: IOException) { - AttemptResult.RETRY(e.message ?: "Network error") - } catch (e: Exception) { - // Unexpected — never crash silently. - emitTerminal(StreamEvent.Error(e.message ?: "Stream interrupted", retryable = false)) - AttemptResult.DONE - } - - when (attemptOutcome) { - is AttemptResult.DONE -> break - is AttemptResult.RETRY -> { - attempt++ - if (attempt > MAX_RETRIES || !isActive) { - emitTerminal(StreamEvent.Error(attemptOutcome.reason, retryable = true)) - break - } - // Backoff before retrying; abort early if collector cancelled. - val waited = runCatching { delay(backoff) }.isSuccess - if (!waited || !isActive) break - backoff = (backoff * 2).coerceAtMost(MAX_BACKOFF_MS) - } - } - } - - // Safety net: if loop exited without any terminal event, emit Done so the - // collector is never left hanging (prevents perpetual "Streaming…" state). - if (!terminated) { - emitTerminal(StreamEvent.Done(null)) - } - - close() - - awaitClose { - runCatching { activeCall?.cancel() } - } - }.flowOn(Dispatchers.IO) - - /** - * Reads and parses the SSE body line-by-line. Emits Token/Done via [emit] and - * routes the single terminal event through [emitTerminal]. - * Returns DONE on a clean end, or RETRY if the stream ends abruptly without - * a terminal marker (so the caller can retry). - */ - private fun consumeStream( - source: BufferedSource, - emitTerminal: (StreamEvent) -> Unit, - emit: (StreamEvent) -> Unit - ): AttemptResult { - var sawDone = false - var sawAnyToken = false - // Buffer for multi-line SSE `data:` accumulation (Gemini can split frames). - val dataBuffer = StringBuilder() - - try { - while (true) { - val line = source.readUtf8Line() ?: break - - // Blank line == end of one SSE event; flush buffered data. - if (line.isBlank()) { - if (dataBuffer.isNotEmpty()) { - val handled = handleData(dataBuffer.toString().trim(), emitTerminal, emit) - if (handled.token) sawAnyToken = true - if (handled.done) { sawDone = true; break } - dataBuffer.setLength(0) - } - continue - } - - // Ignore SSE comments / event/id fields we don't use. - if (line.startsWith(":")) continue - if (!line.startsWith("data:")) continue - - val chunk = line.removePrefix("data:").trim() - if (chunk.isEmpty()) continue - - // OpenAI-style termination sentinel. - if (chunk == "[DONE]") { sawDone = true; break } - - // Accumulate; flushed on blank line, but also try eager parse - // for single-line JSON frames (Groq/Kimi/most providers). - if (dataBuffer.isEmpty()) { - val handled = handleData(chunk, emitTerminal, emit) - if (handled.token) sawAnyToken = true - if (handled.done) { sawDone = true; break } - // If it wasn't valid JSON on its own, buffer for multi-line join. - if (!handled.parsed) dataBuffer.append(chunk) - } else { - dataBuffer.append(chunk) - } - } - } catch (e: SocketTimeoutException) { - return AttemptResult.RETRY("Network timeout") - } catch (e: IOException) { - // Abrupt end: retry only if we never got a clean terminal. - return if (sawDone) AttemptResult.DONE else AttemptResult.RETRY(e.message ?: "Connection lost") - } - - if (sawDone) { - emitTerminal(StreamEvent.Done(null)) - return AttemptResult.DONE - } - // Stream ended without explicit [DONE]/done flag. - return if (sawAnyToken) { - // We received content but no terminal marker — treat as complete. - emitTerminal(StreamEvent.Done(null)) - AttemptResult.DONE - } else { - // Nothing at all — let caller retry. - AttemptResult.RETRY("Stream ended unexpectedly") - } - } - - private data class DataResult( - val parsed: Boolean, - val token: Boolean, - val done: Boolean - ) - - /** - * Parses one SSE data payload across provider formats and emits the - * appropriate event. Returns whether it parsed and what it contained. - */ - private fun handleData( - data: String, - emitTerminal: (StreamEvent) -> Unit, - emit: (StreamEvent) -> Unit - ): DataResult { - if (data.isEmpty()) return DataResult(parsed = false, token = false, done = false) - if (data == "[DONE]") { - emitTerminal(StreamEvent.Done(null)) - return DataResult(parsed = true, token = false, done = true) - } - - val obj = runCatching { json.parseToJsonElement(data).jsonObject }.getOrNull() - ?: return DataResult(parsed = false, token = false, done = false) - - // Explicit completion flag (backend / Gemini finishReason). - val doneFlag = obj["done"]?.jsonPrimitive?.booleanOrNull == true - val finishReason = obj["finish_reason"]?.jsonPrimitive?.contentOrNull - ?: obj["finishReason"]?.jsonPrimitive?.contentOrNull - ?: extractChoiceFinishReason(obj) - - // Provider error frame inside the stream. - extractError(obj)?.let { errMsg -> - emitTerminal(StreamEvent.Error(errMsg, retryable = false)) - return DataResult(parsed = true, token = false, done = true) - } - - // Extract token text across known shapes. - val text = extractToken(obj) - if (!text.isNullOrEmpty()) { - emit(StreamEvent.Token(text)) - } - - if (doneFlag || finishReason != null && finishReason != "null") { - val mid = obj["message_id"]?.jsonPrimitive?.intOrNull - ?: obj["messageId"]?.jsonPrimitive?.intOrNull - emitTerminal(StreamEvent.Done(mid)) - return DataResult(parsed = true, token = !text.isNullOrEmpty(), done = true) - } - - return DataResult(parsed = true, token = !text.isNullOrEmpty(), done = false) - } - - /** Pulls incremental text from any supported provider payload shape. */ - private fun extractToken(obj: JsonObject): String? { - // 1. Backend/simple shapes. - obj["token"]?.jsonPrimitive?.contentOrNull?.let { return it } - obj["delta"]?.let { el -> - // delta may be a string (simple) or an object (OpenAI). - el.jsonPrimitive.contentOrNull?.let { return it } - } - obj["content"]?.jsonPrimitive?.contentOrNull?.let { return it } - obj["text"]?.jsonPrimitive?.contentOrNull?.let { return it } - - // 2. OpenAI / Groq / Kimi: choices[].delta.content (or .text). - (obj["choices"] as? JsonArray)?.let { choices -> - val sb = StringBuilder() - for (choice in choices) { - val c = choice as? JsonObject ?: continue - val delta = c["delta"] as? JsonObject - val piece = delta?.get("content")?.jsonPrimitive?.contentOrNull - ?: c["text"]?.jsonPrimitive?.contentOrNull - ?: (c["message"] as? JsonObject)?.get("content")?.jsonPrimitive?.contentOrNull - if (!piece.isNullOrEmpty()) sb.append(piece) - } - if (sb.isNotEmpty()) return sb.toString() - } - - // 3. Gemini: candidates[].content.parts[].text - (obj["candidates"] as? JsonArray)?.let { candidates -> - val sb = StringBuilder() - for (cand in candidates) { - val c = cand as? JsonObject ?: continue - val parts = (c["content"] as? JsonObject)?.get("parts") as? JsonArray ?: continue - for (part in parts) { - (part as? JsonObject)?.get("text")?.jsonPrimitive?.contentOrNull?.let { sb.append(it) } - } - } - if (sb.isNotEmpty()) return sb.toString() - } - - return null - } - - /** Detects an error object embedded in a streamed frame. */ - private fun extractError(obj: JsonObject): String? { - (obj["error"])?.let { el -> - (el as? JsonObject)?.let { eo -> - return eo["message"]?.jsonPrimitive?.contentOrNull ?: "Provider error" - } - el.jsonPrimitive.contentOrNull?.let { return it } - } - return null - } - - private fun extractChoiceFinishReason(obj: JsonObject): String? { - val choices = obj["choices"] as? JsonArray ?: return null - for (choice in choices) { - (choice as? JsonObject)?.get("finish_reason")?.jsonPrimitive?.contentOrNull?.let { - if (it != "null") return it - } - } - return null - } - - /** Internal result type for the retry loop / stream consumer. */ - private sealed class AttemptResult { - data object DONE : AttemptResult() - data class RETRY(val reason: String) : AttemptResult() - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/data/ThemePreferences.kt b/api/Android/app/src/main/java/com/ainotebook/app/data/ThemePreferences.kt deleted file mode 100644 index 1ef131a..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/data/ThemePreferences.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.ainotebook.app.data - -import android.content.Context -import androidx.datastore.preferences.core.booleanPreferencesKey -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.preferencesDataStore -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map - -private val Context.themeStore by preferencesDataStore(name = "ai_notebook_prefs") - -/** User-selectable theme mode for the app (mirrors ChatGPT/Gemini appearance settings). */ -enum class ThemeMode { SYSTEM, LIGHT, DARK } - -/** - * Persists user appearance + assistant preferences using Jetpack DataStore. - * Purely additive — does not touch the existing session/auth flow. - */ -class ThemePreferences(private val context: Context) { - - companion object { - private val THEME_KEY = stringPreferencesKey("pref_theme_mode") - private val DYNAMIC_KEY = booleanPreferencesKey("pref_dynamic_color") - private val HAPTICS_KEY = booleanPreferencesKey("pref_haptics") - private val MODEL_KEY = stringPreferencesKey("pref_ai_model") - } - - val themeMode: Flow = context.themeStore.data.map { prefs -> - when (prefs[THEME_KEY]) { - "LIGHT" -> ThemeMode.LIGHT - "DARK" -> ThemeMode.DARK - else -> ThemeMode.DARK // premium dark-first default, like Perplexity/Claude - } - } - - val dynamicColor: Flow = - context.themeStore.data.map { it[DYNAMIC_KEY] ?: false } - - val hapticsEnabled: Flow = - context.themeStore.data.map { it[HAPTICS_KEY] ?: true } - - val aiModel: Flow = - context.themeStore.data.map { it[MODEL_KEY] ?: "auto" } - - suspend fun setThemeMode(mode: ThemeMode) { - context.themeStore.edit { it[THEME_KEY] = mode.name } - } - - suspend fun setDynamicColor(enabled: Boolean) { - context.themeStore.edit { it[DYNAMIC_KEY] = enabled } - } - - suspend fun setHaptics(enabled: Boolean) { - context.themeStore.edit { it[HAPTICS_KEY] = enabled } - } - - suspend fun setAiModel(model: String) { - context.themeStore.edit { it[MODEL_KEY] = model } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/AppLocals.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/AppLocals.kt deleted file mode 100644 index 067836b..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/AppLocals.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.compose.runtime.staticCompositionLocalOf -import com.ainotebook.app.data.NetworkMonitor -import com.ainotebook.app.data.ThemePreferences - -/** - * App-wide composition locals so deep screens (settings, chat) can reach the - * appearance preferences and connectivity monitor without prop-drilling. - */ -val LocalAppPrefs = staticCompositionLocalOf { - error("ThemePreferences not provided") -} - -val LocalNetworkMonitor = staticCompositionLocalOf { - error("NetworkMonitor not provided") -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/AppNav.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/AppNav.kt deleted file mode 100644 index 92ad126..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/AppNav.kt +++ /dev/null @@ -1,223 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.compose.animation.AnimatedContentTransitionScope -import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.slideInHorizontally -import androidx.compose.animation.slideOutHorizontally -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.Chat -import androidx.compose.material.icons.filled.Dashboard -import androidx.compose.material.icons.filled.Person -import androidx.compose.material.icons.filled.Widgets -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.NavigationBar -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.NavigationBarItemDefaults -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.NavType -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState -import androidx.navigation.compose.rememberNavController -import androidx.navigation.navArgument -import com.ainotebook.app.data.Repository -import com.ainotebook.app.ui.components.OfflineBanner -import com.ainotebook.app.ui.components.SpaceBackground -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.screens.ChatScreen -import com.ainotebook.app.ui.screens.DashboardScreen -import com.ainotebook.app.ui.screens.LoginScreen -import com.ainotebook.app.ui.screens.ProfileScreen -import com.ainotebook.app.ui.screens.SignupScreen -import com.ainotebook.app.ui.screens.ToolsScreen -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.MutedText - -object Routes { - const val LOGIN = "login" - const val SIGNUP = "signup" - const val DASHBOARD = "dashboard" - const val CHAT = "chat" - const val TOOLS = "tools" - const val PROFILE = "profile" -} - -private data class NavItem(val route: String, val label: String, val icon: ImageVector) - -private val BOTTOM_ITEMS = listOf( - NavItem(Routes.DASHBOARD, "Home", Icons.Default.Dashboard), - NavItem(Routes.CHAT, "Chat", Icons.AutoMirrored.Filled.Chat), - NavItem(Routes.TOOLS, "Tools", Icons.Default.Widgets), - NavItem(Routes.PROFILE, "Profile", Icons.Default.Person), -) - -@Composable -fun AppRoot(repo: Repository) { - val factory = remember(repo) { VMFactory(repo) } - val token by repo.tokenFlow.collectAsState(initial = null) - val isAuthed = !token.isNullOrBlank() - - if (isAuthed) { - MainShell(factory) - } else { - AuthFlow(factory) - } -} - -@Composable -private fun AuthFlow(factory: VMFactory) { - val nav = rememberNavController() - val authVm: AuthViewModel = viewModel(factory = factory) - - NavHost( - navController = nav, - startDestination = Routes.LOGIN, - enterTransition = { slideInHorizontally(tween(300)) { it / 2 } + fadeIn(tween(300)) }, - exitTransition = { fadeOut(tween(200)) }, - popEnterTransition = { fadeIn(tween(300)) }, - popExitTransition = { slideOutHorizontally(tween(300)) { it / 2 } + fadeOut(tween(200)) } - ) { - composable(Routes.LOGIN) { - LoginScreen( - vm = authVm, - onLoggedIn = { /* token flow flips AppRoot to MainShell */ }, - onGoSignup = { nav.navigate(Routes.SIGNUP) } - ) - } - composable(Routes.SIGNUP) { - SignupScreen( - vm = authVm, - onSignedUp = { }, - onGoLogin = { nav.popBackStack() } - ) - } - } -} - -@Composable -private fun MainShell(factory: VMFactory) { - val nav = rememberNavController() - val backStack by nav.currentBackStackEntryAsState() - val current = backStack?.destination?.route - val haptic = rememberHaptics() - - val dashboardVm: DashboardViewModel = viewModel(factory = factory) - val chatVm: ChatViewModel = viewModel(factory = factory) - val toolsVm: ToolsViewModel = viewModel(factory = factory) - val profileVm: ProfileViewModel = viewModel(factory = factory) - - val userState by profileVm.state.collectAsState() - val networkMonitor = LocalNetworkMonitor.current - val isOnline by networkMonitor.isOnline.collectAsState(initial = networkMonitor.currentlyOnline()) - - SpaceBackground { - Scaffold( - containerColor = androidx.compose.ui.graphics.Color.Transparent, - bottomBar = { - NavigationBar( - containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f), - tonalElevation = 0.dp - ) { - BOTTOM_ITEMS.forEach { item -> - val selected = current?.startsWith(item.route) == true - NavigationBarItem( - selected = selected, - onClick = { - if (!selected) { - haptic() - nav.navigate(item.route) { - popUpTo(Routes.DASHBOARD) { saveState = true } - launchSingleTop = true - restoreState = true - } - } - }, - icon = { Icon(item.icon, contentDescription = item.label) }, - label = { - Text( - item.label, - fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Normal - ) - }, - colors = NavigationBarItemDefaults.colors( - selectedIconColor = Indigo, - selectedTextColor = Indigo, - unselectedIconColor = MutedText, - unselectedTextColor = MutedText, - indicatorColor = Indigo.copy(alpha = 0.16f) - ) - ) - } - } - } - ) { padding -> - Column(Modifier.padding(padding)) { - OfflineBanner(isOnline = isOnline) - NavHost( - navController = nav, - startDestination = Routes.DASHBOARD, - enterTransition = { fadeIn(tween(220)) + slideInHorizontally(tween(260)) { it / 6 } }, - exitTransition = { fadeOut(tween(160)) }, - popEnterTransition = { fadeIn(tween(220)) }, - popExitTransition = { fadeOut(tween(160)) } - ) { - composable(Routes.DASHBOARD) { - DashboardScreen( - vm = dashboardVm, - userName = userState.user?.name ?: "", - onOpenChat = { id -> nav.navigate("${Routes.CHAT}?chatId=$id") }, - onNewChat = { - nav.navigate(Routes.CHAT) { - popUpTo(Routes.DASHBOARD) { saveState = true } - launchSingleTop = true - } - }, - onOpenTools = { - nav.navigate(Routes.TOOLS) { - popUpTo(Routes.DASHBOARD) { saveState = true } - launchSingleTop = true - } - } - ) - } - composable( - route = "${Routes.CHAT}?chatId={chatId}", - arguments = listOf(navArgument("chatId") { - type = NavType.IntType; defaultValue = -1 - }) - ) { entry -> - val chatId = entry.arguments?.getInt("chatId") ?: -1 - ChatScreen(vm = chatVm, initialChatId = if (chatId > 0) chatId else null) - } - composable(Routes.CHAT) { - ChatScreen(vm = chatVm, initialChatId = null) - } - composable(Routes.TOOLS) { - ToolsScreen(vm = toolsVm) - } - composable(Routes.PROFILE) { - ProfileScreen( - vm = profileVm, - onLoggedOut = { /* token flow flips AppRoot to AuthFlow */ } - ) - } - } - } - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/AuthViewModel.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/AuthViewModel.kt deleted file mode 100644 index 8c6f0d2..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/AuthViewModel.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.ainotebook.app.data.Repository -import com.ainotebook.app.data.User -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch - -data class AuthUiState( - val loading: Boolean = false, - val error: String? = null, - val success: Boolean = false -) - -class AuthViewModel(private val repo: Repository) : ViewModel() { - - private val _state = MutableStateFlow(AuthUiState()) - val state: StateFlow = _state.asStateFlow() - - val userFlow = repo.userFlow - - fun clearError() { - _state.value = _state.value.copy(error = null) - } - - private fun run(block: suspend () -> User) { - viewModelScope.launch { - _state.value = AuthUiState(loading = true) - try { - block() - _state.value = AuthUiState(success = true) - } catch (e: Exception) { - _state.value = AuthUiState(error = friendly(e)) - } - } - } - - fun login(identifier: String, password: String) { - if (identifier.isBlank() || password.isBlank()) { - _state.value = AuthUiState(error = "Please enter your email/username and password.") - return - } - run { repo.login(identifier.trim(), password) } - } - - fun signup( - name: String, username: String, email: String, - password: String, confirm: String -) { - when { - name.isBlank() || username.isBlank() || email.isBlank() -> - _state.value = AuthUiState(error = "Please fill in all fields.") - !email.contains("@") || !email.contains(".") -> // ← ADD THIS - _state.value = AuthUiState(error = "Please enter a valid email address.") - password.length < 6 -> - _state.value = AuthUiState(error = "Password must be at least 6 characters.") - password != confirm -> - _state.value = AuthUiState(error = "Passwords do not match.") - else -> run { - repo.signup(name.trim(), username.trim(), email.trim(), password, confirm) - } - } -} - - fun guest() = run { repo.guest() } - - private fun friendly(e: Exception): String { - if (e is retrofit2.HttpException) { - val code = e.code() - val detail = try { - val body = e.response()?.errorBody()?.string() - if (!body.isNullOrBlank()) { - org.json.JSONObject(body).optString("detail", null) - } else null - } catch (ignored: Exception) { null } - - return when (code) { - 400 -> detail ?: "Invalid request. Please check your details." - 401 -> detail ?: "Invalid credentials." - 409 -> detail ?: "That account already exists." - 422 -> "Please check all fields and try again." - 429 -> "Too many requests. Please slow down." - 500 -> "Server error. Please try again later." - else -> detail ?: "Request failed ($code)." - } - } - - return when { - e.message?.contains("Unable to resolve host", true) == true || - e.message?.contains("timeout", true) == true || - e.message?.contains("failed to connect", true) == true -> - "Cannot reach the server. Check your connection." - else -> e.message ?: "Something went wrong." - } -} -} - diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/ChatViewModel.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/ChatViewModel.kt deleted file mode 100644 index 54fd47d..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/ChatViewModel.kt +++ /dev/null @@ -1,319 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.ainotebook.app.data.Chat -import com.ainotebook.app.data.ChatMessage -import com.ainotebook.app.data.Repository -import com.ainotebook.app.data.StreamEvent -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update // ← required for atomic CAS updates -import kotlinx.coroutines.launch - -data class ChatUiState( - val chats: List = emptyList(), - val currentChatId: Int? = null, - val currentTitle: String = "New Chat", - val messages: List = emptyList(), - val streaming: Boolean = false, - val loading: Boolean = false, - val error: String? = null, - val model: String = "auto", - val modelOptions: List = listOf("auto"), - val pinnedChatIds: Set = emptySet(), - val searchQuery: String = "" -) { - val visibleChats: List - get() { - val filtered = if (searchQuery.isBlank()) chats - else chats.filter { it.title.contains(searchQuery, ignoreCase = true) } - // Pinned chats float to the top, preserving recency order within each group. - return filtered.sortedByDescending { it.id in pinnedChatIds } - } -} - -class ChatViewModel(private val repo: Repository) : ViewModel() { - - private val _state = MutableStateFlow(ChatUiState()) - val state: StateFlow = _state.asStateFlow() - - init { loadModelOptions() } - - // ─── Chat list ──────────────────────────────────────────────────────────── - - fun loadChats() { - viewModelScope.launch { - try { - val chats = repo.listChats() - _state.update { it.copy(chats = chats) } - } catch (e: Exception) { - _state.update { it.copy(error = friendly(e)) } - } - } - } - - // ─── Model selection ────────────────────────────────────────────────────── - - private fun loadModelOptions() { - viewModelScope.launch { - try { - val res = repo.aiModels() - _state.update { - it.copy( - model = res.selected.ifBlank { "auto" }, - modelOptions = res.options.ifEmpty { listOf("auto") } - ) - } - } catch (_: Exception) { - // Non-fatal — defaults already set in ChatUiState. - } - } - } - - fun selectModel(model: String) { - _state.update { it.copy(model = model) } - viewModelScope.launch { - try { repo.setAiModel(model) } catch (_: Exception) { /* best-effort persist */ } - } - } - - // ─── Search / pin ───────────────────────────────────────────────────────── - - fun setSearchQuery(q: String) { - _state.update { it.copy(searchQuery = q) } - } - - fun togglePin(chatId: Int) { - // FIX: entire read-modify-write is inside update {} so it cannot race. - _state.update { current -> - val pins = current.pinnedChatIds.toMutableSet() - if (!pins.add(chatId)) pins.remove(chatId) - current.copy(pinnedChatIds = pins) - } - } - - // ─── Chat lifecycle ─────────────────────────────────────────────────────── - - fun openChat(chatId: Int) { - viewModelScope.launch { - _state.update { it.copy(loading = true, error = null) } - try { - val detail = repo.getChat(chatId) - _state.update { - it.copy( - loading = false, - currentChatId = detail.chat.id, - currentTitle = detail.chat.title, - messages = detail.messages - ) - } - } catch (e: Exception) { - _state.update { it.copy(loading = false, error = friendly(e)) } - } - } - } - - fun startNewChat() { - _state.update { - it.copy( - currentChatId = null, - currentTitle = "New Chat", - messages = emptyList(), - error = null - ) - } - } - - fun deleteChat(chatId: Int) { - viewModelScope.launch { - try { - repo.deleteChat(chatId) - // FIX: capture wasCurrentChat BEFORE mutating state so we don't - // read a value we just changed. - val wasCurrentChat = _state.value.currentChatId == chatId - _state.update { current -> - val pins = current.pinnedChatIds.toMutableSet().apply { remove(chatId) } - current.copy(pinnedChatIds = pins) - } - if (wasCurrentChat) startNewChat() - loadChats() - } catch (e: Exception) { - _state.update { it.copy(error = friendly(e)) } - } - } - } - - fun renameChat(chatId: Int, title: String) { - if (title.isBlank()) return - viewModelScope.launch { - try { - val chat = repo.renameChat(chatId, title.trim()) - _state.update { current -> - if (current.currentChatId == chatId) current.copy(currentTitle = chat.title) - else current - } - loadChats() - } catch (e: Exception) { - _state.update { it.copy(error = friendly(e)) } - } - } - } - - // ─── Messaging ──────────────────────────────────────────────────────────── - - /** - * Send a message — creating a chat first if needed — and stream the reply. - */ - fun send(content: String) { - if (content.isBlank() || _state.value.streaming) return - viewModelScope.launch { - try { - // Resolve or create a chat ID before touching the message list. - val chatId = _state.value.currentChatId ?: run { - val chat = repo.newChat() - _state.update { - it.copy(currentChatId = chat.id, currentTitle = chat.title) - } - chat.id - } - - // FIX: append both bubbles AND set streaming=true in a single atomic - // update so the UI never sees a partial state (e.g. streaming=false - // while the assistant bubble already exists). - val userMsg = ChatMessage(id = -1, role = "user", content = content) - val assistantMsg = ChatMessage(id = -2, role = "assistant", content = "") - _state.update { - it.copy( - // FIX: read it.messages inside the lambda — not _state.value.messages - // from an outer scope — to guarantee we append to the latest list. - messages = it.messages + userMsg + assistantMsg, - streaming = true, - error = null - ) - } - - streamReply(chatId, content) - } catch (e: Exception) { - _state.update { it.copy(streaming = false, error = friendly(e)) } - } - } - } - - /** - * Regenerate the latest assistant reply: re-send the most recent user - * message and stream a fresh answer in place (ChatGPT/Gemini behaviour). - */ - fun regenerateLast() { - if (_state.value.streaming) return - // Snapshot outside the coroutine; these values are immutable data. - val currentState = _state.value - val lastUser = currentState.messages.lastOrNull { it.role == "user" } ?: return - val chatId = currentState.currentChatId ?: return - - viewModelScope.launch { - // FIX: added try-catch — without it, any exception thrown by streamReply - // (e.g. from repo.currentToken()) would leave streaming=true forever and - // swallow the error silently. - try { - // FIX: atomic swap of the trailing assistant bubble. - _state.update { current -> - val trimmed = current.messages.toMutableList() - if (trimmed.isNotEmpty() && trimmed.last().role == "assistant") { - trimmed.removeAt(trimmed.lastIndex) - } - trimmed.add(ChatMessage(id = -2, role = "assistant", content = "")) - current.copy(messages = trimmed, streaming = true, error = null) - } - streamReply(chatId, lastUser.content) - } catch (e: Exception) { - _state.update { it.copy(streaming = false, error = friendly(e)) } - } - } - } - - /** - * Edit the last user message and resend it (Claude/ChatGPT-style edit). - * Removes the old user+assistant pair and submits the new text. - */ - fun editAndResend(newContent: String) { - if (newContent.isBlank() || _state.value.streaming) return - val lastUserIdx = _state.value.messages.indexOfLast { it.role == "user" } - if (lastUserIdx < 0) { - send(newContent) - return - } - // FIX: trim happens atomically inside update {}; the subsequent send() will - // then read the already-trimmed list when it appends the new bubbles. - _state.update { current -> - val trimmed = current.messages.toMutableList() - while (trimmed.size > lastUserIdx) trimmed.removeAt(trimmed.lastIndex) - current.copy(messages = trimmed) - } - send(newContent) - } - - // ─── Internal streaming ─────────────────────────────────────────────────── - - private suspend fun streamReply(chatId: Int, content: String) { - val token = repo.currentToken() - val sb = StringBuilder() - try { - repo.streamMessage(chatId, content, token, _state.value.model).collect { event -> - when (event) { - is StreamEvent.Token -> { - sb.append(event.text) - updateLastAssistant(sb.toString()) - } - is StreamEvent.Done -> { - _state.update { it.copy(streaming = false) } - loadChats() - } - is StreamEvent.Error -> { - if (sb.isEmpty()) updateLastAssistant("⚠️ ${event.message}") - _state.update { it.copy(streaming = false) } - } - } - } - } finally { - // FIX: conditional update avoids emitting a spurious state change when - // Done/Error already cleared the flag. Coroutine cancellation is also - // covered — streaming will always be false when this scope exits. - _state.update { if (it.streaming) it.copy(streaming = false) else it } - } - } - - /** - * Atomically patch the last assistant bubble's text. - * FIX: using update {} prevents a torn read-modify-write on every streaming - * token, which was the highest-frequency race in the original code. - */ - private fun updateLastAssistant(text: String) { - _state.update { current -> - val msgs = current.messages.toMutableList() - val idx = msgs.indexOfLast { it.role == "assistant" } - if (idx >= 0) { - msgs[idx] = msgs[idx].copy(content = text) - current.copy(messages = msgs) - } else current // guard: no-op if the bubble is somehow missing - } - } - - // ─── Misc ───────────────────────────────────────────────────────────────── - - fun clearError() { - _state.update { it.copy(error = null) } - } - - private fun friendly(e: Exception): String { - val msg = e.message ?: "Something went wrong." - return when { - msg.contains("Unable to resolve host", true) || - msg.contains("timeout", true) || - msg.contains("failed to connect", true) -> - "Cannot reach the server. Check your connection and try again." - else -> msg - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/DashboardViewModel.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/DashboardViewModel.kt deleted file mode 100644 index 28fdca6..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/DashboardViewModel.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.ainotebook.app.data.Repository -import com.ainotebook.app.data.Stats -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch - -data class DashboardUiState( - val loading: Boolean = true, - val stats: Stats? = null, - val error: String? = null -) - -class DashboardViewModel(private val repo: Repository) : ViewModel() { - - private val _state = MutableStateFlow(DashboardUiState()) - val state: StateFlow = _state.asStateFlow() - - init { load() } - - fun load() { - viewModelScope.launch { - _state.value = _state.value.copy(loading = true, error = null) - try { - val s = repo.stats() - _state.value = DashboardUiState(loading = false, stats = s) - } catch (e: Exception) { - _state.value = DashboardUiState( - loading = false, - error = e.message ?: "Could not load your dashboard." - ) - } - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/ProfileViewModel.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/ProfileViewModel.kt deleted file mode 100644 index 3c1e1d6..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/ProfileViewModel.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.ainotebook.app.data.Repository -import com.ainotebook.app.data.User -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch - -data class ProfileUiState( - val user: User? = null, - val loading: Boolean = false, - val message: String? = null, - val error: String? = null, - val loggedOut: Boolean = false -) - -class ProfileViewModel(private val repo: Repository) : ViewModel() { - - private val _state = MutableStateFlow(ProfileUiState()) - val state: StateFlow = _state.asStateFlow() - - init { refresh() } - - fun refresh() { - viewModelScope.launch { - try { - _state.value = _state.value.copy(user = repo.me()) - } catch (e: Exception) { - _state.value = _state.value.copy(error = e.message) - } - } - } - - fun updateName(name: String) { - if (name.isBlank()) { - _state.value = _state.value.copy(error = "Please enter your name.") - return - } - viewModelScope.launch { - _state.value = _state.value.copy(loading = true, message = null, error = null) - try { - val u = repo.updateProfile(name.trim()) - _state.value = _state.value.copy(loading = false, user = u, message = "Profile updated.") - } catch (e: Exception) { - _state.value = _state.value.copy(loading = false, error = e.message) - } - } - } - - fun changePassword(current: String, new: String) { - if (new.length < 6) { - _state.value = _state.value.copy(error = "New password must be at least 6 characters.") - return - } - viewModelScope.launch { - _state.value = _state.value.copy(loading = true, message = null, error = null) - try { - val msg = repo.changePassword(current, new) - _state.value = _state.value.copy(loading = false, message = msg) - } catch (e: Exception) { - _state.value = _state.value.copy(loading = false, error = e.message) - } - } - } - - fun logout() { - viewModelScope.launch { - repo.logout() - _state.value = _state.value.copy(loggedOut = true) - } - } - - fun clearMessages() { - _state.value = _state.value.copy(message = null, error = null) - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/ToolsViewModel.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/ToolsViewModel.kt deleted file mode 100644 index be64e13..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/ToolsViewModel.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.ainotebook.app.data.Flashcard -import com.ainotebook.app.data.QuizQuestion -import com.ainotebook.app.data.Repository -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch - -/** Generic result holder for the study tools. */ -data class ToolsUiState( - val loading: Boolean = false, - val error: String? = null, - val textResult: String? = null, // notes / plan / summary / homework - val quiz: List? = null, - val flashcards: List? = null -) - -enum class Tool { NOTES, QUIZ, FLASHCARDS, PLAN, SUMMARIZE, HOMEWORK } - -class ToolsViewModel(private val repo: Repository) : ViewModel() { - - private val _state = MutableStateFlow(ToolsUiState()) - val state: StateFlow = _state.asStateFlow() - - fun reset() { - _state.value = ToolsUiState() - } - - private fun begin() { - _state.value = ToolsUiState(loading = true) - } - - private fun fail(e: Exception) { - _state.value = ToolsUiState(error = e.message ?: "Something went wrong.") - } - - fun notes(topic: String) = launch { _state.value = ToolsUiState(textResult = repo.generateNotes(topic).content) } - fun plan(goal: String, days: Int) = launch { _state.value = ToolsUiState(textResult = repo.generatePlan(goal, days).content) } - fun summarize(text: String) = launch { _state.value = ToolsUiState(textResult = repo.summarize(text).summary) } - fun homework(q: String) = launch { _state.value = ToolsUiState(textResult = repo.homework(q).answer) } - fun quiz(topic: String, n: Int) = launch { _state.value = ToolsUiState(quiz = repo.generateQuiz(topic, n).questions) } - fun flashcards(topic: String, n: Int) = launch { _state.value = ToolsUiState(flashcards = repo.generateFlashcards(topic, n).cards) } - - private fun launch(block: suspend () -> Unit) { - viewModelScope.launch { - begin() - try { - block() - } catch (e: Exception) { - fail(e) - } - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/ViewModelFactory.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/ViewModelFactory.kt deleted file mode 100644 index 5878653..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/ViewModelFactory.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.ainotebook.app.ui - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.ainotebook.app.data.Repository - -/** - * Single factory able to construct every view model in the app from the shared - * [Repository]. Keeps things dependency-injection-framework-free. - */ -class VMFactory(private val repo: Repository) : ViewModelProvider.Factory { - @Suppress("UNCHECKED_CAST") - override fun create(modelClass: Class): T { - return when { - modelClass.isAssignableFrom(AuthViewModel::class.java) -> AuthViewModel(repo) as T - modelClass.isAssignableFrom(DashboardViewModel::class.java) -> DashboardViewModel(repo) as T - modelClass.isAssignableFrom(ChatViewModel::class.java) -> ChatViewModel(repo) as T - modelClass.isAssignableFrom(ToolsViewModel::class.java) -> ToolsViewModel(repo) as T - modelClass.isAssignableFrom(ProfileViewModel::class.java) -> ProfileViewModel(repo) as T - else -> throw IllegalArgumentException("Unknown ViewModel: ${modelClass.name}") - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Common.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Common.kt deleted file mode 100644 index 110f2d1..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Common.kt +++ /dev/null @@ -1,228 +0,0 @@ -package com.ainotebook.app.ui.components - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.RepeatMode -import androidx.compose.animation.core.animateFloat -import androidx.compose.animation.core.infiniteRepeatable -import androidx.compose.animation.core.rememberInfiniteTransition -import androidx.compose.animation.core.tween -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.CloudOff -import androidx.compose.material.icons.filled.ErrorOutline -import androidx.compose.animation.AnimatedVisibility as AnimatedVisibilityCommon -import androidx.compose.animation.expandVertically -import androidx.compose.animation.shrinkVertically -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.ainotebook.app.R -import com.ainotebook.app.ui.theme.Cyan -import com.ainotebook.app.ui.theme.HairlineOutline -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.SpaceBg -import com.ainotebook.app.ui.theme.Violet - -/** A subtle space gradient background used on every screen. */ -@Composable -fun SpaceBackground(content: @Composable () -> Unit) { - Box( - modifier = Modifier - .fillMaxSize() - .background( - Brush.verticalGradient( - listOf(SpaceBg, Color(0xFF0C1226), SpaceBg) - ) - ) - ) { content() } -} - -/** Glassmorphism-ish card with a hairline border for the assistant-app look. */ -@Composable -fun GlassCard( - modifier: Modifier = Modifier, - content: @Composable () -> Unit -) { - Card( - modifier = modifier.border( - width = 1.dp, - color = HairlineOutline.copy(alpha = 0.6f), - shape = RoundedCornerShape(20.dp) - ), - shape = RoundedCornerShape(20.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.65f) - ), - elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) - ) { content() } -} - -/** - * The official AI Notebook logo, shown cleanly with preserved proportions. - * Uses the uploaded brand asset (res/drawable-nodpi/ss_logo.png) — no generated - * or alternative branding. - */ -@Composable -fun BrandLogo( - size: Dp, - modifier: Modifier = Modifier -) { - Image( - painter = painterResource(id = R.drawable.ss_logo), - contentDescription = "AI Notebook", - contentScale = ContentScale.Fit, - modifier = modifier.size(size) - ) -} - -/** - * Circular assistant avatar that displays the official logo — used next to AI - * replies in chat (ChatGPT/Gemini/Perplexity-style message rows). - */ -@Composable -fun AssistantAvatar(size: Dp = 30.dp, modifier: Modifier = Modifier) { - Box( - modifier = modifier - .size(size) - .clip(CircleShape) - .background(Brush.linearGradient(listOf(Indigo, Violet))) - .border(1.dp, HairlineOutline, CircleShape), - contentAlignment = Alignment.Center - ) { - Image( - painter = painterResource(id = R.drawable.ss_logo), - contentDescription = "AI Notebook", - contentScale = ContentScale.Fit, - modifier = Modifier.size(size * 0.66f) - ) - } -} - -/** Animated three-dot "thinking" indicator used while the AI streams a reply. */ -@Composable -fun TypingDots(color: Color = Indigo) { - val transition = rememberInfiniteTransition(label = "typing") - Row(verticalAlignment = Alignment.CenterVertically) { - repeat(3) { i -> - val alpha by transition.animateFloat( - initialValue = 0.25f, - targetValue = 1f, - animationSpec = infiniteRepeatable( - animation = tween(600, delayMillis = i * 180, easing = LinearEasing), - repeatMode = RepeatMode.Reverse - ), - label = "dot$i" - ) - Box( - Modifier - .padding(horizontal = 2.dp) - .size(7.dp) - .alpha(alpha) - .clip(CircleShape) - .background(color) - ) - if (i < 2) Spacer(Modifier.size(2.dp)) - } - } -} - -@Composable -fun GradientBrush(): Brush = - Brush.horizontalGradient(listOf(Indigo, Violet, Cyan)) - -@Composable -fun LoadingBox(modifier: Modifier = Modifier) { - Box(modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - CircularProgressIndicator(color = Indigo) - } -} - -@Composable -fun ErrorBanner(message: String?) { - AnimatedVisibility(visible = message != null) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp) - .background(Color(0x33FB7185), RoundedCornerShape(12.dp)) - .padding(12.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - Icons.Default.ErrorOutline, - contentDescription = null, - tint = Color(0xFFFB7185), - modifier = Modifier.size(20.dp) - ) - Text( - message ?: "", - color = Color(0xFFFCA5A5), - style = MaterialTheme.typography.bodyMedium - ) - } - } -} - -/** - * A slim, animated "You're offline" banner shown at the top of the shell when - * connectivity is lost — premium reliability behaviour like ChatGPT/Gemini. - */ -@Composable -fun OfflineBanner(isOnline: Boolean) { - AnimatedVisibilityCommon( - visible = !isOnline, - enter = expandVertically(), - exit = shrinkVertically() - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .background(Color(0xFF3A1F2B)) - .padding(horizontal = 16.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - Icons.Default.CloudOff, - contentDescription = null, - tint = Color(0xFFFCA5A5), - modifier = Modifier.size(18.dp) - ) - Text( - "You're offline — some features may be unavailable.", - color = Color(0xFFFCA5A5), - style = MaterialTheme.typography.bodySmall - ) - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Effects.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Effects.kt deleted file mode 100644 index 79114ba..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Effects.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.ainotebook.app.ui.components - -import androidx.compose.animation.core.RepeatMode -import androidx.compose.animation.core.animateFloat -import androidx.compose.animation.core.infiniteRepeatable -import androidx.compose.animation.core.rememberInfiniteTransition -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.composed -import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.unit.dp -import androidx.compose.material3.MaterialTheme -import android.view.HapticFeedbackConstants - -/** - * Shimmer brush used for skeleton loaders (ChatGPT/Gemini-style perceived-speed - * loading). Applies an animated diagonal gradient sweep. - */ -fun Modifier.shimmer(): Modifier = composed { - val base = MaterialTheme.colorScheme.surfaceContainerHigh - val highlight = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.06f) - val transition = rememberInfiniteTransition(label = "shimmer") - val x by transition.animateFloat( - initialValue = -600f, - targetValue = 600f, - animationSpec = infiniteRepeatable( - animation = tween(1300), - repeatMode = RepeatMode.Restart - ), - label = "shimmer-x" - ) - background( - Brush.linearGradient( - colors = listOf(base, highlight, base), - start = Offset(x, 0f), - end = Offset(x + 300f, 300f) - ) - ) -} - -@Composable -fun SkeletonBox( - modifier: Modifier = Modifier, - cornerRadius: Int = 12 -) { - Spacer( - modifier - .clip(RoundedCornerShape(cornerRadius.dp)) - .shimmer() - ) -} - -/** Skeleton placeholder mirroring the dashboard layout while stats load. */ -@Composable -fun DashboardSkeleton(modifier: Modifier = Modifier) { - Column(modifier.padding(16.dp)) { - Row { - SkeletonBox(Modifier.size(44.dp), cornerRadius = 22) - Spacer(Modifier.size(12.dp)) - Column { - SkeletonBox(Modifier.size(width = 120.dp, height = 14.dp)) - Spacer(Modifier.height(8.dp)) - SkeletonBox(Modifier.size(width = 180.dp, height = 22.dp)) - } - } - Spacer(Modifier.height(20.dp)) - repeat(3) { - Row(Modifier.fillMaxWidth().padding(bottom = 12.dp)) { - SkeletonBox(Modifier.weight(1f).height(96.dp)) - Spacer(Modifier.size(12.dp)) - SkeletonBox(Modifier.weight(1f).height(96.dp)) - } - } - Spacer(Modifier.height(8.dp)) - SkeletonBox(Modifier.size(width = 140.dp, height = 18.dp)) - Spacer(Modifier.height(12.dp)) - repeat(3) { - SkeletonBox(Modifier.fillMaxWidth().height(64.dp)) - Spacer(Modifier.height(10.dp)) - } - } -} - -/** Lightweight result-loading skeleton used by study tools. */ -@Composable -fun TextResultSkeleton(modifier: Modifier = Modifier) { - Column(modifier.fillMaxWidth()) { - SkeletonBox(Modifier.fillMaxWidth().height(16.dp)) - Spacer(Modifier.height(10.dp)) - SkeletonBox(Modifier.fillMaxWidth().height(16.dp)) - Spacer(Modifier.height(10.dp)) - SkeletonBox(Modifier.fillMaxWidth(0.7f).height(16.dp)) - } -} - -/** Performs a light haptic tick — used on key taps for a tactile, native feel. */ -@Composable -fun rememberHaptics(): () -> Unit { - val view = LocalView.current - return { - view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY) - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Markdown.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Markdown.kt deleted file mode 100644 index a2da866..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/components/Markdown.kt +++ /dev/null @@ -1,429 +0,0 @@ -package com.ainotebook.app.ui.components - -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.ContentCopy -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.ainotebook.app.ui.theme.Cyan -import com.ainotebook.app.ui.theme.Indigo - -/* ========================================================================= - * Lightweight, dependency-free Markdown renderer tuned for AI assistant - * replies (ChatGPT / Gemini / Claude / Perplexity style). Supports: - * - Headings (#, ##, ###) - * - Bold **x**, italic *x* / _x_, inline `code` - * - Bullet (-, *, •) and numbered (1.) lists - * - Fenced code blocks ``` with a copy button - * - Blockquotes (>) - * - Simple pipe tables - * - Horizontal rules (---) - * ========================================================================= */ - -private sealed interface MdBlock { - data class Heading(val level: Int, val text: String) : MdBlock - data class Paragraph(val text: String) : MdBlock - data class BulletItem(val text: String, val ordered: Boolean, val index: Int) : MdBlock - data class Code(val language: String, val code: String) : MdBlock - data class Quote(val text: String) : MdBlock - data class Table(val rows: List>, val hasHeader: Boolean) : MdBlock - data object Divider : MdBlock -} - -private fun parseMarkdown(src: String): List { - val blocks = mutableListOf() - val lines = src.replace("\r\n", "\n").split("\n") - var i = 0 - var orderedCounter = 0 - - while (i < lines.size) { - val raw = lines[i] - val line = raw.trimEnd() - val trimmed = line.trim() - - when { - // Fenced code block - trimmed.startsWith("```") -> { - val lang = trimmed.removePrefix("```").trim() - val sb = StringBuilder() - i++ - while (i < lines.size && !lines[i].trim().startsWith("```")) { - sb.appendLine(lines[i]) - i++ - } - i++ // closing fence - blocks += MdBlock.Code(lang, sb.toString().trimEnd('\n')) - orderedCounter = 0 - } - - trimmed.isEmpty() -> { - orderedCounter = 0 - i++ - } - - trimmed.startsWith("### ") -> { blocks += MdBlock.Heading(3, trimmed.removePrefix("### ")); i++ } - trimmed.startsWith("## ") -> { blocks += MdBlock.Heading(2, trimmed.removePrefix("## ")); i++ } - trimmed.startsWith("# ") -> { blocks += MdBlock.Heading(1, trimmed.removePrefix("# ")); i++ } - - trimmed == "---" || trimmed == "***" || trimmed == "___" -> { - blocks += MdBlock.Divider; i++ - } - - trimmed.startsWith("> ") -> { - blocks += MdBlock.Quote(trimmed.removePrefix("> ")); i++ - } - - // Table: a line with pipes followed by a separator row - trimmed.contains("|") && i + 1 < lines.size && - lines[i + 1].trim().matches(Regex("\\|?[\\s:|-]+\\|?")) && - lines[i + 1].contains("-") -> { - val rows = mutableListOf>() - rows += splitRow(trimmed) - i += 2 // skip header + separator - while (i < lines.size && lines[i].trim().contains("|") && lines[i].trim().isNotEmpty()) { - rows += splitRow(lines[i].trim()) - i++ - } - blocks += MdBlock.Table(rows, hasHeader = true) - orderedCounter = 0 - } - - trimmed.startsWith("- ") || trimmed.startsWith("* ") || trimmed.startsWith("• ") -> { - blocks += MdBlock.BulletItem(trimmed.drop(2), ordered = false, index = 0) - orderedCounter = 0 - i++ - } - - trimmed.matches(Regex("^\\d+\\.\\s.*")) -> { - orderedCounter++ - val content = trimmed.replaceFirst(Regex("^\\d+\\.\\s"), "") - blocks += MdBlock.BulletItem(content, ordered = true, index = orderedCounter) - i++ - } - - else -> { - blocks += MdBlock.Paragraph(trimmed) - orderedCounter = 0 - i++ - } - } - } - return blocks -} - -private fun splitRow(line: String): List = - line.trim().trim('|').split("|").map { it.trim() } - -/** Renders inline markdown (**bold**, *italic*, `code`) into an AnnotatedString. */ -private fun inline(text: String, codeColor: Color): AnnotatedString = buildAnnotatedString { - var i = 0 - while (i < text.length) { - val c = text[i] - when { - text.startsWith("**", i) -> { - val end = text.indexOf("**", i + 2) - if (end > 0) { - withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { - append(text.substring(i + 2, end)) - } - i = end + 2 - } else { append(c); i++ } - } - c == '`' -> { - val end = text.indexOf('`', i + 1) - if (end > 0) { - withStyle( - SpanStyle( - fontFamily = FontFamily.Monospace, - background = codeColor.copy(alpha = 0.16f), - color = codeColor, - fontSize = 13.5.sp - ) - ) { append(text.substring(i + 1, end)) } - i = end + 1 - } else { append(c); i++ } - } - (c == '*' || c == '_') -> { - val end = text.indexOf(c, i + 1) - if (end > i + 1) { - withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { - append(text.substring(i + 1, end)) - } - i = end + 1 - } else { append(c); i++ } - } - else -> { append(c); i++ } - } - } -} - -@Composable -fun MarkdownText( - markdown: String, - modifier: Modifier = Modifier, - color: Color = MaterialTheme.colorScheme.onSurface -) { - val blocks = remember(markdown) { parseMarkdown(markdown) } - val codeColor = Cyan - - Column(modifier, verticalArrangement = Arrangement.spacedBy(6.dp)) { - blocks.forEach { block -> - when (block) { - is MdBlock.Heading -> Text( - text = inline(block.text, codeColor), - color = color, - style = when (block.level) { - 1 -> MaterialTheme.typography.titleLarge - 2 -> MaterialTheme.typography.titleMedium - else -> MaterialTheme.typography.titleSmall - }, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(top = 4.dp) - ) - - is MdBlock.Paragraph -> Text( - text = inline(block.text, codeColor), - color = color, - style = MaterialTheme.typography.bodyMedium - ) - - is MdBlock.BulletItem -> Row(Modifier.fillMaxWidth()) { - Text( - if (block.ordered) "${block.index}." else "•", - color = Indigo, - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Bold, - modifier = Modifier.width(if (block.ordered) 24.dp else 18.dp) - ) - Text( - text = inline(block.text, codeColor), - color = color, - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.weight(1f) - ) - } - - is MdBlock.Code -> CodeBlock(block.language, block.code) - - is MdBlock.Quote -> Row( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - .background(MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = 0.5f)) - ) { - Box( - Modifier - .width(3.dp) - .background(Indigo) - .padding(vertical = 12.dp) - .size(width = 3.dp, height = 18.dp) - ) - Text( - text = inline(block.text, codeColor), - color = MaterialTheme.colorScheme.onSurfaceVariant, - style = MaterialTheme.typography.bodyMedium, - fontStyle = FontStyle.Italic, - modifier = Modifier.padding(10.dp) - ) - } - - is MdBlock.Table -> MarkdownTable(block.rows, block.hasHeader, codeColor) - - MdBlock.Divider -> Box( - Modifier - .fillMaxWidth() - .padding(vertical = 4.dp) - .size(height = 1.dp, width = 1.dp) - .fillMaxWidth() - .background(MaterialTheme.colorScheme.outline.copy(alpha = 0.5f)) - ) - } - } - } -} - -@Composable -private fun CodeBlock(language: String, code: String) { - val clipboard = LocalClipboardManager.current - var copied by remember { mutableStateOf(false) } - - Column( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(12.dp)) - .background(Color(0xFF0B0F1F)) - .border(1.dp, MaterialTheme.colorScheme.outline.copy(alpha = 0.5f), RoundedCornerShape(12.dp)) - ) { - Row( - Modifier - .fillMaxWidth() - .background(Color(0xFF11162A)) - .padding(horizontal = 12.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - language.ifBlank { "code" }, - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - fontFamily = FontFamily.Monospace - ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .clip(RoundedCornerShape(6.dp)) - .clickable { - clipboard.setText(AnnotatedString(code)) - copied = true - } - .padding(horizontal = 6.dp, vertical = 2.dp) - ) { - Icon( - if (copied) Icons.Default.Check else Icons.Default.ContentCopy, - contentDescription = "Copy code", - tint = if (copied) Cyan else MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.size(14.dp) - ) - Spacer(Modifier.width(4.dp)) - Text( - if (copied) "Copied" else "Copy", - style = MaterialTheme.typography.labelSmall, - color = if (copied) Cyan else MaterialTheme.colorScheme.onSurfaceVariant - ) - } - } - Box( - Modifier - .fillMaxWidth() - .horizontalScroll(rememberScrollState()) - ) { - Text( - buildCodeHighlight(code), - modifier = Modifier.padding(12.dp), - fontFamily = FontFamily.Monospace, - fontSize = 13.sp, - color = Color(0xFFE6E9F5) - ) - } - } -} - -/** Very light syntax tinting: keywords, strings, numbers, comments. */ -private val CODE_KEYWORDS = setOf( - "fun", "val", "var", "if", "else", "for", "while", "return", "class", - "object", "import", "package", "public", "private", "void", "int", - "String", "def", "function", "const", "let", "new", "true", "false", - "null", "None", "True", "False", "print", "println", "in", "is", "when" -) - -private fun buildCodeHighlight(code: String): AnnotatedString = buildAnnotatedString { - val keywordColor = Color(0xFFA855F7) - val stringColor = Color(0xFF7DD3A0) - val numberColor = Color(0xFF22D3EE) - val commentColor = Color(0xFF6B7394) - - code.split("\n").forEachIndexed { idx, line -> - if (idx > 0) append("\n") - val commentIdx = lineCommentIndex(line) - val codePart = if (commentIdx >= 0) line.substring(0, commentIdx) else line - val comment = if (commentIdx >= 0) line.substring(commentIdx) else "" - - val tokens = Regex("(\"[^\"]*\"|'[^']*'|\\b\\w+\\b|\\W)").findAll(codePart) - for (m in tokens) { - val t = m.value - when { - t.startsWith("\"") || t.startsWith("'") -> - withStyle(SpanStyle(color = stringColor)) { append(t) } - t.matches(Regex("\\d+(\\.\\d+)?")) -> - withStyle(SpanStyle(color = numberColor)) { append(t) } - t in CODE_KEYWORDS -> - withStyle(SpanStyle(color = keywordColor, fontWeight = FontWeight.Bold)) { append(t) } - else -> append(t) - } - } - if (comment.isNotEmpty()) { - withStyle(SpanStyle(color = commentColor, fontStyle = FontStyle.Italic)) { append(comment) } - } - } -} - -private fun lineCommentIndex(line: String): Int { - val slashes = line.indexOf("//") - val hash = line.indexOf("#") - return when { - slashes >= 0 && (hash < 0 || slashes < hash) -> slashes - hash >= 0 -> hash - else -> -1 - } -} - -@Composable -private fun MarkdownTable(rows: List>, hasHeader: Boolean, codeColor: Color) { - Column( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(10.dp)) - .border(1.dp, MaterialTheme.colorScheme.outline.copy(alpha = 0.5f), RoundedCornerShape(10.dp)) - ) { - rows.forEachIndexed { rIdx, row -> - val isHeader = hasHeader && rIdx == 0 - Row( - Modifier - .fillMaxWidth() - .background( - if (isHeader) MaterialTheme.colorScheme.surfaceContainerHigh - else if (rIdx % 2 == 0) Color.Transparent - else MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = 0.25f) - ) - ) { - row.forEach { cell -> - Text( - text = inline(cell, codeColor), - modifier = Modifier - .weight(1f) - .padding(horizontal = 10.dp, vertical = 8.dp), - style = MaterialTheme.typography.bodySmall, - color = if (isHeader) MaterialTheme.colorScheme.onSurface - else MaterialTheme.colorScheme.onSurfaceVariant, - fontWeight = if (isHeader) FontWeight.Bold else FontWeight.Normal - ) - } - } - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatScreen.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatScreen.kt deleted file mode 100644 index b87798b..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatScreen.kt +++ /dev/null @@ -1,647 +0,0 @@ -package com.ainotebook.app.ui.screens - -import android.content.Intent -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.scaleOut -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.Send -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.ArrowDownward -import androidx.compose.material.icons.filled.AutoAwesome -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.ContentCopy -import androidx.compose.material.icons.filled.Edit -import androidx.compose.material.icons.filled.History -import androidx.compose.material.icons.filled.Person -import androidx.compose.material.icons.filled.Refresh -import androidx.compose.material.icons.filled.Share -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.OutlinedTextFieldDefaults -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.ainotebook.app.data.ChatMessage -import com.ainotebook.app.ui.ChatViewModel -import com.ainotebook.app.ui.components.AssistantAvatar -import com.ainotebook.app.ui.components.BrandLogo -import com.ainotebook.app.ui.components.MarkdownText -import com.ainotebook.app.ui.components.TypingDots -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.theme.HairlineOutline -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.MutedText -import com.ainotebook.app.ui.theme.Violet -import kotlinx.coroutines.launch - -private val SUGGESTIONS = listOf( - "Explain photosynthesis simply" to "🌱", - "Quiz me on world history" to "🏛️", - "Summarize the French Revolution" to "📜", - "Help with my calculus homework" to "∫" -) - -@Composable -fun ChatScreen( - vm: ChatViewModel, - initialChatId: Int? -) { - val state by vm.state.collectAsState() - var input by remember { mutableStateOf("") } - var editing by remember { mutableStateOf(null) } - val listState = rememberLazyListState() - val scope = rememberCoroutineScope() - val haptic = rememberHaptics() - - var showHistory by remember { mutableStateOf(false) } - var showModels by remember { mutableStateOf(false) } - - LaunchedEffect(initialChatId) { - vm.loadChats() - if (initialChatId != null && initialChatId > 0) vm.openChat(initialChatId) - else vm.startNewChat() - } - - // FIX (Bug 3 partial): Only depend on messages.size, not content, to avoid - // re-triggering animateScrollToItem on every streaming token — which was - // cancelling and restarting the scroll coroutine hundreds of times and could - // cause the list state to become inconsistent. - LaunchedEffect(state.messages.size) { - if (state.messages.isNotEmpty()) { - listState.animateScrollToItem(state.messages.size - 1) - } - } - - val showScrollDown by remember { - derivedStateOf { - val last = listState.layoutInfo.totalItemsCount - 1 - val visibleLast = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0 - last > 0 && visibleLast < last - 1 - } - } - - Box(Modifier.fillMaxSize()) { - Column( - Modifier - .fillMaxSize() - .imePadding() - ) { - ChatHeader( - title = if (state.streaming) "Thinking…" else state.currentTitle, - model = state.model, - onNewChat = { haptic(); vm.startNewChat(); editing = null; input = "" }, - onHistory = { haptic(); showHistory = true }, - onModel = { haptic(); showModels = true } - ) - - // FIX (Bug 2 + Bug 3): EmptyChat and LazyColumn both occupy the - // same weight(1f) slot so the Column can always resolve heights. - // ChatInputBar is now OUTSIDE the if/else so it is always present — - // this eliminates the layout thrash that occurred when the first - // message was sent and the entire bottom half of the screen was - // suddenly added in a single recomposition. - if (state.messages.isEmpty()) { - EmptyChat( - modifier = Modifier.weight(1f), - onSuggestion = { vm.send(it) } - ) - } else { - LazyColumn( - state = listState, - modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(horizontal = 12.dp), - verticalArrangement = Arrangement.spacedBy(18.dp), - contentPadding = PaddingValues(vertical = 12.dp) - ) { - // FIX (Bug 1 — MAIN CRASH): Removed key = { it.id }. - // - // Room auto-generates IDs only after a row is inserted. - // While messages are in-flight (user message sent, assistant - // placeholder added), BOTH have id = 0. Compose's LazyColumn - // requires keys to be unique; two items sharing key=0 throws - // an IllegalArgumentException and crashes the app immediately. - // - // Chat messages are append-only, so position-based identity - // (the default when no key is supplied) is perfectly stable - // and correct here. - items(state.messages) { msg -> - MessageRow( - msg = msg, - streaming = state.streaming, - isLastAssistant = msg == state.messages.lastOrNull { it.role == "assistant" }, - onRegenerate = { haptic(); vm.regenerateLast() }, - onEdit = { editing = msg; input = msg.content } - ) - } - } - } - - // Always-visible input bar (moved out of else branch). - ChatInputBar( - value = input, - onValueChange = { input = it }, - streaming = state.streaming, - isEditing = editing != null, - onCancelEdit = { editing = null; input = "" }, - onSend = { - val text = input.trim() - if (text.isNotEmpty()) { - haptic() - if (editing != null) { - vm.editAndResend(text) - editing = null - } else { - vm.send(text) - } - input = "" - } - } - ) - } // End Column - - // Scroll-to-bottom FAB. - AnimatedVisibility( - visible = showScrollDown && !showHistory, - enter = scaleIn() + fadeIn(), - exit = scaleOut() + fadeOut(), - modifier = Modifier - .align(Alignment.BottomCenter) - .padding(bottom = 92.dp) - ) { - Box( - Modifier - .size(40.dp) - .clip(CircleShape) - .background(MaterialTheme.colorScheme.surfaceContainerHigh) - .border(1.dp, HairlineOutline, CircleShape) - .clickable { - scope.launch { - if (state.messages.isNotEmpty()) - listState.animateScrollToItem(state.messages.size - 1) - } - }, - contentAlignment = Alignment.Center - ) { - Icon( - Icons.Default.ArrowDownward, - contentDescription = "Scroll to bottom", - tint = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.size(20.dp) - ) - } - } - - // Sheets overlaid on top of everything. - if (showHistory) { - ChatHistorySheet( - vm = vm, - onDismiss = { showHistory = false } - ) - } - - if (showModels) { - ModelPickerSheet( - options = state.modelOptions, - selected = state.model, - onSelect = { vm.selectModel(it); showModels = false }, - onDismiss = { showModels = false } - ) - } - } // End outer Box -} - -@Composable -private fun ChatHeader( - title: String, - model: String, - onNewChat: () -> Unit, - onHistory: () -> Unit, - onModel: () -> Unit -) { - Row( - Modifier - .fillMaxWidth() - .statusBarsPadding() - .padding(horizontal = 12.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - IconButton(onClick = onHistory) { - Icon( - Icons.Default.History, - contentDescription = "Chat history", - tint = MaterialTheme.colorScheme.onBackground - ) - } - AssistantAvatar(size = 32.dp) - Spacer(Modifier.size(10.dp)) - Column(Modifier.weight(1f)) { - Text( - "AI Notebook", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onBackground, - maxLines = 1 - ) - Text( - title, - style = MaterialTheme.typography.bodySmall, - color = MutedText, - maxLines = 1 - ) - } - Row( - Modifier - .clip(RoundedCornerShape(20.dp)) - .background(Indigo.copy(alpha = 0.16f)) - .clickable(onClick = onModel) - .padding(horizontal = 10.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Default.AutoAwesome, - contentDescription = null, - tint = Indigo, - modifier = Modifier.size(15.dp) - ) - Spacer(Modifier.size(4.dp)) - Text( - when (model) { // ✅ correct place - "kimi" -> "AI Notebook Pro" - "groq" -> "AI Notebook Lite" - "auto" -> "Auto" - else -> model.replaceFirstChar { it.uppercase() } - }, - style = MaterialTheme.typography.labelMedium, - color = Indigo, - fontWeight = FontWeight.SemiBold - ) - } - IconButton(onClick = onNewChat) { - Icon(Icons.Default.Add, contentDescription = "New chat", tint = Indigo) - } - } -} -@Composable -private fun ChatInputBar( - value: String, - onValueChange: (String) -> Unit, - streaming: Boolean, - isEditing: Boolean, - onCancelEdit: () -> Unit, - onSend: () -> Unit -) { - Column { - AnimatedVisibility(visible = isEditing) { - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Default.Edit, - contentDescription = null, - tint = Violet, - modifier = Modifier.size(16.dp) - ) - Spacer(Modifier.size(6.dp)) - Text( - "Editing message", - style = MaterialTheme.typography.labelMedium, - color = Violet, - modifier = Modifier.weight(1f) - ) - Text( - "Cancel", - style = MaterialTheme.typography.labelMedium, - color = MutedText, - modifier = Modifier.clickable(onClick = onCancelEdit) - ) - } - } - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 10.dp), - verticalAlignment = Alignment.Bottom - ) { - OutlinedTextField( - value = value, - onValueChange = onValueChange, - placeholder = { Text("Message AI Notebook…") }, - modifier = Modifier.weight(1f), - shape = RoundedCornerShape(24.dp), - maxLines = 5, - colors = OutlinedTextFieldDefaults.colors( - focusedBorderColor = Indigo, - unfocusedBorderColor = HairlineOutline, - focusedContainerColor = MaterialTheme.colorScheme.surface, - unfocusedContainerColor = MaterialTheme.colorScheme.surface - ) - ) - Spacer(Modifier.size(8.dp)) - val sendBrush = if (streaming || value.isBlank()) - Brush.linearGradient(listOf(Indigo.copy(alpha = 0.4f), Indigo.copy(alpha = 0.4f))) - else - Brush.linearGradient(listOf(Indigo, Violet)) - - Box( - Modifier - .size(50.dp) - .clip(CircleShape) - .background(sendBrush) - .clickable(enabled = !streaming && value.isNotBlank(), onClick = onSend), - contentAlignment = Alignment.Center - ) { - if (streaming) { - CircularProgressIndicator( - modifier = Modifier.size(22.dp), - color = Color.White, - strokeWidth = 2.dp - ) - } else { - Icon( - Icons.AutoMirrored.Filled.Send, - contentDescription = "Send", - tint = Color.White - ) - } - } - } - } -} - -// FIX (Bug 2): Added modifier parameter so the call site can pass weight(1f), -// letting the Column resolve heights without ambiguity. Changed internal Box -// from fillMaxSize() to fillMaxWidth() — height is now controlled by the -// caller via the modifier, not asserted from inside. -@Composable -private fun EmptyChat( - modifier: Modifier = Modifier, - onSuggestion: (String) -> Unit -) { - Box( - modifier - .fillMaxWidth() - .padding(horizontal = 24.dp), - contentAlignment = Alignment.Center - ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - BrandLogo(size = 88.dp) - Spacer(Modifier.size(16.dp)) - Text( - "How can I help you learn today?", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onBackground - ) - Spacer(Modifier.size(6.dp)) - Text( - "Ask anything, or try one of these:", - style = MaterialTheme.typography.bodyMedium, - color = MutedText - ) - Spacer(Modifier.size(20.dp)) - Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { - SUGGESTIONS.forEach { (suggestion, emoji) -> - Row( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.55f)) - .border( - 1.dp, - HairlineOutline.copy(alpha = 0.6f), - RoundedCornerShape(16.dp) - ) - .clickable { onSuggestion(suggestion) } - .padding(horizontal = 16.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(emoji, style = MaterialTheme.typography.titleMedium) - Spacer(Modifier.size(12.dp)) - Text( - suggestion, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurface - ) - } - } - } - } - } -} - -@Composable -private fun MessageRow( - msg: ChatMessage, - streaming: Boolean, - isLastAssistant: Boolean, - onRegenerate: () -> Unit, - onEdit: () -> Unit -) { - if (msg.role == "user") { - UserMessage(msg, onEdit) - } else { - AssistantMessage(msg, streaming, isLastAssistant, onRegenerate) - } -} - -@Composable -private fun UserMessage(msg: ChatMessage, onEdit: () -> Unit) { - var showActions by remember { mutableStateOf(false) } - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.End) { - Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End, - verticalAlignment = Alignment.Top - ) { - Box( - Modifier - .widthIn(max = 300.dp) - .clip( - RoundedCornerShape( - topStart = 18.dp, - topEnd = 18.dp, - bottomStart = 18.dp, - bottomEnd = 4.dp - ) - ) - .background(Brush.linearGradient(listOf(Indigo, Violet))) - .clickable { showActions = !showActions } - .padding(14.dp) - ) { - Text(msg.content, color = Color.White, style = MaterialTheme.typography.bodyMedium) - } - Spacer(Modifier.size(8.dp)) - Box( - Modifier - .size(30.dp) - .clip(CircleShape) - .background(Violet.copy(alpha = 0.25f)), - contentAlignment = Alignment.Center - ) { - Icon( - Icons.Default.Person, - contentDescription = null, - tint = Violet, - modifier = Modifier.size(18.dp) - ) - } - } - AnimatedVisibility(visible = showActions && msg.id >= 0) { - Row(Modifier.padding(end = 38.dp, top = 4.dp)) { - MessageAction(Icons.Default.Edit, "Edit") { showActions = false; onEdit() } - } - } - } -} - -@Composable -private fun AssistantMessage( - msg: ChatMessage, - streaming: Boolean, - isLastAssistant: Boolean, - onRegenerate: () -> Unit -) { - val clipboard = LocalClipboardManager.current - val context = LocalContext.current - val isEmptyStreaming = msg.content.isBlank() && streaming - - Column(Modifier.fillMaxWidth()) { - Row(verticalAlignment = Alignment.CenterVertically) { - AssistantAvatar(size = 30.dp) - Spacer(Modifier.size(8.dp)) - Text( - "AI Notebook", - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onBackground - ) - } - Spacer(Modifier.size(6.dp)) - Box( - Modifier - .fillMaxWidth() - .clip( - RoundedCornerShape( - topStart = 4.dp, - topEnd = 18.dp, - bottomStart = 18.dp, - bottomEnd = 18.dp - ) - ) - .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.6f)) - .border( - 1.dp, - HairlineOutline.copy(alpha = 0.5f), - RoundedCornerShape( - topStart = 4.dp, - topEnd = 18.dp, - bottomStart = 18.dp, - bottomEnd = 18.dp - ) - ) - .padding(14.dp) - ) { - if (isEmptyStreaming) { - TypingDots() - } else { - MarkdownText(markdown = msg.content) - } - } - // Action row for completed assistant replies. - if (!isEmptyStreaming && msg.content.isNotBlank()) { - Row( - Modifier.padding(top = 6.dp, start = 2.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - var copied by remember(msg.content) { mutableStateOf(false) } - MessageAction( - icon = if (copied) Icons.Default.Check else Icons.Default.ContentCopy, - label = if (copied) "Copied" else "Copy" - ) { - clipboard.setText(AnnotatedString(msg.content)) - copied = true - } - MessageAction(Icons.Default.Share, "Share") { - val send = Intent(Intent.ACTION_SEND).apply { - type = "text/plain" - putExtra(Intent.EXTRA_TEXT, msg.content) - putExtra(Intent.EXTRA_SUBJECT, "AI Notebook") - } - context.startActivity(Intent.createChooser(send, "Share response")) - } - if (isLastAssistant && !streaming) { - MessageAction(Icons.Default.Refresh, "Regenerate", onClick = onRegenerate) - } - } - } - } -} - -@Composable -private fun MessageAction( - icon: androidx.compose.ui.graphics.vector.ImageVector, - label: String, - onClick: () -> Unit -) { - Row( - Modifier - .clip(RoundedCornerShape(8.dp)) - .clickable(onClick = onClick) - .padding(horizontal = 8.dp, vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(icon, contentDescription = label, tint = MutedText, modifier = Modifier.size(15.dp)) - Spacer(Modifier.size(4.dp)) - Text(label, style = MaterialTheme.typography.labelSmall, color = MutedText) - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatSheets.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatSheets.kt deleted file mode 100644 index fd00f97..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ChatSheets.kt +++ /dev/null @@ -1,274 +0,0 @@ -package com.ainotebook.app.ui.screens - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.automirrored.filled.Chat -import androidx.compose.material.icons.filled.Delete -import androidx.compose.material.icons.filled.DriveFileRenameOutline -import androidx.compose.material.icons.filled.PushPin -import androidx.compose.material.icons.filled.Search -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.ainotebook.app.data.Chat -import com.ainotebook.app.ui.ChatViewModel -import com.ainotebook.app.ui.theme.Cyan -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.MutedText -import com.ainotebook.app.ui.theme.Violet - -/** Native modal bottom sheet listing chat history with search, pin, rename, delete. */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun ChatHistorySheet(vm: ChatViewModel, onDismiss: () -> Unit) { - val state by vm.state.collectAsState() - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - var renameTarget by remember { mutableStateOf(null) } - var deleteTarget by remember { mutableStateOf(null) } - - ModalBottomSheet( - onDismissRequest = onDismiss, - sheetState = sheetState, - containerColor = MaterialTheme.colorScheme.surface - ) { - Column(Modifier.fillMaxWidth().padding(horizontal = 16.dp)) { - Text( - "Your conversations", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onSurface - ) - Spacer(Modifier.size(12.dp)) - OutlinedTextField( - value = state.searchQuery, - onValueChange = vm::setSearchQuery, - placeholder = { Text("Search chats") }, - leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) }, - singleLine = true, - shape = RoundedCornerShape(16.dp), - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.size(12.dp)) - - val chats = state.visibleChats - if (chats.isEmpty()) { - Box(Modifier.fillMaxWidth().padding(40.dp), contentAlignment = Alignment.Center) { - Text( - if (state.searchQuery.isBlank()) "No conversations yet." - else "No chats match \"${state.searchQuery}\".", - color = MutedText - ) - } - } else { - LazyColumn( - Modifier.heightIn(max = 460.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(chats, key = { it.id }) { chat -> - ChatHistoryRow( - chat = chat, - pinned = chat.id in state.pinnedChatIds, - onOpen = { vm.openChat(chat.id); onDismiss() }, - onPin = { vm.togglePin(chat.id) }, - onRename = { renameTarget = chat }, - onDelete = { deleteTarget = chat } - ) - } - } - } - Spacer(Modifier.size(24.dp)) - } - } - - renameTarget?.let { chat -> - var newTitle by remember { mutableStateOf(chat.title) } - AlertDialog( - onDismissRequest = { renameTarget = null }, - title = { Text("Rename conversation") }, - text = { - OutlinedTextField( - value = newTitle, - onValueChange = { newTitle = it }, - singleLine = true, - modifier = Modifier.fillMaxWidth() - ) - }, - confirmButton = { - TextButton(onClick = { vm.renameChat(chat.id, newTitle); renameTarget = null }) { - Text("Save") - } - }, - dismissButton = { - TextButton(onClick = { renameTarget = null }) { Text("Cancel") } - } - ) - } - - deleteTarget?.let { chat -> - AlertDialog( - onDismissRequest = { deleteTarget = null }, - title = { Text("Delete conversation?") }, - text = { Text("\"${chat.title}\" will be permanently removed.") }, - confirmButton = { - TextButton(onClick = { vm.deleteChat(chat.id); deleteTarget = null }) { - Text("Delete", color = MaterialTheme.colorScheme.error) - } - }, - dismissButton = { - TextButton(onClick = { deleteTarget = null }) { Text("Cancel") } - } - ) - } -} - -@Composable -private fun ChatHistoryRow( - chat: Chat, - pinned: Boolean, - onOpen: () -> Unit, - onPin: () -> Unit, - onRename: () -> Unit, - onDelete: () -> Unit -) { - Row( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = 0.5f)) - .clickable(onClick = onOpen) - .padding(horizontal = 12.dp, vertical = 12.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(Icons.AutoMirrored.Filled.Chat, contentDescription = null, tint = if (pinned) Cyan else Indigo, modifier = Modifier.size(20.dp)) - Spacer(Modifier.size(12.dp)) - Column(Modifier.weight(1f)) { - Text( - chat.title, - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.Medium, - color = MaterialTheme.colorScheme.onSurface, - maxLines = 1 - ) - chat.updated_at?.let { - Text(it, style = MaterialTheme.typography.bodySmall, color = MutedText, maxLines = 1) - } - } - IconButton(onClick = onPin, modifier = Modifier.size(34.dp)) { - Icon( - Icons.Default.PushPin, - contentDescription = "Pin", - tint = if (pinned) Cyan else MutedText, - modifier = Modifier.size(17.dp) - ) - } - IconButton(onClick = onRename, modifier = Modifier.size(34.dp)) { - Icon(Icons.Default.DriveFileRenameOutline, contentDescription = "Rename", tint = MutedText, modifier = Modifier.size(17.dp)) - } - IconButton(onClick = onDelete, modifier = Modifier.size(34.dp)) { - Icon(Icons.Default.Delete, contentDescription = "Delete", tint = MutedText, modifier = Modifier.size(17.dp)) - } - } -} - -/** Native bottom sheet for picking the AI provider (Auto / Kimi / Gemini / Groq). */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun ModelPickerSheet( - options: List, - selected: String, - onSelect: (String) -> Unit, - onDismiss: () -> Unit -) { - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - ModalBottomSheet( - onDismissRequest = onDismiss, - sheetState = sheetState, - containerColor = MaterialTheme.colorScheme.surface - ) { - Column(Modifier.fillMaxWidth().padding(horizontal = 16.dp)) { - Text( - "Choose AI model", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onSurface - ) - Text( - "\"Auto\" picks the best available provider automatically.", - style = MaterialTheme.typography.bodySmall, - color = MutedText - ) - Spacer(Modifier.size(12.dp)) - options.forEach { opt -> - val isSelected = opt.equals(selected, ignoreCase = true) - Row( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(if (isSelected) Indigo.copy(alpha = 0.14f) else MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = 0.4f)) - .clickable { onSelect(opt) } - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Column(Modifier.weight(1f)) { - Text( - opt.replaceFirstChar { it.uppercase() }, - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onSurface - ) - Text( - modelDescription(opt), - style = MaterialTheme.typography.bodySmall, - color = MutedText - ) - } - if (isSelected) { - Icon(Icons.Default.Check, contentDescription = "Selected", tint = Indigo) - } - } - Spacer(Modifier.size(8.dp)) - } - Spacer(Modifier.size(20.dp)) - } - } -} - -private fun modelDescription(model: String): String = when (model.lowercase()) { - "auto" -> "Smart fallback across all providers" - "kimi" -> "Moonshot Kimi — fast, capable" - "gemini" -> "Google Gemini" - "groq" -> "Groq — ultra-low latency" - else -> "AI provider" -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/DashboardScreen.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/DashboardScreen.kt deleted file mode 100644 index 49bd6ed..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/DashboardScreen.kt +++ /dev/null @@ -1,362 +0,0 @@ -package com.ainotebook.app.ui.screens - -import androidx.compose.animation.core.animateIntAsState -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.Chat -import androidx.compose.material.icons.filled.AutoStories -import androidx.compose.material.icons.filled.Bolt -import androidx.compose.material.icons.filled.Forum -import androidx.compose.material.icons.filled.Quiz -import androidx.compose.material.icons.filled.SmartToy -import androidx.compose.material.icons.filled.Widgets -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.pulltorefresh.PullToRefreshContainer -import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.ainotebook.app.data.Chat -import com.ainotebook.app.data.Stats -import com.ainotebook.app.ui.DashboardViewModel -import com.ainotebook.app.ui.components.BrandLogo -import com.ainotebook.app.ui.components.DashboardSkeleton -import com.ainotebook.app.ui.components.ErrorBanner -import com.ainotebook.app.ui.components.GlassCard -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.theme.Cyan -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.MutedText -import com.ainotebook.app.ui.theme.Violet - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun DashboardScreen( - vm: DashboardViewModel, - userName: String, - onOpenChat: (Int) -> Unit, - onNewChat: () -> Unit, - onOpenTools: () -> Unit -) { - val state by vm.state.collectAsState() - val haptic = rememberHaptics() - - if (state.loading && state.stats == null) { - DashboardSkeleton(Modifier.fillMaxSize()) - return - } - - val pullState = rememberPullToRefreshState() - if (pullState.isRefreshing) { - LaunchedEffect(true) { - haptic() - vm.load() - } - } - // End the indicator animation once the load completes. - LaunchedEffect(state.loading) { - if (!state.loading) pullState.endRefresh() - } - - Box(Modifier.fillMaxSize().nestedScroll(pullState.nestedScrollConnection)) { - LazyColumn( - modifier = Modifier.fillMaxSize().padding(16.dp), - verticalArrangement = Arrangement.spacedBy(14.dp) - ) { - item { - Row(verticalAlignment = Alignment.CenterVertically) { - BrandLogo(size = 44.dp) - Spacer(Modifier.width(12.dp)) - Column { - Text( - greeting(), - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Text( - userName.ifBlank { "Explorer" }, - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - } - } - Spacer(Modifier.height(8.dp)) - ErrorBanner(state.error) - } - - val s = state.stats - if (s != null) { - item { InsightBanner(s, onNewChat) } - - item { - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) { - StatCard("Chats", s.total_chats, Icons.AutoMirrored.Filled.Chat, Indigo, Modifier.weight(1f)) - StatCard("Messages", s.total_messages, Icons.Default.Forum, Violet, Modifier.weight(1f)) - } - } - item { - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) { - StatCard("AI replies", s.ai_responses, Icons.Default.SmartToy, Cyan, Modifier.weight(1f)) - StatCard("Notes", s.notes, Icons.Default.AutoStories, Indigo, Modifier.weight(1f)) - } - } - item { - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) { - StatCard("Quizzes", s.quizzes, Icons.Default.Quiz, Violet, Modifier.weight(1f)) - QuickActionCard(onOpenTools, Modifier.weight(1f)) - } - } - - if (s.daily_activity.isNotEmpty()) { - item { - Text( - "Activity this week", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onBackground - ) - } - item { ActivityChart(s.daily_activity.map { it.day to it.count }) } - } - - item { - Spacer(Modifier.height(4.dp)) - Text( - "Recent chats", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onBackground - ) - } - - if (s.recent_chats.isEmpty()) { - item { - GlassCard(Modifier.fillMaxWidth()) { - Column(Modifier.padding(20.dp)) { - Text( - "No chats yet. Start your first conversation!", - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - } - } - } else { - items(s.recent_chats) { chat -> RecentChatRow(chat, onOpenChat) } - } - } - } - - PullToRefreshContainer( - state = pullState, - modifier = Modifier.align(Alignment.TopCenter) - ) - } -} - -private fun greeting(): String { - val hour = java.util.Calendar.getInstance().get(java.util.Calendar.HOUR_OF_DAY) - return when (hour) { - in 5..11 -> "Good morning," - in 12..17 -> "Good afternoon," - else -> "Good evening," - } -} - -@Composable -private fun InsightBanner(s: Stats, onNewChat: () -> Unit) { - Box( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(20.dp)) - .background(Brush.linearGradient(listOf(Indigo, Violet))) - .clickable(onClick = onNewChat) - .padding(18.dp) - ) { - Column { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(Icons.Default.Bolt, contentDescription = null, tint = Color.White, modifier = Modifier.size(20.dp)) - Spacer(Modifier.width(6.dp)) - Text( - "Keep your streak going", - color = Color.White, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold - ) - } - Spacer(Modifier.height(6.dp)) - Text( - insightText(s), - color = Color.White.copy(alpha = 0.9f), - style = MaterialTheme.typography.bodyMedium - ) - Spacer(Modifier.height(10.dp)) - Box( - Modifier - .clip(RoundedCornerShape(20.dp)) - .background(Color.White.copy(alpha = 0.2f)) - .padding(horizontal = 14.dp, vertical = 8.dp) - ) { - Text("Start a new chat →", color = Color.White, style = MaterialTheme.typography.labelLarge, fontWeight = FontWeight.SemiBold) - } - } - } -} - -private fun insightText(s: Stats): String = when { - s.total_chats == 0 -> "Ask your first question and I'll help you learn anything." - s.ai_responses >= 50 -> "You've had ${s.ai_responses} AI replies — you're on a roll!" - s.quizzes > 0 -> "Great work — you've completed ${s.quizzes} quizzes so far." - else -> "You've started ${s.total_chats} chats. Ready to explore more?" -} - -@Composable -private fun StatCard( - label: String, - value: Int, - icon: ImageVector, - accent: Color, - modifier: Modifier = Modifier -) { - // Count-up animation for a lively, premium feel. - val animated by animateIntAsState(targetValue = value, animationSpec = tween(900), label = "stat-$label") - GlassCard(modifier) { - Column(Modifier.padding(16.dp)) { - Box( - Modifier - .size(40.dp) - .background(accent.copy(alpha = 0.18f), RoundedCornerShape(12.dp)), - contentAlignment = Alignment.Center - ) { - Icon(icon, contentDescription = null, tint = accent, modifier = Modifier.size(22.dp)) - } - Spacer(Modifier.height(10.dp)) - Text( - animated.toString(), - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onSurface - ) - Text(label, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - } -} - -@Composable -private fun QuickActionCard(onOpenTools: () -> Unit, modifier: Modifier = Modifier) { - GlassCard(modifier.clickable(onClick = onOpenTools)) { - Column(Modifier.padding(16.dp)) { - Box( - Modifier - .size(40.dp) - .background(Cyan.copy(alpha = 0.18f), RoundedCornerShape(12.dp)), - contentAlignment = Alignment.Center - ) { - Icon(Icons.Default.Widgets, contentDescription = null, tint = Cyan, modifier = Modifier.size(22.dp)) - } - Spacer(Modifier.height(10.dp)) - Text("Study Tools", style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onSurface) - Text("Notes, quizzes & more", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) - } - } -} - -/** Minimal native bar chart for weekly activity (no external chart deps). */ -@Composable -private fun ActivityChart(data: List>) { - val max = (data.maxOfOrNull { it.second } ?: 0).coerceAtLeast(1) - GlassCard(Modifier.fillMaxWidth()) { - Row( - Modifier - .fillMaxWidth() - .height(140.dp) - .padding(16.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalAlignment = Alignment.Bottom - ) { - data.takeLast(7).forEach { (day, count) -> - val fraction = count.toFloat() / max - Column( - Modifier.weight(1f), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Bottom - ) { - val animated by animateIntAsState(count, tween(800), label = "bar-$day") - Text(animated.toString(), style = MaterialTheme.typography.labelSmall, color = MutedText) - Spacer(Modifier.height(4.dp)) - Box( - Modifier - .fillMaxWidth() - .height((90 * fraction).dp.coerceAtLeast(4.dp)) - .clip(RoundedCornerShape(6.dp)) - .background(Brush.verticalGradient(listOf(Indigo, Violet))) - ) - Spacer(Modifier.height(4.dp)) - Text(day.take(3), style = MaterialTheme.typography.labelSmall, color = MutedText) - } - } - } - } -} - -@Composable -private fun RecentChatRow(chat: Chat, onOpenChat: (Int) -> Unit) { - GlassCard(Modifier.fillMaxWidth().clickable { onOpenChat(chat.id) }) { - Row( - Modifier.fillMaxWidth().padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Box( - Modifier - .size(36.dp) - .clip(RoundedCornerShape(10.dp)) - .background(Indigo.copy(alpha = 0.16f)), - contentAlignment = Alignment.Center - ) { - Icon(Icons.AutoMirrored.Filled.Chat, contentDescription = null, tint = Indigo, modifier = Modifier.size(18.dp)) - } - Spacer(Modifier.width(12.dp)) - Column(Modifier.weight(1f)) { - Text( - chat.title, - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.Medium, - color = MaterialTheme.colorScheme.onSurface, - maxLines = 1 - ) - chat.updated_at?.let { - Text(it, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1) - } - } - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/LoginScreen.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/LoginScreen.kt deleted file mode 100644 index 0654b57..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/LoginScreen.kt +++ /dev/null @@ -1,187 +0,0 @@ -package com.ainotebook.app.ui.screens - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Visibility -import androidx.compose.material.icons.filled.VisibilityOff -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.ui.unit.dp -import com.ainotebook.app.ui.AuthViewModel -import com.ainotebook.app.ui.components.BrandLogo -import com.ainotebook.app.ui.components.ErrorBanner -import com.ainotebook.app.ui.components.GlassCard -import com.ainotebook.app.ui.components.SpaceBackground -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.Violet - -@Composable -fun LoginScreen( - vm: AuthViewModel, - onLoggedIn: () -> Unit, - onGoSignup: () -> Unit -) { - val state by vm.state.collectAsState() - var identifier by remember { mutableStateOf("") } - var password by remember { mutableStateOf("") } - var showPw by remember { mutableStateOf(false) } - val haptics = rememberHaptics() - - if (state.success) onLoggedIn() - - SpaceBackground { - Column( - modifier = Modifier - .fillMaxSize() - .statusBarsPadding() - .verticalScroll(rememberScrollState()) - .padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Spacer(Modifier.height(40.dp)) - BrandLogo(size = 96.dp) - Spacer(Modifier.height(12.dp)) - Text( - "AI Notebook", - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - Text( - "Your intelligent learning companion", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Spacer(Modifier.height(28.dp)) - - GlassCard(Modifier.fillMaxWidth()) { - Column(Modifier.padding(20.dp)) { - Text( - "Welcome back", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onSurface - ) - Spacer(Modifier.height(16.dp)) - - ErrorBanner(state.error) - - OutlinedTextField( - value = identifier, - onValueChange = { identifier = it; vm.clearError() }, - label = { Text("Email or username") }, - singleLine = true, - modifier = Modifier.fillMaxWidth(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email) - ) - Spacer(Modifier.height(12.dp)) - OutlinedTextField( - value = password, - onValueChange = { password = it; vm.clearError() }, - label = { Text("Password") }, - singleLine = true, - modifier = Modifier.fillMaxWidth(), - visualTransformation = if (showPw) VisualTransformation.None - else PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), - trailingIcon = { - IconButton(onClick = { showPw = !showPw }) { - Icon( - if (showPw) Icons.Default.VisibilityOff - else Icons.Default.Visibility, - contentDescription = null - ) - } - } - ) - - Spacer(Modifier.height(20.dp)) - Box( - Modifier - .fillMaxWidth() - .height(50.dp) - .clip(androidx.compose.foundation.shape.RoundedCornerShape(14.dp)) - .background(Brush.linearGradient(listOf(Indigo, Violet))) - ) { - Button( - onClick = { haptics(); vm.login(identifier, password) }, - enabled = !state.loading, - modifier = Modifier.fillMaxWidth().height(50.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - disabledContainerColor = Color.Transparent - ), - elevation = null - ) { - if (state.loading) { - CircularProgressIndicator( - modifier = Modifier.size(20.dp), - color = Color.White, - strokeWidth = 2.dp - ) - } else { - Text("Log in", fontWeight = FontWeight.SemiBold, color = Color.White) - } - } - } - - Spacer(Modifier.height(8.dp)) - OutlinedButton( - onClick = { haptics(); vm.guest() }, - enabled = !state.loading, - modifier = Modifier.fillMaxWidth().height(50.dp) - ) { - Text("Continue as guest") - } - - Spacer(Modifier.height(8.dp)) - TextButton( - onClick = onGoSignup, - modifier = Modifier.fillMaxWidth() - ) { - Text("Don't have an account? Sign up") - } - } - } - Spacer(Modifier.height(40.dp)) - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ProfileScreen.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ProfileScreen.kt deleted file mode 100644 index e9e5edd..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ProfileScreen.kt +++ /dev/null @@ -1,348 +0,0 @@ -package com.ainotebook.app.ui.screens - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.Logout -import androidx.compose.material.icons.filled.AutoAwesome -import androidx.compose.material.icons.filled.Brightness6 -import androidx.compose.material.icons.filled.ChevronRight -import androidx.compose.material.icons.filled.ColorLens -import androidx.compose.material.icons.filled.Lock -import androidx.compose.material.icons.filled.Person -import androidx.compose.material.icons.filled.Vibration -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.ainotebook.app.data.ThemeMode -import com.ainotebook.app.ui.LocalAppPrefs -import com.ainotebook.app.ui.ProfileViewModel -import com.ainotebook.app.ui.components.ErrorBanner -import com.ainotebook.app.ui.components.GlassCard -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.theme.Cyan -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.MutedText -import com.ainotebook.app.ui.theme.Violet -import kotlinx.coroutines.launch - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun ProfileScreen( - vm: ProfileViewModel, - onLoggedOut: () -> Unit -) { - val state by vm.state.collectAsState() - val prefs = LocalAppPrefs.current - val scope = rememberCoroutineScope() - val haptic = rememberHaptics() - - val themeMode by prefs.themeMode.collectAsState(initial = ThemeMode.DARK) - val dynamicColor by prefs.dynamicColor.collectAsState(initial = false) - val haptics by prefs.hapticsEnabled.collectAsState(initial = true) - - var showThemeSheet by remember { mutableStateOf(false) } - var showNameDialog by remember { mutableStateOf(false) } - var showPasswordDialog by remember { mutableStateOf(false) } - - LaunchedEffect(state.loggedOut) { if (state.loggedOut) onLoggedOut() } - - Column( - Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()) - .statusBarsPadding() - .padding(16.dp) - ) { - // Header / avatar - Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Box( - Modifier - .size(88.dp) - .clip(CircleShape) - .background(Brush.linearGradient(listOf(Indigo, Violet))), - contentAlignment = Alignment.Center - ) { - Text( - (state.user?.name?.firstOrNull() ?: 'U').uppercase(), - color = Color.White, - fontSize = 38.sp, - fontWeight = FontWeight.Bold - ) - } - Spacer(Modifier.height(12.dp)) - Text( - state.user?.name ?: "User", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - Text( - state.user?.email ?: "", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - if (state.user?.is_guest == true) { - Spacer(Modifier.height(4.dp)) - Box( - Modifier - .clip(RoundedCornerShape(12.dp)) - .background(Violet.copy(alpha = 0.18f)) - .padding(horizontal = 10.dp, vertical = 4.dp) - ) { - Text("Guest account", color = Violet, style = MaterialTheme.typography.labelMedium) - } - } - } - } - - Spacer(Modifier.height(18.dp)) - ErrorBanner(state.error) - state.message?.let { - Text(it, color = MaterialTheme.colorScheme.tertiary, modifier = Modifier.padding(vertical = 6.dp)) - } - - // Account section - SectionLabel("Account") - SettingsGroup { - SettingsRow(Icons.Default.Person, "Display name", state.user?.name ?: "—") { showNameDialog = true } - Divider() - SettingsRow(Icons.Default.Lock, "Change password", "••••••") { showPasswordDialog = true } - } - - Spacer(Modifier.height(16.dp)) - - // Appearance section - SectionLabel("Appearance") - SettingsGroup { - SettingsRow(Icons.Default.Brightness6, "Theme", themeModeLabel(themeMode)) { showThemeSheet = true } - Divider() - SettingsToggleRow( - Icons.Default.ColorLens, - "Dynamic color", - "Use your wallpaper colors (Android 12+)", - dynamicColor - ) { enabled -> scope.launch { prefs.setDynamicColor(enabled) } } - Divider() - SettingsToggleRow( - Icons.Default.Vibration, - "Haptic feedback", - "Subtle vibrations on key actions", - haptics - ) { enabled -> haptic(); scope.launch { prefs.setHaptics(enabled) } } - } - - Spacer(Modifier.height(24.dp)) - OutlinedButton( - onClick = { haptic(); vm.logout() }, - modifier = Modifier.fillMaxWidth().height(52.dp), - shape = RoundedCornerShape(16.dp) - ) { - Icon(Icons.AutoMirrored.Filled.Logout, contentDescription = null, modifier = Modifier.size(18.dp)) - Spacer(Modifier.size(8.dp)) - Text("Log out") - } - Spacer(Modifier.height(8.dp)) - Text( - "AI Notebook · v1.1", - style = MaterialTheme.typography.labelSmall, - color = MutedText, - modifier = Modifier.fillMaxWidth().padding(top = 8.dp), - textAlign = androidx.compose.ui.text.style.TextAlign.Center - ) - Spacer(Modifier.height(24.dp)) - } - - // Theme picker bottom sheet - if (showThemeSheet) { - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - ModalBottomSheet( - onDismissRequest = { showThemeSheet = false }, - sheetState = sheetState, - containerColor = MaterialTheme.colorScheme.surface - ) { - Column(Modifier.fillMaxWidth().padding(horizontal = 16.dp)) { - Text("Theme", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onSurface) - Spacer(Modifier.height(12.dp)) - ThemeMode.values().forEach { mode -> - val selected = mode == themeMode - Row( - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(14.dp)) - .background(if (selected) Indigo.copy(alpha = 0.14f) else Color.Transparent) - .clickable { scope.launch { prefs.setThemeMode(mode) }; showThemeSheet = false } - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(themeModeLabel(mode), Modifier.weight(1f), color = MaterialTheme.colorScheme.onSurface, fontWeight = FontWeight.SemiBold) - if (selected) Icon(Icons.Default.AutoAwesome, contentDescription = null, tint = Indigo) - } - Spacer(Modifier.height(6.dp)) - } - Spacer(Modifier.height(20.dp)) - } - } - } - - // Edit name dialog - if (showNameDialog) { - var newName by remember { mutableStateOf(state.user?.name ?: "") } - AlertDialog( - onDismissRequest = { showNameDialog = false }, - title = { Text("Display name") }, - text = { - OutlinedTextField(value = newName, onValueChange = { newName = it }, singleLine = true, modifier = Modifier.fillMaxWidth()) - }, - confirmButton = { - TextButton(onClick = { vm.updateName(newName); showNameDialog = false }) { Text("Save") } - }, - dismissButton = { TextButton(onClick = { showNameDialog = false }) { Text("Cancel") } } - ) - } - - // Change password dialog - if (showPasswordDialog) { - var current by remember { mutableStateOf("") } - var new by remember { mutableStateOf("") } - AlertDialog( - onDismissRequest = { showPasswordDialog = false }, - title = { Text("Change password") }, - text = { - Column { - OutlinedTextField( - value = current, onValueChange = { current = it }, - label = { Text("Current password") }, singleLine = true, - visualTransformation = PasswordVisualTransformation(), - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(8.dp)) - OutlinedTextField( - value = new, onValueChange = { new = it }, - label = { Text("New password (min 6)") }, singleLine = true, - visualTransformation = PasswordVisualTransformation(), - modifier = Modifier.fillMaxWidth() - ) - } - }, - confirmButton = { - TextButton(onClick = { vm.changePassword(current, new); showPasswordDialog = false }) { Text("Update") } - }, - dismissButton = { TextButton(onClick = { showPasswordDialog = false }) { Text("Cancel") } } - ) - } -} - -private fun themeModeLabel(mode: ThemeMode) = when (mode) { - ThemeMode.SYSTEM -> "System default" - ThemeMode.LIGHT -> "Light" - ThemeMode.DARK -> "Dark" -} - -@Composable -private fun SectionLabel(text: String) { - Text( - text.uppercase(), - style = MaterialTheme.typography.labelMedium, - color = MutedText, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(start = 4.dp, bottom = 8.dp) - ) -} - -@Composable -private fun SettingsGroup(content: @Composable () -> Unit) { - GlassCard(Modifier.fillMaxWidth()) { Column { content() } } -} - -@Composable -private fun Divider() { - Box( - Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - .height(1.dp) - .background(MaterialTheme.colorScheme.outline.copy(alpha = 0.4f)) - ) -} - -@Composable -private fun SettingsRow(icon: ImageVector, title: String, value: String, onClick: () -> Unit) { - Row( - Modifier.fillMaxWidth().clickable(onClick = onClick).padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(icon, contentDescription = null, tint = Indigo, modifier = Modifier.size(22.dp)) - Spacer(Modifier.size(14.dp)) - Text(title, Modifier.weight(1f), color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.bodyLarge) - Text(value, color = MutedText, style = MaterialTheme.typography.bodyMedium, maxLines = 1) - Spacer(Modifier.size(4.dp)) - Icon(Icons.Default.ChevronRight, contentDescription = null, tint = MutedText, modifier = Modifier.size(20.dp)) - } -} - -@Composable -private fun SettingsToggleRow( - icon: ImageVector, - title: String, - subtitle: String, - checked: Boolean, - onToggle: (Boolean) -> Unit -) { - Row( - Modifier.fillMaxWidth().padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon(icon, contentDescription = null, tint = Cyan, modifier = Modifier.size(22.dp)) - Spacer(Modifier.size(14.dp)) - Column(Modifier.weight(1f)) { - Text(title, color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.bodyLarge) - Text(subtitle, color = MutedText, style = MaterialTheme.typography.bodySmall) - } - Switch(checked = checked, onCheckedChange = onToggle) - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/SignupScreen.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/SignupScreen.kt deleted file mode 100644 index 0ae0f34..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/SignupScreen.kt +++ /dev/null @@ -1,161 +0,0 @@ -package com.ainotebook.app.ui.screens - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.PasswordVisualTransformation -import androidx.compose.ui.unit.dp -import com.ainotebook.app.ui.AuthViewModel -import com.ainotebook.app.ui.components.BrandLogo -import com.ainotebook.app.ui.components.ErrorBanner -import com.ainotebook.app.ui.components.GlassCard -import com.ainotebook.app.ui.components.SpaceBackground -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.Violet - -@Composable -fun SignupScreen( - vm: AuthViewModel, - onSignedUp: () -> Unit, - onGoLogin: () -> Unit -) { - val state by vm.state.collectAsState() - var name by remember { mutableStateOf("") } - var username by remember { mutableStateOf("") } - var email by remember { mutableStateOf("") } - var password by remember { mutableStateOf("") } - var confirm by remember { mutableStateOf("") } - val haptics = rememberHaptics() - - if (state.success) onSignedUp() - - SpaceBackground { - Column( - modifier = Modifier - .fillMaxSize() - .statusBarsPadding() - .verticalScroll(rememberScrollState()) - .padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Spacer(Modifier.height(24.dp)) - BrandLogo(size = 72.dp) - Spacer(Modifier.height(10.dp)) - Text( - "Create your account", - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - Spacer(Modifier.height(20.dp)) - - GlassCard(Modifier.fillMaxWidth()) { - Column(Modifier.padding(20.dp)) { - ErrorBanner(state.error) - - OutlinedTextField( - value = name, onValueChange = { name = it; vm.clearError() }, - label = { Text("Full name") }, singleLine = true, - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(10.dp)) - OutlinedTextField( - value = username, onValueChange = { username = it; vm.clearError() }, - label = { Text("Username") }, singleLine = true, - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(10.dp)) - OutlinedTextField( - value = email, onValueChange = { email = it; vm.clearError() }, - label = { Text("Email") }, singleLine = true, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email), - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(10.dp)) - OutlinedTextField( - value = password, onValueChange = { password = it; vm.clearError() }, - label = { Text("Password (min 6)") }, singleLine = true, - visualTransformation = PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(10.dp)) - OutlinedTextField( - value = confirm, onValueChange = { confirm = it; vm.clearError() }, - label = { Text("Confirm password") }, singleLine = true, - visualTransformation = PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), - modifier = Modifier.fillMaxWidth() - ) - - Spacer(Modifier.height(20.dp)) - Box( - Modifier - .fillMaxWidth() - .height(50.dp) - .clip(androidx.compose.foundation.shape.RoundedCornerShape(14.dp)) - .background(Brush.linearGradient(listOf(Indigo, Violet))) - ) { - Button( - onClick = { haptics(); vm.signup(name, username, email, password, confirm) }, - enabled = !state.loading, - modifier = Modifier.fillMaxWidth().height(50.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - disabledContainerColor = Color.Transparent - ), - elevation = null - ) { - if (state.loading) { - CircularProgressIndicator( - modifier = Modifier.size(20.dp), - color = Color.White, strokeWidth = 2.dp - ) - } else { - Text("Create account", fontWeight = FontWeight.SemiBold, color = Color.White) - } - } - } - Spacer(Modifier.height(8.dp)) - TextButton(onClick = onGoLogin, modifier = Modifier.fillMaxWidth()) { - Text("Already have an account? Log in") - } - } - } - Spacer(Modifier.height(24.dp)) - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ToolsScreen.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ToolsScreen.kt deleted file mode 100644 index b40e6eb..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/screens/ToolsScreen.kt +++ /dev/null @@ -1,328 +0,0 @@ -package com.ainotebook.app.ui.screens - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.AutoStories -import androidx.compose.material.icons.filled.CalendarMonth -import androidx.compose.material.icons.automirrored.filled.HelpOutline -import androidx.compose.material.icons.filled.Quiz -import androidx.compose.material.icons.filled.Style -import androidx.compose.material.icons.filled.Summarize -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.ainotebook.app.ui.Tool -import com.ainotebook.app.ui.ToolsViewModel -import com.ainotebook.app.ui.components.BrandLogo -import com.ainotebook.app.ui.components.ErrorBanner -import com.ainotebook.app.ui.components.GlassCard -import com.ainotebook.app.ui.components.MarkdownText -import com.ainotebook.app.ui.components.TextResultSkeleton -import com.ainotebook.app.ui.components.rememberHaptics -import com.ainotebook.app.ui.theme.Cyan -import com.ainotebook.app.ui.theme.Indigo -import com.ainotebook.app.ui.theme.Violet - -private data class ToolMeta(val tool: Tool, val title: String, val desc: String, val icon: ImageVector, val accent: Color) - -private val TOOLS = listOf( - ToolMeta(Tool.NOTES, "Notes", "Generate study notes", Icons.Default.AutoStories, Indigo), - ToolMeta(Tool.QUIZ, "Quiz", "Interactive MCQ quiz", Icons.Default.Quiz, Violet), - ToolMeta(Tool.FLASHCARDS, "Flashcards", "Flip-to-reveal cards", Icons.Default.Style, Cyan), - ToolMeta(Tool.PLAN, "Study Plan", "Day-by-day plan", Icons.Default.CalendarMonth, Indigo), - ToolMeta(Tool.SUMMARIZE, "Summarizer", "Summarize any text", Icons.Default.Summarize, Violet), - ToolMeta(Tool.HOMEWORK, "Homework Helper", "Step-by-step answers", Icons.AutoMirrored.Filled.HelpOutline, Cyan), -) - -@Composable -fun ToolsScreen(vm: ToolsViewModel) { - var selected by remember { mutableStateOf(null) } - - val haptics = rememberHaptics() - - if (selected == null) { - Column(Modifier.fillMaxSize().statusBarsPadding().padding(16.dp)) { - Row(verticalAlignment = Alignment.CenterVertically) { - BrandLogo(size = 40.dp) - Spacer(Modifier.size(10.dp)) - Text( - "Study Tools", - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - } - Spacer(Modifier.height(12.dp)) - LazyVerticalGrid( - columns = GridCells.Fixed(2), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalArrangement = Arrangement.spacedBy(12.dp) - ) { - items(TOOLS) { meta -> - GlassCard( - Modifier - .fillMaxWidth() - .height(140.dp) - .clickable { haptics(); vm.reset(); selected = meta.tool } - ) { - Column(Modifier.padding(16.dp)) { - Box( - Modifier - .size(44.dp) - .background(meta.accent.copy(alpha = 0.18f), androidx.compose.foundation.shape.RoundedCornerShape(12.dp)), - contentAlignment = Alignment.Center - ) { - Icon(meta.icon, null, tint = meta.accent, modifier = Modifier.size(24.dp)) - } - Spacer(Modifier.height(10.dp)) - Text(meta.title, fontWeight = FontWeight.SemiBold, color = MaterialTheme.colorScheme.onSurface) - Text( - meta.desc, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - } - } - } - } - } else { - ToolDetail(vm, selected!!, onBack = { haptics(); selected = null; vm.reset() }) - } -} - -@Composable -private fun ToolDetail(vm: ToolsViewModel, tool: Tool, onBack: () -> Unit) { - val state by vm.state.collectAsState() - var topic by remember { mutableStateOf("") } - var number by remember { mutableStateOf("5") } - - val meta = TOOLS.first { it.tool == tool } - - val haptics = rememberHaptics() - - Column( - Modifier - .fillMaxSize() - .statusBarsPadding() - .verticalScroll(rememberScrollState()) - .padding(16.dp) - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - IconButton(onClick = onBack) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back", tint = MaterialTheme.colorScheme.onBackground) - } - Text( - meta.title, - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.onBackground - ) - } - Spacer(Modifier.height(8.dp)) - ErrorBanner(state.error) - - val multiline = tool == Tool.SUMMARIZE || tool == Tool.HOMEWORK - val label = when (tool) { - Tool.SUMMARIZE -> "Paste text to summarize" - Tool.HOMEWORK -> "Your homework question" - Tool.PLAN -> "Your study goal" - else -> "Topic" - } - - OutlinedTextField( - value = topic, - onValueChange = { topic = it }, - label = { Text(label) }, - modifier = Modifier.fillMaxWidth().then(if (multiline) Modifier.height(160.dp) else Modifier), - singleLine = !multiline - ) - - if (tool == Tool.QUIZ || tool == Tool.FLASHCARDS || tool == Tool.PLAN) { - Spacer(Modifier.height(10.dp)) - OutlinedTextField( - value = number, - onValueChange = { number = it.filter { c -> c.isDigit() } }, - label = { Text(if (tool == Tool.PLAN) "Number of days" else "How many?") }, - singleLine = true, - modifier = Modifier.fillMaxWidth() - ) - } - - Spacer(Modifier.height(16.dp)) - val canGenerate = !state.loading && topic.isNotBlank() - Box( - Modifier - .fillMaxWidth() - .height(50.dp) - .clip(androidx.compose.foundation.shape.RoundedCornerShape(14.dp)) - .background( - if (canGenerate) - Brush.linearGradient(listOf(Indigo, Violet)) - else - Brush.linearGradient( - listOf( - MaterialTheme.colorScheme.surfaceContainerHigh, - MaterialTheme.colorScheme.surfaceContainerHigh - ) - ) - ) - ) { - Button( - onClick = { - haptics() - val n = number.toIntOrNull() ?: 5 - when (tool) { - Tool.NOTES -> vm.notes(topic) - Tool.QUIZ -> vm.quiz(topic, n.coerceIn(1, 15)) - Tool.FLASHCARDS -> vm.flashcards(topic, n.coerceIn(1, 20)) - Tool.PLAN -> vm.plan(topic, n.coerceIn(1, 60)) - Tool.SUMMARIZE -> vm.summarize(topic) - Tool.HOMEWORK -> vm.homework(topic) - } - }, - enabled = canGenerate, - modifier = Modifier.fillMaxWidth().height(50.dp), - colors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - disabledContainerColor = Color.Transparent - ), - elevation = null - ) { - if (state.loading) { - CircularProgressIndicator(Modifier.size(20.dp), color = Color.White, strokeWidth = 2.dp) - } else { - Text("Generate", fontWeight = FontWeight.SemiBold, color = Color.White) - } - } - } - - Spacer(Modifier.height(16.dp)) - - // Results - if (state.loading && state.textResult == null && state.quiz == null && state.flashcards == null) { - GlassCard(Modifier.fillMaxWidth()) { - TextResultSkeleton(Modifier.padding(16.dp)) - } - } - state.textResult?.let { ResultCard(it) } - state.quiz?.let { QuizResult(it) } - state.flashcards?.let { cards -> - cards.forEach { FlashcardView(it.front, it.back) } - } - } -} - -@Composable -private fun ResultCard(text: String) { - GlassCard(Modifier.fillMaxWidth()) { - MarkdownText( - markdown = text, - modifier = Modifier.padding(16.dp), - color = MaterialTheme.colorScheme.onSurface - ) - } -} - -@Composable -private fun QuizResult(questions: List) { - Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { - questions.forEachIndexed { i, q -> - GlassCard(Modifier.fillMaxWidth()) { - Column(Modifier.padding(16.dp)) { - Text( - "${i + 1}. ${q.question}", - fontWeight = FontWeight.SemiBold, - color = MaterialTheme.colorScheme.onSurface - ) - Spacer(Modifier.height(8.dp)) - q.options.forEachIndexed { idx, opt -> - val correct = idx == q.answer - Text( - "${('A' + idx)}. $opt", - color = if (correct) Cyan else MaterialTheme.colorScheme.onSurfaceVariant, - fontWeight = if (correct) FontWeight.Bold else FontWeight.Normal, - modifier = Modifier.padding(vertical = 2.dp) - ) - } - if (q.explanation.isNotBlank()) { - Spacer(Modifier.height(6.dp)) - Text( - "💡 ${q.explanation}", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - } - } - } - } -} - -@Composable -private fun FlashcardView(front: String, back: String) { - var flipped by remember { mutableStateOf(false) } - GlassCard( - Modifier - .fillMaxWidth() - .padding(vertical = 6.dp) - .clickable { flipped = !flipped } - ) { - Column(Modifier.padding(20.dp)) { - Text( - if (flipped) "Answer" else "Question", - style = MaterialTheme.typography.labelSmall, - color = Indigo - ) - Spacer(Modifier.height(6.dp)) - Text( - if (flipped) back else front, - color = MaterialTheme.colorScheme.onSurface, - style = MaterialTheme.typography.bodyLarge - ) - Spacer(Modifier.height(6.dp)) - Text( - "Tap to flip", - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - } -} diff --git a/api/Android/app/src/main/java/com/ainotebook/app/ui/theme/Theme.kt b/api/Android/app/src/main/java/com/ainotebook/app/ui/theme/Theme.kt deleted file mode 100644 index a78368a..0000000 --- a/api/Android/app/src/main/java/com/ainotebook/app/ui/theme/Theme.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.ainotebook.app.ui.theme - -import android.app.Activity -import android.os.Build -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Typography -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp -import androidx.core.view.WindowCompat - -// Brand palette (mirrors the web app's indigo / violet / cyan gradient look). -val Indigo = Color(0xFF6D7BFF) -val Violet = Color(0xFFA855F7) -val Cyan = Color(0xFF22D3EE) - -// Deep, calm space backgrounds — tuned for a premium ChatGPT/Gemini/Perplexity -// assistant feel: near-black canvas with subtly elevated surfaces. -val SpaceBg = Color(0xFF080B16) -val SpaceSurface = Color(0xFF11162A) -val SpaceCard = Color(0xFF161C33) - -// Additional assistant-UI tokens (used by chat bubbles, dividers, hints). -val AssistantBubble = Color(0xFF181E36) -val HairlineOutline = Color(0xFF263052) -val MutedText = Color(0xFF9AA3C7) - -// Light-mode equivalents so chat/dashboard stay legible when the user opts in. -val LightBg = Color(0xFFF6F7FC) -val LightSurface = Color(0xFFFFFFFF) -val LightCard = Color(0xFFEFF1FA) -val LightHairline = Color(0xFFDDE1F0) -val LightMuted = Color(0xFF5B647F) - -private val DarkColors = darkColorScheme( - primary = Indigo, - onPrimary = Color.White, - primaryContainer = Indigo.copy(alpha = 0.22f), - onPrimaryContainer = Color(0xFFD8DCFF), - secondary = Violet, - onSecondary = Color.White, - tertiary = Cyan, - onTertiary = Color(0xFF062A30), - background = SpaceBg, - onBackground = Color(0xFFEDEFFA), - surface = SpaceSurface, - onSurface = Color(0xFFEDEFFA), - surfaceVariant = SpaceCard, - onSurfaceVariant = MutedText, - surfaceContainer = SpaceCard, - surfaceContainerHigh = Color(0xFF1A2138), - outline = HairlineOutline, - outlineVariant = Color(0xFF1C2440), - error = Color(0xFFFB7185), - onError = Color.White -) - -private val LightColors = lightColorScheme( - primary = Indigo, - onPrimary = Color.White, - primaryContainer = Indigo.copy(alpha = 0.14f), - onPrimaryContainer = Color(0xFF2A2F66), - secondary = Violet, - onSecondary = Color.White, - tertiary = Cyan, - onTertiary = Color(0xFF062A30), - background = LightBg, - onBackground = Color(0xFF131726), - surface = LightSurface, - onSurface = Color(0xFF131726), - surfaceVariant = LightCard, - onSurfaceVariant = LightMuted, - surfaceContainer = LightCard, - surfaceContainerHigh = Color(0xFFE7EAF6), - outline = LightHairline, - outlineVariant = Color(0xFFE2E5F2), - error = Color(0xFFDC2626), - onError = Color.White -) - -// Slightly tighter, more confident type scale (assistant-app feel). -private val AppTypography = Typography().run { - copy( - displaySmall = displaySmall.copy(fontWeight = FontWeight.Bold, letterSpacing = (-0.6).sp), - headlineMedium = headlineMedium.copy(fontWeight = FontWeight.Bold, letterSpacing = (-0.5).sp), - headlineSmall = headlineSmall.copy(fontWeight = FontWeight.Bold, letterSpacing = (-0.3).sp), - titleLarge = titleLarge.copy(fontWeight = FontWeight.SemiBold), - titleMedium = titleMedium.copy(fontWeight = FontWeight.SemiBold), - bodyLarge = bodyLarge.copy(lineHeight = 24.sp), - bodyMedium = bodyMedium.copy(lineHeight = 22.sp), - labelLarge = labelLarge.copy(fontWeight = FontWeight.SemiBold) - ) -} - -@Composable -fun AiNotebookTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - dynamicColor: Boolean = false, - content: @Composable () -> Unit -) { - val context = LocalContext.current - val colors = when { - dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } - darkTheme -> DarkColors - else -> LightColors - } - - // Keep the system bars edge-to-edge and pick legible icon tints for the - // chosen scheme (premium native behaviour, never a "website" frame). - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - WindowCompat.setDecorFitsSystemWindows(window, false) - val lightIcons = colors.background.luminance() > 0.5f - val controller = WindowCompat.getInsetsController(window, view) - controller.isAppearanceLightStatusBars = lightIcons - controller.isAppearanceLightNavigationBars = lightIcons - } - } - - MaterialTheme( - colorScheme = colors, - typography = AppTypography, - content = content - ) -} diff --git a/api/Android/app/src/main/res/drawable-nodpi/ss_logo.png b/api/Android/app/src/main/res/drawable-nodpi/ss_logo.png deleted file mode 100644 index 7e252371e462d312e83ae4d24414be88b00ab745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121222 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 JYP1dRe*m5DGN%9l diff --git a/api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index be43858..0000000 --- a/api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index be43858..0000000 --- a/api/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/api/Android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/api/Android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a7ad822c04b089d6ce8bae7bd7207e31eb01fb88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4047 zcmZ{nWmMD+)5ibAvP&=B0@BUB)KZed(t?z9N#_DmQj3%UONewMB_XAVbglsi(k)%G z!qNf{_ow$g=Q+=uGxM97>&(aba3wy_*CZ!lCIJ9|TnnLYbW6m)2_d?zCi{(=w;*&; z(Nh6{_sOJx?LoIQha;OP6695=|b3Yj>+zLbv zI-2UYyp40Uw#Zu$`yw9s0{}(uzlk^KQ{i;G1P5s8-3RXw(F0(~gKy*$w_1mmx{7h| z?0$AgI^9IxU}vZ0*WFW_)3EkYp;5^O8fGVBWf16B&s~y49Y(#M7j${( z4hM6LBN;Vo2@T~AcQF$knL8mNOZNRo)T7RB%%3ig4<~02uD-MPQGCpm*ep%VTMNIg zu4?-mQSdNuchM5GhDqZy$X5tC{Qpfk_(D~FDU(Fvr8{&&wMeNjR>iLVu<#=}46e(a zV=v_rqM>*b4w?PMXva)YCi*OWm9rJlb}oYBLBQXb0c9jevWAfxAL1nwCBwP!J<}%l zDu-4*$B4)Sl*X|>MRhiTT_9S6`J^03y}xse;TKj7Tr=f0ewcHqR%#SaOhQUy)a zL)q)cI`adaad{DJja9Hn36yK~!>@QtkP((dtBd(vK7*C zX?Sd4RIl$skoi=SD$RGo2+9SKOIZsmN(rQtq+ZlS$?Rl2%X&>v-cQYgQW9zpvot|D z7iQG5DZEwh=VAkEAQ#w=Lkx8gyAn3H0-uA5v_U%}N#^au&a2o-O71C7_9SD@%_WSv)tFOMRvwQof-w4q$kzO?&_zhhfRx%U zVti9|>os=I7Aac!z$iq9@)abGm-bgEb&G#UOQD4fWa7Ebmhaa<_ zpQkQR-(PRW#<GKV*{6ifs?E-=_4o^Gh6Qn97h#m0QWdDlG*Ye8c1o?ed z|1&D~3f!lJ*Oc+tnd@aw|AVT;G0n)KH_0cV^5lN0Yq_L@=Puk92Yp@koNLIb5}`lb z&J(rVWv`1k?#0UZznB?UOp_$q}2zy{e#<{ygPB24hPW`}mb@1B&H zOV@rd4chf|2y+cakUcYmy|UW9IhX<6T3Ui=EqkbaNfCbyt)G%yb{^4P&(75k>xNnU3 zY?~h19KWP6-|G>mXBBdv;aBHr#<8`E##3sAAX;k8d?$$jI^@if{co(s8j@h;Bd>Qy zA)Uc|DWJ^D#q*#lH+LS)Zno(;t134m(aE{qf*wOAq*Lw)9PN*{aq6B=DP zAk~yQBeOwMXme48XGFp6KaI(i=28kBDM@2vL@lN=|Y)I#&vLvQ8ouHqNR(`&!9(h7DHrTkDrEkW3Ux}4jeP2j{fAm?s9SL8ud`cw*YDQ5IUHt&Ux+>l7o9zh~eUvQ}KRqNyM*t~jxO;pMqddw%Z*@Iuf%E*tq~2Fn z=J%*XMDm_4l@;Us1II%xMS<@8}o;-R%{21+6K zh+XBU6Y}r|++B&A2nslF0p0=qslcrCe5fIyw#Sj(0g~T}`Tl6;Tc{A8C;ZdhxQ;112rr`8HA` zt(*7iJR(ihjSmy_JtKYVUupnDJDn2f(JnXaNODUXR&-o*

$ns7Yly@>8)hh=nJQhO}rPkJ6@SI}zphB1g{ z{hX=s4+-Qe=II4+zMI%c`bc zf0v5)KYrHT@01xa^_{68+yb6SlXcB@a3YHEzwPr2ia5W;tj!TMR0dU6?@N8MM;hS` zn$D9yNhmWKeaQ@26=b9Zajg746l0a7H)Dy zX_awWbCI6oT70DeY;D3V7-E=N%K8Ly-glG~H^wzU5zt8b{IsZIPkQnjA6h>HxttG2 zXh$)jtjft3F#XWCM8t6hQE7Xyzt=~41@|uLjR3-bR>r4fS%sKrjcE(N=H*D_qAlG# zW71Sl__-q^0@* zl6nYH1^ok`5mqg#+0qw|Ws+y<$s82l?cs}fRk{7(m8%%GRMeqdhfWOGovsZx@!pA_KBENv z+B$SD(ZLk_J}x+qY96kxQZ!3d=dn?k?k_0fC>iweX+PsLCg#kzi!XJ7r3<{VR+~hv z;bP?58{9K=l3}w{0em_LHFqu+g2wi#?SX6fo1sDL{_MV6E`V2S`{%-#h|`WDyRP+vYWP*b|- z1xjiB6yPBY!2H$32DG)m#QeEb2g$(Ozb%*SVIEE+T?Sdw1YeRLw(N3cT(>&8eDJkD z-mV{uKW`ysYfrH}5HWq!PX3*dY>*mgF8+ulu~qsVuFh4m&6h)>WU|<$vc*U%=S?Np zplOw&^VjVtkBq+?jo)bf`l{mn>bhCjm&MkRsQt+jw@r$9q>qS}4~Jwko3;&P$zt5n z?Kr>ih=h`$m`VfZu@+LTd=U~{R7N)QjWgILCAf5@ug#?73R?WldUBL2Sx5T?+-AOR z&;U;&&2*((QGzG=I$#z2Ap}rP<|Q_D;hfnPt*tX-4Sv)8<#R8O)G?Ozm4(vm*-g@= z7%v1c#_BL`5Vq7XB0SXLq2!ifmW8nwjgHCiB2OqQDC^D_qMxjMBIIfwH)p=bqp7G| zOusie`~)Lo;IShxg}VlxG?Z5j4twMl%r;>RLJL%o`49wOzQ((yr@<$N?oZpN?$j+Z5JtfkgjDW! z$Ci-}4c|+A;6!HI?kgBiDi5F8PfQI4iQLpffUaQ5QNFP~q2zu}9H4q|-ZEj>De#;q;33YB0WKtA~boWP}f&AcfV{rQQ0ax8%UJ{IJUJA zH`DHWA)?0IgBL?m2|hJ1dv@-CicGMp{w)r_n@g5uWjJ%JFlAT7`A1&dbL>4LjyHQ( z1!OKoBb7*1GU!jUqo^C36_C6Dc$LjvJfVW1fH+V5=djyf7e#KfbI~%96^#IHk;)uXV?Jgr*z-3g(f#4|HQ>G$>wV91E`{(6 z@~LoigZ0qiwgD)->mzhJa=hz%t<0)G=E(n;?1_d;LGC1|LgOZny!)Q|ZT zK2_$-r0*KWZ>Tl&R;N|1w Z<{a|B55(|_ZhbTWXx-OWuT`}}{RhH?a*_Z5 diff --git a/api/Android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/api/Android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 4652213353af46bd6cc9bd7466abee8a562e446d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9285 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%0A3jv zDf*!(tJ_I~!d0_yOJ20ySz;l?K;Oq;+6q?7g7&*+8>M(jA~4gG_w>{x;}%Qk^keZbN;1^U@z8l0O35c>t#uXJAWq0 z3cveHt~!Mn$S9_5S!i=cY#!IKGzq7P}EF&VmGfC`^=`{XK4H)@*ZX*k#9 z5dUx5-*`B@VKx?lWr13JxkUkE%EcOUAnqEecgblyPByH7qg=+AU>=fz{-aG}cBPN< zqBEinM6*d^XYz&LcutyMxrW$^1G^)jL&PYhs6|wlGUh`jyvDcw{yu!2_+tOiK5}+7 zQsX4Z<)a!@5OBH@t5}r`Uhm}jm3ij8c=M`^l|1==pb^W^?j=#+H!TP-n(~&69g^I* z$Qht&TOU|xs2|4s52hb_+Upsc!@7s^LZnci8w8*?0PZFB3N8@pQhX0g+iJ;2+82be_Z zF*M$zDPzeP>hrED#jzHZf=VB~$r!5I6 zjjvxZ-1D#GVzdnYyp0YRBNp3v=2rL0Pgq6U8&>nPFX#%`kSt0dT0*9~aWPpk+Rt}z zK+7AE9zOk3#wxNsSw)sx-8Pdm`-N-+4I9zC7-d>;;?bT>_LpDXabty5v2Y zh$V8+7g?g&d++bZT|@Uy?W{ktdz=l47jc}S;IQ6WTs*f=c>Z-I0HEHr0?O?n8md?~ zRX);?JsGXmsn{ix{RGgB)YuN}t5Ajdg(GeqwILJtH~AOPuKx60^3X^J0Hg`pmkqX!Pc)VP{-C zfG4)kK0a{7)Io0gpNA8n*~Pct_*#*|m}wN^;v&4eNl z=k5-&mT1yTr7z8*=RRmoH9;$X=ks)e5CyODy| zsoMOVk4;%Hbuwf~XQcI8>fLV!BUbiq9yg5bK$Nh_hBkN0pDu?Ex0dw%H4@ISE+vwR z%FOzRxRwW?y@H!u&=ou5M=(5xSx3FHT z%VS@hjw4aeKy{=PskZ}gwO9#?*x=yBc|_C&UzSUu*pwPWvR|=_0P2&ftc^2tq2j@F zmgvhVE8KXnpBfMFyiCUK%-|-v*ncxAZt3zV>w>?sh0iE4_03c(1hxo2XH@x>4cp=` zYVDJE1Q~^r`=S$^^gUwA^+-Pj=kCfs&^)<3s-V z%9)&(di4*9$hddzYjUqfMHlq6lq$y^<%}^l+a0_fiGJ%fuBE9`qZ~RS^u>gZq{$x= zYSgyd?PKL@O7f0EP(U#`r$VdK6Uq(ue2#APjty9P+ey;s=iVgSC;V4PDhH@VxZ)AN&h!zyM_Cmg~a(ypytm==R*^JWt@6&f{sLWt^ z!II3=ED41<_llX3Uj$L`_SNbfIH_BfYIsjs&IM$Nr_tAK2sUvdaDPNm1XDsV2Y*W! zxeFjGYoAMUR&=@WGOXl=9gzpx2bnX{>htAZ3aY^ts;&9gxgOU=Pebkq$UCagEZwO9 z^-ZeDYffN3Y0DRh?Z)q*Q8k7aV3OLh+$;TNWx-@s-2_dVCd$dg+ESS!6u`8t$x-SV zvc;YQYv{fUrs-tsY1d`|q-GGK*u_@AS%mxkqif^IZ>DEv3PCZ2Lba z{8n0*SrqN(NwBK}Pwfz=kw`xP=u)o(&5@!S-Yz!fg%JmxTA0|6$&vw$L49_#R9uvN zfu6Ql1#W-d>$b$o>$e+G@A-6xl+#j2LDp@8Pxl%?lN7x(7|%t5xS!a#g-~F~inEep z(XRtV6-z<#W|Bqq)E0~p(H=V+jg=$1Cr|!g(KlZZ8YPwYV#4pg{mhb@ApkbQmnl$$ zK?kAGh0HRx2cwIvr*`%KKc&(aba3wy_*CZ!lCIJ9|TnnLYbW6m)2_d?zCi{(=w;*&; z(Nh6{_sOJx?LoIQha;OP6695=|b3Yj>+zLbv zI-2UYyp40Uw#Zu$`yw9s0{}(uzlk^KQ{i;G1P5s8-3RXw(F0(~gKy*$w_1mmx{7h| z?0$AgI^9IxU}vZ0*WFW_)3EkYp;5^O8fGVBWf16B&s~y49Y(#M7j${( z4hM6LBN;Vo2@T~AcQF$knL8mNOZNRo)T7RB%%3ig4<~02uD-MPQGCpm*ep%VTMNIg zu4?-mQSdNuchM5GhDqZy$X5tC{Qpfk_(D~FDU(Fvr8{&&wMeNjR>iLVu<#=}46e(a zV=v_rqM>*b4w?PMXva)YCi*OWm9rJlb}oYBLBQXb0c9jevWAfxAL1nwCBwP!J<}%l zDu-4*$B4)Sl*X|>MRhiTT_9S6`J^03y}xse;TKj7Tr=f0ewcHqR%#SaOhQUy)a zL)q)cI`adaad{DJja9Hn36yK~!>@QtkP((dtBd(vK7*C zX?Sd4RIl$skoi=SD$RGo2+9SKOIZsmN(rQtq+ZlS$?Rl2%X&>v-cQYgQW9zpvot|D z7iQG5DZEwh=VAkEAQ#w=Lkx8gyAn3H0-uA5v_U%}N#^au&a2o-O71C7_9SD@%_WSv)tFOMRvwQof-w4q$kzO?&_zhhfRx%U zVti9|>os=I7Aac!z$iq9@)abGm-bgEb&G#UOQD4fWa7Ebmhaa<_ zpQkQR-(PRW#<GKV*{6ifs?E-=_4o^Gh6Qn97h#m0QWdDlG*Ye8c1o?ed z|1&D~3f!lJ*Oc+tnd@aw|AVT;G0n)KH_0cV^5lN0Yq_L@=Puk92Yp@koNLIb5}`lb z&J(rVWv`1k?#0UZznB?UOp_$q}2zy{e#<{ygPB24hPW`}mb@1B&H zOV@rd4chf|2y+cakUcYmy|UW9IhX<6T3Ui=EqkbaNfCbyt)G%yb{^4P&(75k>xNnU3 zY?~h19KWP6-|G>mXBBdv;aBHr#<8`E##3sAAX;k8d?$$jI^@if{co(s8j@h;Bd>Qy zA)Uc|DWJ^D#q*#lH+LS)Zno(;t134m(aE{qf*wOAq*Lw)9PN*{aq6B=DP zAk~yQBeOwMXme48XGFp6KaI(i=28kBDM@2vL@lN=|Y)I#&vLvQ8ouHqNR(`&!9(h7DHrTkDrEkW3Ux}4jeP2j{fAm?s9SL8ud`cw*YDQ5IUHt&Ux+>l7o9zh~eUvQ}KRqNyM*t~jxO;pMqddw%Z*@Iuf%E*tq~2Fn z=J%*XMDm_4l@;Us1II%xMS<@8}o;-R%{21+6K zh+XBU6Y}r|++B&A2nslF0p0=qslcrCe5fIyw#Sj(0g~T}`Tl6;Tc{A8C;ZdhxQ;112rr`8HA` zt(*7iJR(ihjSmy_JtKYVUupnDJDn2f(JnXaNODUXR&-o*

NnX)EH+Nua)3Y(c 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 '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/api/Android/gradlew.bat b/api/Android/gradlew.bat deleted file mode 100644 index 16e26a1..0000000 --- a/api/Android/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/api/Android/settings.gradle.kts b/api/Android/settings.gradle.kts deleted file mode 100644 index cc64ae7..0000000 --- a/api/Android/settings.gradle.kts +++ /dev/null @@ -1,23 +0,0 @@ -pluginManagement { - repositories { - google { - content { - includeGroupByRegex("com\\.android.*") - includeGroupByRegex("com\\.google.*") - includeGroupByRegex("androidx.*") - } - } - mavenCentral() - gradlePluginPortal() - } -} -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} - -rootProject.name = "AINotebook" -include(":app")

$ns7Yly@>8)hh=nJQhO}rPkJ6@SI}zphB1g{ z{hX=s4+-Qe=II4+zMI%c`bc zf0v5)KYrHT@01xa^_{68+yb6SlXcB@a3YHEzwPr2ia5W;tj!TMR0dU6?@N8MM;hS` zn$D9yNhmWKeaQ@26=b9Zajg746l0a7H)Dy zX_awWbCI6oT70DeY;D3V7-E=N%K8Ly-glG~H^wzU5zt8b{IsZIPkQnjA6h>HxttG2 zXh$)jtjft3F#XWCM8t6hQE7Xyzt=~41@|uLjR3-bR>r4fS%sKrjcE(N=H*D_qAlG# zW71Sl__-q^0@* zl6nYH1^ok`5mqg#+0qw|Ws+y<$s82l?cs}fRk{7(m8%%GRMeqdhfWOGovsZx@!pA_KBENv z+B$SD(ZLk_J}x+qY96kxQZ!3d=dn?k?k_0fC>iweX+PsLCg#kzi!XJ7r3<{VR+~hv z;bP?58{9K=l3}w{0em_LHFqu+g2wi#?SX6fo1sDL{_MV6E`V2S`{%-#h|`WDyRP+vYWP*b|- z1xjiB6yPBY!2H$32DG)m#QeEb2g$(Ozb%*SVIEE+T?Sdw1YeRLw(N3cT(>&8eDJkD z-mV{uKW`ysYfrH}5HWq!PX3*dY>*mgF8+ulu~qsVuFh4m&6h)>WU|<$vc*U%=S?Np zplOw&^VjVtkBq+?jo)bf`l{mn>bhCjm&MkRsQt+jw@r$9q>qS}4~Jwko3;&P$zt5n z?Kr>ih=h`$m`VfZu@+LTd=U~{R7N)QjWgILCAf5@ug#?73R?WldUBL2Sx5T?+-AOR z&;U;&&2*((QGzG=I$#z2Ap}rP<|Q_D;hfnPt*tX-4Sv)8<#R8O)G?Ozm4(vm*-g@= z7%v1c#_BL`5Vq7XB0SXLq2!ifmW8nwjgHCiB2OqQDC^D_qMxjMBIIfwH)p=bqp7G| zOusie`~)Lo;IShxg}VlxG?Z5j4twMl%r;>RLJL%o`49wOzQ((yr@<$N?oZpN?$j+Z5JtfkgjDW! z$Ci-}4c|+A;6!HI?kgBiDi5F8PfQI4iQLpffUaQ5QNFP~q2zu}9H4q|-ZEj>De#;q;33YB0WKtA~boWP}f&AcfV{rQQ0ax8%UJ{IJUJA zH`DHWA)?0IgBL?m2|hJ1dv@-CicGMp{w)r_n@g5uWjJ%JFlAT7`A1&dbL>4LjyHQ( z1!OKoBb7*1GU!jUqo^C36_C6Dc$LjvJfVW1fH+V5=djyf7e#KfbI~%96^#IHk;)uXV?Jgr*z-3g(f#4|HQ>G$>wV91E`{(6 z@~LoigZ0qiwgD)->mzhJa=hz%t<0)G=E(n;?1_d;LGC1|LgOZny!)Q|ZT zK2_$-r0*KWZ>Tl&R;N|1w Z<{a|B55(|_ZhbTWXx-OWuT`}}{RhH?a*_Z5 diff --git a/api/Android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/api/Android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index dc33b7cf5f9086dbeb439cd00d7e6969c6b69ae8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2188 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 diff --git a/api/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/api/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index e04bcf0a1231749f147c7ba78fb91dcc1fb8b7be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6415 zcma)>WmME%w8sC`&m>V008jS)s%FfXz^cQfu7FwFMi@rK)08FDGva( z3AlHb7*B6TYc<`M01(Iy0PsivxOqy!cLBgh008za06_8!08qGRw&_Se6+l*+s!C6M zTGxv0p-;eeS9{|H00e#i1I(9v3q@x)LGb8&t|)P}TyHkI0o-eV?DOM~i4prO=!9OOW>Mx%5Bj`^?If^N@0_ z&f=e?ppUHT|BrqB9HG^K@*H$J>9jtR@9kSeCO3_fr;SwT*Gn7+4x2?Wiq+7y zlVICVpNZ)@Q(AgZ%p64}ti-je-KNBI*ik%{o9Dvi;Z>tT9|SX^|9}^@S}X;?2cwIM z33cA9Lou}#pq1N2owF_ZkLsNL>d)Y^2WTIQP3Mz_JVcV)aHfXC9ihrRZ8$}(N&8?u z%dHMLrB8L0=h;Aw?h)au4$gkk*)oLPO^LOKtd#Ce?*R?ovIJ#YA6ot_JcvZ+k^KFx zRo1R7{g^r%Pzm0ub6*Aus}z~(m086TsGZ0sGsct83z{(?uLw+b0ZkvqbtZ@6)n0;v z36xeqFna(sBwVs5NgH2fd%)3HoxS-$63;QsIh88i( z_qeyzw~|?XaqQn>ikWAS6pNiMVJ&txa@R+$(4q6ZO+q6fnrJck+z%^lgeZn6usTgJGeJb&Nps@PEDauu=$a# zy}o9(7+C?cVBdE4S%3{5&)~a`TkQUnCrroKRxUXFG2gwi{UKPTcP$uT9VT?nj?u&& z4yi?*xY3q%uCgb3mlYQAIbrI~aOWItT2gVSJy9T#kSI$*4hKUF$@U$;B1T2)L%3QAC9KJOXK-R=fWf?tIQo7p{y_F3cC0E{U{ z?bZTOCf(VOI6LWsF+Ur>`LQ8EPlre!R!44L6+4{#i9qh#mpVOW)6U$g5<5m!%y7gZ zR{M_noKb*}B5GUcz(0hu%lx)E6S9kggT5!}WbcGwx4gUN8?RN$CeZ>e=ae^Q!3)K} z49CrbOl30j)dZzGk^Q*GrRDJabu8-cqPM&X^=1DH1b?>igF;_eGpA`vC60kEz;%i^evC; z-nn4+V?TKzOv|z`p%7*VyE?lN(YqfD=Gmg)K~l`m6-pi5crxc|B(7(~wc0L+UZB=2 zT^_4ZQsi1)2G3O5OVC{OVPW9ZlzU58Nm)N1ThftxHF_Mi+&&y|yrOI*Ab}!>;w|`o zw+P`%We{8-nA*$>Q9WjHSrs*|OMdqSY3bQ-C~;*KU0GJ9;gRdfcC9uv~Q9egux2**F2X4>+HT<842S2U;{IcJDbZOgZs zWAM0b4M{gx-!uv$#C>}jYWDga=LP{H_F(-@;u%CKB1aa3Hg;9{zLyIJB-*4mZw$^u zOLMsefb33{vjT3eq$D!XyX^d?B06@{LWdoDVRf&d9tjK*iK;ytVq-7(5;1|V7F)sNDZ2FSn>k@Z0VX`EdomKgbXVh~3^6S9H!m1y^A0%>y z3T<-Hf@IDT1h>IxB*^P;7$NyMWcR zc_&h#WKvchLXx4+#B&aHy6EoD8LcCV&yJQWk$RB*p|B8Vy)w>vW0nds$QlyzrMC{^ z*eq7t%&?w%*}j;@SP+B!uxgu-{#Xz>eGn#gZ<^`T40>D{2P7ji3BG>6Xf{BzB7xQS zi+|`-YMjN$Wo!2qFpn^@5lOh6HDevEO%~`{ch*{#_tMOAC|L?qe3)G|F&D1`F22PW z(0|$+(};K`e7Q9A!Kg$+IG=9Vfa<7gP5@yLrgm;Md22}j{=i=06pFR;V_1-pOsPIs zV!UpJ<7i^>!O;gryfGKIK>9OkJnkO1Faqj~#heEQ06`z@eVY2K({hqklhq;0>TXJg; zD|}i`dnvfYFP*&O$5xo}TXME1co7#Pnu#nnA$oCOQ1Bas57qjrq-M8<)MYwsP$FgrSB2yWNIYEH}uHPqM5l!ui30P>rC4z=v0zIaYuAOH!Q?z3m zS)e68crx5kIWc`P9$Jr+w7nyj9;Kw9IO=YkLJE>{!R)|p_HGf<@9z^O-Xb3`BbfkB z)|@|6X`tw$j*hw(BzPo>nz9^8n;6S7CpnprX8H#}U)3nMUNO4(`JP98ZT>Fv(+M)d zF?HUKHV+zOo2Y8xh36CjaAC}*<>++qkzzZaOYBQ*gcO{tHe(^hP(ed1Kksc#d?6Nw zFXOza^5>;|>Fw=>m~seDkRQF@U-n5-3s(mlG*KEm&UDQk=3Bo9Z-c8&;s)5oh|A7n zcZI)=4brfpC4XThpqafhWqNIdH^NAF$J`x5Ifr!l3=^f=ZSZR#IP$pwuuJyovAM)q1)q~Fvq57(L#>gl; zL2Lty%;$AzbxT?x2tO%QP0gr)<1VPC%=^GA;AR2uAIqWkAu5(xQdzdylo%-YE@z;Q zM&;0V1es~ZF2yhAGxrWd|976OqUIO3EaHLgIgs2;t4Q!nn;%>+jgdEev_gRM0bjG! zLveY@hFXd+zSVv1jmT<9n;^FwiUr{;174kDH+V{yk*bC)7hRk^*ke9u??5T~*m@7&1{Ee(MKCWc}Hoa_f%)lX~BGR{rBPFs912sa~KI5+*M z@uq3zMQ+{xc%X@%9M)M44*F$hpg%}KN~+)GdsS}{x`GbyI4Q~DcunV4@of$^#AgUJ zY*22GjoP`?h*OHCAh&bhL00#kbjVI+>>*z$sCXI7rg-QsWiqW?$qitKTiL~EedkhJ z>p#Mi`!WeKs_j3fmQkbocaZ#AN8A9<%LJaD;nrHVKNa{eDv4vBR z<|JC6I86^?;1|=Kmnp@3=LVx^1X#{%R~t`Fpa6Kmon0-I;qy+tIW(CKkCuF`J$L4= zY1G&pz{O>V%l754GiOK;|w%)*xq$mTZV1S zV%KREEP90=1}Ne7OoCu@s?`wdFso&E5 zqapwEqgKCQl7g`n{1V12UDR#WgaXI5_&GX;D9jGeI+16CegSw0t=6IyC(Bgd)_w80 zMO43HmLu%Vb5zB7?yfUqd+?#7r2k$)|Lo2#bzvuQL3??AvXO6H<520b2}IdyF!y9EA`=I9%_3e|wL{${NbBJq~rZQ-o75qFptQ5co{EO7xh1)Hf$lDpDAK?P|H|pe##z zDgw;!s}+eJga3`?K*3pF$HFtT3om~d7S`%XkiMI_v-!&SaZQChZ7cKR;wOT?Z-)Yw z@oYAIx02|7S@fq6Qtv}s4q{9OX-lDXi$2RHyF#JW8;hNRDx0+6r`bY=A zclF_-F7NKO2eV)Og2BRFEXEh_cNcGk=9?I9n`iD`-Gu030f4qAK5f;=sF)ZTyq37_ zz#zSTx$hy`b6?wEFx#AF1BMX2*A(s)=eGQ%FRfAV9MK<0H1gNO&a@>I@uxRKSl_Ov z^h+k*u6E3xhP7IfwFCL?2?ra*@l%#BT|FhVw5>hUxYy`i;)4Q=; zn9RMFHO$VG08}EA$BTQsMJ62Am6~Ab_jlpH?;jd4VpN-Z4&Hg#Ev=Cv`7O+8C}8!` zRzb(aFIKnhZDGKjCcx@SI|NVz5H-M4hZR3uuQJ|ZtTBMMN+sQN1$WGc?mCSrhc@eB z-nJJgAZIR**CjMWRJ1jlFH2W!QZBu(!BrVt$Jexij1T{5@nA>&_gY}p6;s%Qi+K#( z*aR~URX>}$Qv`UGH5RuT{G&1Y2i%Lz*ou{gtKyM;RN;@T;2$I)E23;3sA9xC~!!{&V(Qt^U%+aw?d{qb4xR-_e># z#>^9{77(z59yyOvU4778PwJ>mIG_}(kx05pP5wErOypm^tZe@^*mY<}@wTkA))O13 z(VMHKs-&29y}@g{)%bGiUAAzZu(6)8;X!;|OhcA-+Wl>fYrQws?5oR_zo6PoE&r{n zX&{@tM&rVyB;OE*;jHDBK=Q7FVS z&Ax%7o#SvJqf!g((97v%kiBe$pp$9I1MqKkYux&7rH{82A!3X4!`X0)ds-*HCA6u( z2r8GNPV?^Ijyq4&%V^yeN08c~YT#ei!v$Jq&S$mHTzGg1z#EQps(((=(;9_KYK!dO z1={7JvhFXWt$bV1Gpq&Ui#Qt>V3@uYZBAX;ikc)>Ot_lfaj{TRl~@14unbGwrhZeg zOB9C?b*g@!QGWAQ5XWFW2xms-C;xlbZyxI{I6Yq_qd3R|Df#^D`3^4$Q$~NQu(H?x zZ9~iXKE7RC{eJrI(YcO}uUv<*B$n_+BMQ)!uSkni&Xl<`$qS|r&~k6j|2cRtV`cvQ zz}sLVqvUt9uP!eTGnd{0u{^R^X~!;EmUy??*$VQiFm0N(iOk5KZ?K6A3Rv2_$Dxqspl^72!nP z3{^88;$BF9uGKaa11o0A)F-_!zEaKq=Q+Vm+%a9t$6%MbwXqg?=&F^F5|#J(tSYs} z2(tG;D)4bfyXJ_ArA-CD)rnM^D)`#%68guF{zmP$MC_^7x~EYr1(B0c_2-Zq^q(yi zQlzg`d5{uE#*`(R}NV5#!@=8gu8#ro%MhH5j{;k`bV?ZKaAo9}QU zv8zC5|BN)ykWNrSN}}&)6FIMh=o8$JwQBGCL=sfy4Ns|FMb#!fzRY>LML3R3Rr~kEOy{-theeXar79SgXGTmD7?1clXRhqM`I3U!XnUzG(IH@M zmL1|twjy#2r|OP$8m`*G#1xrO<%(jdV}Qa~N0six zI&DA?f%P8WZbI{)X3T-k<|xHG57=$zv^9YlJl3G_2cWn~g2devgGo|;7Zx*Xr_1#{ zjvjQ*r6o_De5h8`7026^JvwjWTPy~jWPo0VeRgN0e-j^FhLNvWYu+mSGi?3VLaD={ zBEYmm%rfof<|{*O?Up?s0L1Lk&}Gg#qDysdFnQCB*5@8ZSxwHU_-xOAP&>ts-ppe~ zijL02PwB?BlxKe+MfF|uK!1;86ib&Vgj(3d^s6JA0J@}r#+RhwmxH~XVVMz31P+ET z%1ocmpF})s8}CtP?IE&Dw(U#xlYs2}BTUDAuV1iPEU;nj><1=TG+fy!=&)i4yp*NO z3aYM)rcFj<7r6O$$F_BP1n#V16+vefGA2K#{k-0J*LWeooWtb3>vQv`G^^vHlO%AK zVQlDGPd6Uy`T+WqixOl%TnOI_OyKh zAS56p$}1qsDmb;3Z&98u9C!;O{0CfrI zj~0lpZ5k_OZFK5a}{y_jhECT?DU2|HrBwh!QEZ-=}zv3(1 z$+ZT(0;;RBp$7n9_58=6ewPaC*G^m__mj@sML5EF?ZMQkv;6H1|Mg1WkXS?eW&{8creZi zZR$0|5nu(oGSdJwvZ4Oqvbx5(L>mq(Ea!L8Khlkw z%vhbo@`Ey^oy0&vh?c8p$&>HjhHN(D$sQr%?aH|GsnKKf41nd=P$g?4U>#~1zd=GH zvggfjHZIWR)iAY=d7QFhx|3QUCGKjn@a{^&5j*z7(SI>2#^g~LF-|{NI$>r1GGrNE zj3pmGpZ8pSaekhJ(Ot=Zt|t7-sRTX2WQ8S5}tPbE7bn33F*<4$p4XPzYgq&ni?W?xdC8z5f9X z&!YA_f^%&6wlVY#dCGhv_cOUhtr}d#J%r#4f-Y4 z?i>-DBvQKLvdkkFN{lz6Ua&*|1*Z%b>c=WNT-P+WPfKekzleaM1QnvRd4sztIfK{;pQ;SU2$P7XPG-6kSHRSSg@*+#J9@6J z7atY%hr<_GP$;x_6P}lk?M%ylY}Z2GQq$;^{{5N=3ioQtZ-Bkw2OD3VA->*sN^yNLHCgoZ|n>D*^@S;xnYEL3v>hN$Ntj|#S+f5@+ z>{ZUsCz-KT^0GNQVe7Zci>`{MXzAtfk$8Za+!WcU@1na&fDs}v@gOZ^XZ{irK3KMS0F(N2cj{_Nns2H=w7luMECkjwgqEQToCdzf%)h zUB}USHC!otuH%UbvYNk0l~J~#qr<-JpoDiL0%sMWGy%^c68~QoNa{Thmb+EmcXp{bdjuiz>iutev}C5`$I#C{DbCCkLQ@wwM?=)CL~ z>|_$Hf>jRR9DLR_IOgSU9qgpHD_l1ZW?46nNOKbc)5;FtM<^7kjeIeXl_O%(&Flg- zEDJCm_-0WXL@W3*jb3$V^vutI00v=#Tbs311B&I~((ri0u>8%xgLQ&O(?OVxRfi_d zJU=Ye!Tq6e)SGF$mH@b#Tg%~dAn{x{Hbmx^uYc1H+okUzwt8qr@@gbg>CLYuCowC- z%80p)3kQ`&A%8K^tBg-fwl@W!FX8Z-@js=S4h4-$A{>T-#U+5Kv&{L)(3}sJ3oggf z3?IAW8M5A8BXMF7TmJCw$Vgc|9%!%h6SK1DQ{;#@$Z&_?tlrU*1@X(PGq39urrNwW zh@rxmwwFP^Zl~{f*^zt{=!&pWnAGm==q;mwKElV?-#uo#p7=EI9+ATXd)Yr>c@MvX zm89P_m+To?AG*XJ8NUf7T8UFXFiF`;=zAk;@KR6i|sZrnKMtdC77YeN3rnm_dH;V%WH>Bh& z>_@mHgM`ehH22Nq?+0( zeYJN}X5DhszVSXEK59s)kNby8xkYAWPWer5?Ez{o5) z7W20~N6kPnweYHvo%vP2#(8b(ywyZ<;N{-BRTc{e_X$*25qETeg!cJMCLEAe`yegw zsn1wMLtVY$eEb(o8C8AwMOFM?NAsgw>U~XfBGR{`x7e5t&k?bY&FrKNY>E)G3LL8& zNwC)v8vy37Z?!D!puT`1k~G{cWnJG$M>qcg8<6``9H>+B^AkkQ#?MHPD|V#iXij|wBldx@Ir_{<-J%+ouv&`EqEaxK1crB{C#-@*0{Wdw_0YLC*J zl5|^r_$NC0C19KCQl@o~HP^WIHoQ}Ty5iCB#Rn%|ANSODy5s%$h5on=JA1uuyoNuO z;+7)C@(XP02IeL*qmN6U=6Hy`+7n&O?oUW$i-mHLMV$~}*dj2GiKh?7wuQ{kUG>ML zr;Qkfe1G!*f7@eCz4k{C_+bn75|S_GAA9WS@wk6TY!!fuVv+BcWC(W=JvimO>kTVq zk-VitKaH=K3YT^f6hV*rR)zm%kaKC&&p75P0uRM}%N! zWoFRd8{j?H`0!T#s3v$OL!8!46b)OgyLS>Ffa*Pn@&A=1*c#c$?|eZjHB9AJEeNMP^ub=`+QT02 zGziK$xT2vcQk#EmC=(W%ODA2d!`EazANxdZvQ_~aCh3+~j29OBW2~I1M=7lsC7bVh zU@bt#Z4I4uyr3Jt=j=CSHUK3YH|3!--RpYxzDqT(kC$+*1)rwH#rRCNacea*X@5N{ z4daD4V!wOaGlrR|i}?4GzUbx(>1--h=8j@L0d~yZ59W~>kKMy^ct2#1F|#KU@;ir4 zoI%#ZSf8+tm4%V}XZ@)9whf4fu*6xwT{fXz-o!^tEhj_*qa!CQmL~f3m1xd`*GGpD zu{~N*zgDtz?pnY{E?@?vthV?k7ET6xwbP2!7K=qZ={@WVEr~krrOU3x6HGVUY3c_* znSdYK?3D|hEtwkHyU>DJkAvdMn8|S))7bvjS zkYPi<(ifqp-`IN3&e_G6hY{fMeeCQmh6QKgm#%;X0QBe=kmQti&;IthD*ljzk&rvC zX*yq^@~1VSq*DLfZ12~}#_6)Gi`rL;x-eBHStId<&;FE{rqdNWs>Ni~vz~DA$ef(^ zC@f91TWcY)E1dxF74wJXyVdCAZtB~!FCVF}hNVvS2gZ#fu}?DpZRD*;a9-ZA8ZdMP6R?W}PF2wJ$Tg1aJXwu2oJBKqN2 zLBi?~ZMFH9Sx5iPBkvz|+OKE`0iv^E+P*hOEL`np!H!R!7k7%D6GPF0IlO1Q>YExu zh!m8A+oDzxmB=6Wmwq;(0PC&e1HqLq16bp!mkSd@0GKBTG$|v`Y#KqVIMd=&Xv9o& z?+_Of=1YmOk^oz-1iOd4+@JSFTUswJRmI=A7P-jwj)4uq-c;gOZ~cg&8qWp~kc=^cEX&D5z&@@z1Ndnh7I_VxVKT zn%jU(Z8)Qv7tqhuVCF^pR60#MyQ1kMw6%GFTfQBgzn;HeN-ojry_cX**5*(#YcPF_f4c81d zC!zua3_f6#E}pk!SrbfKBikaLk|B1v16gsW3nPJA?+tJVdALurDU1;^vTv|QY2N4y znBCWPAVV^CFu?7&QI&S^253L@WN7f?GhQZgT`+g*PV!vy4r+?#P*JLi(dk;^A48k~ zXzJFq#Sl8qX+WQJ;0`iC_MMkZCMZ(6S+ItUzi7OvJ2`&rFp3(fP`*wEuLP~RAn~&X ze1AWDqd`Ws;~^a;Gz1iZ$RcJiNlGS;!24N1C5tIT4JJSujf#TL!P&(_I_j|jgBkS2 z2GE*on_Gs{z{y0*t_b6G^^f0B#65Se-t-49mFGSUIdy)Ozqr8PO7nQt`NF9oSVjS9+!3P=^H}0U{ML+2}=sRRrMo)WDLaSIRx`@V0!>Ip*KXyn1_YD$%2xCD83Qms$pCAJu zt7VdWB(47p;Rgt2?t! z9(Qvocv)37aH7w00n!OcP2Oh~iuRZUb}jBLWy&P+L7o$V{i(lMHbpf0db)wsv0A74?)GZmO%7@ia8h# zi5EjohNgnH#3{{zjrI*)k(k;FA%1)X6}@$0q1#XxRs73>EX%MR<)>~-rOF{SHh47n zXas_tAqDvnny8`gfP5k(TKJv0rtT5a=POy6GTV$9g+yP%BqC-`G^44cc$o2zPXB4l zH|J=N+04B=&T%CI(o=?ZZ@wXl`f5#MVS*0fjI(9NP%IAwzwEnLHt7kCS%$Pfo47B@**MjWTgB$WhJR-hDh44& zmnFn457zzYt0@@1`Kp3Ylx~M^I@BJV?itz>=OddKU58*4dD-oEzH#d^^r=yQX;5X^ zh=5q5rDBTI`w_U>^|Y7>_PVinFO!OSG1)p|anngjP9ix3ypN{mB`&wu@Cw=J?+zZ6 zy}pBZvSF**@lj(TRRaB#C%+-f#>||1(%*X>#Xw3uvI4;lMv?M-AfRN%MsCjHlW)>L zf0RP7CG$|n4C-X^rh-QX=qSgTeFa`(7%ZF^hvx)-X=($KjL97qs zh&kz^DqA-GGIgkZr=PmdSgUeeQ1+sYNFRn3mO#IkrpjsU2QD+Es(WntLq(Nr49 z!=}u3jrE5aq}IAZa+ganMAu)Nn(d`4Xt0-l91i`$hvx!1<5&F=t+Il*JyitOtCQ228 zaI!i&HvDvqB5X`pVBtdK8;d_neH+CsBA!7vD$qV=Q|5`n7YsQ|6&3dIi}xni5Ck;{ z6Tc-W5t2dELx*aQ3q!kC6`LQVV!gpV`4?QyN2URx5P!q*JLoT zx=LZ_)rOHIqi9BIR3UTa8E=9amW|75%%P;?kAWW(_w6y%*$7YxUg&F|;!z05fwzPip#f>1i{s zQ&Qq5)MYNDciWskEI8=lh;Ri~k5FyjE6hS=C>g;gG*3Na<#g~}1%{SIm56pYU^Nw&C9zag-TFeTUANvC0P@=%tv)(E zH5eP}TxFV`&6z4x!zoE3Mq~fQq@DSlsHpyiCEwTHQn6s6_TeHBz!RY`k>I8!%Ho##;ND%ZON+}?^A;FE zeWIDkrZ$!^pDCZ)Pk=BU2?df^gQ6 zi|4tqqn$7#dK#brD&2*Z4j;P%5V^Cghq0Hzm5R!-2>pcVj)!c;KjlfdwYJY|JQ7M? z_QARxuu9UyYL0w!U}95gK$-=u<&V&RzK9$-JZh*v*w(B_BFr!h6_s2}enhN#{x^C34!F6bsw5L)>2ypjsJJsS3iw&prQ_^6S>U@2zUc%y7wO z3#rje&z7t7cz1)enu-&za5JebLtLz@PE+BRkN) zl;uy+wMc({bpmiskfPk7kQ`nDPfR+(wN2^=jY-kJ=Ef%WD(-bBl#n5sxNd!evch!GZiRLlTXXNO!vOXS}%Y1GkJabPKVve(bs`P!up6%qdVN8;zv?ci6v zpP+Y4T8ur8Ty39Gcm&Xd6@#E+1n1+Mloxd6$$9^O(XiCMSPYS3qsbU^rR=xMTm8xF zwj#?noA<4sdA+T<%KTA}p9YS2{K?NwN!QrCrTAs@d=%)E`Wh9r+xgc|8-xGZkCu26 zY*me8Afq#ekNxv(sOQTmH&o-ocanDBWyYP3PqWFQp#+i?*SUl?W#ypu|IT@_H{`XNmA@A zPk-7JpN~xfl&*)o#_!H-H6(9`&3og!`T;h?k_tOoJT`^E*8n6mb*`2J8*cST&{RX| z-4_G~A+>9x6{-bPJpFSA&TO~^G&ythzAKE)gYWQ(=-{GiOHtM6EO@BkH9D%l76wEV zy3Gc*ttqFpcU2^~YW^lZe81MSp#hnFVkL)uw4W`UhND30!39xRfYIR{Ni;pfi}bk+ z35kL^zVfPgHTR{W4^+5s;#%uz@UVGWXOca2OvRSU%0s}r$u+|1oTMfeR6IWj$5C!Q z^k3?fwnx9jL>J*@-E^dbB9k5{lP540AuoWc9r49%hZ)2q>Nl} z;njXkXHb_M`Y+sqO?JN6(5;@)a;cW8Qj=q~sIFEA)xKWagp6MRKqGgD(o4hjtqP8STFk{TeQ_uEJ!tY!I#f`scIo3VDHu_B?q?{cO zPJJv>L+0gMXll>N*FS|{3h&fu6S2!;2X*yTcWz-TLns+EwMyS@?xhni)r(9@72}HPc^GDrI2g1{?!0!vmsX>gF zA*>t9oS9m3C@BE$fKV0vJ?=W_RO>;Wr}nmt>-0B*6FDDbL;~xt5?K(ZCT>=|BTHw9 zp>CD0;p5ET77T7$_k1qs*{tfmY`y01LTJS$r)XV&*I=FyD2&@1X7f8Z>D<3Zc{DIuunw(xYf&|C!?}U-eVb@uBX-k~f6da8tVCU8g@_f>`E(iO&%MY4 zgda=qYCSnl@@l3RrtA~l8Dk+#ScfL2J$)Db5;On(J!Ni)(y+;Tc8^~E_SW)O@{`Wo zVG$`7n^I^OhXaD#TYJBxALH-l%qQM+I|SDMxZCa^LO6lb3J@tK*CE#1Ia%sPYz+c? z`Tb=~LQqyRu&>%BQ_&lqavjtEJbz_omizwfgD(Ldxj-s;+0oAaxLyaxvzWRK%S|G# zvXa>n8~~a10lfyqz>6Gbvy!tP`o5t$mO^X&jy@RdIEyS37pkX!0J?1MEWDM zFX{B<5Lb~YxIxx&t?CGVCt2}F zFdZI1z+%bVh?7?=+&OYF{ko!P)eeqdp|4SZ=lXcM!aCPJPlaKP07B?(R_F==DkfNG z)=X)IN}nnZ-89zx2&`ReR+sW~^KNt&SH!=H*;iYzyyQ$B27e;!_6bM-g#P|?UeW(#(SmL8Ar$&# zQofNcV5{T=tRup6nw{HZ#zud&>zhA`plz)>W*~pgrLnGMu0xl+dv8U9|^5p?<7NZW5}DMM|?psc^?q!$0h=ZZM2&1NL&C#}!@-8}!E7TfsA zTj~`)M4&oFLz0FffmWx3WYGcM71j{tn6<=B11z*UpmqPkb@k!e)XOz14a7I`_nY<) zg?rn*aqS*rOC4pnt)zkcH*o$iLRuu;z2RH2$H}X|?@=c##1(GCh0Ja`dA>>1A2+{! zrfssxMe!E=S%~dWhimn7$?n&WM>Xe&%&E4f!(pUE<(&BeBUfjIc^v!vY{S{GEB=m6 z&3FZ?VdJ`gzSOk&@lTxr1Mn`K)eiIdk)2`C+n?+hY(w`1X}sjTgEximoBH>&lmw4+ z+Y&A(ifI^Ss*YWF+AmL4%3=+R=T39n;8~@FO8i^f@iA92{ToN!p%!EwU`GyS0f}SW zb`$0+3ewMy-Di*TNpqMbs=L`+<{tuQzwBjX|1}`2;Si7UZA%>>-__^~ucWqmN*o&O ze!GJgh;n7AvR1IQPUdWOOBD2ClBh^rQv2_jqHGctjolV@!)2~L9VkuuO!Ruz9VgZP zXep9!6aR<^-BETtEq0VJq8*c_D_Xo1GyLSr$0+!a%kdeRGlY1;nukAGR;Y z>$l)t5%xK}|F6sI>uH_*?VqUn$Mjz&uo6Y;Q}65#rSV4y=Glpg&&dxeMocpm)b_UP z?q}O{h``8NnSsRf0j^FWKh{rDHq)E7f`s(42|skfj!GHax-0g|v2XSJKZ8WNk^}FZ ziwz_Kah_Xw`cuV$$#|)F8friL(+n74p}9G#1{4f-5r()hAMELbKrUbP7_Nv-J)c z=e0{jtTLC~$7(T?wvWicyIrIK#aCD1R;zI;N|*b|jqI+M={cR^dzN?!$)yikIf9fu zs)U*OR5EkNG7I0YGm3ZZb+r8V`{byt`p(e12{DttUrAy3ufGx9+2@Hn6H1A1208$Wdyk~nH%3T-iPuOThauyR-PaE4tt>DyNg>^1>u!NU|Slw zvZ!-8DXqPie#W-7oD9n#W9@F<+-RF9pM;wS^8d8^Zcl(VFJ7oG{`bz^j)lX@z8PMNR#9Q8KtBJhAPY`>`NA)}7IdH@V z`M+vLm(>-X9*=^S{Ph-2rp<@T9Jhob3>)LWcG`h{fdu z{?VkBbWCfJz>T4|e#ah>g;-{Y9HL0pW!{3h+U-(n)o1y5tJZaQEfOv8vxSrWn=p72 z31OH|%Xi&}_xQ=s{b0sOQtOlK+Po*+^ElsmFAwtAfg5B0oDXI69O;yihT^S<&KB3E z)O$AU9jZnq)U$H0h-nXeo&Gyb0eJaV3&oEp5O~>O`^skI#H#H?$LeI>F(=wY`QQP% zTZIhLc`b!!oZiw{NMR0kSv*7veM&j3l(?wKQ&bg8qx(4Zfam!;4lq&C9q#&jxlh)Q z#Fhck=I3YD_gCc-m&ZmPIwvn%H(458FFxTND@!hC)$*iHwP>?F@@6y54q{UR{pUeWoP_@$2! z&3BowpH=-Iy%=k%vOu~0+bU=66OEj20?_PWHJ~-xPTL^A@7Z0NO|?EL-3`k3V|(f` zc%x@nvNzJ1xpmXHZu1bea2dt?TsZ6xOp;hBB zzLgrw+XaOaDK?;%?#;l|?k_&!B92ZdwfI5CTUe{q8pmbY=-LKJe@scz=NLJ17V%xK z!1^OzzxtdLwPNLecUluU>fogy1ABdF1$#*nu+j-%ip;DXxMT2K?Je}o#6Mg`H9F86k>5m=U^LLEt|3>FH()pFngj}W|;oe zQ5xxPhvKcqfo{hkpl=E_s@GYPV>zOkK$=nw#buRWXbK%dFF)_V9PX_}zSx%55mE9t zo<_ZW~KAp5yIAfx+ixJTGozoEM?4WdL{HVy;-=5qGZ(n-w5%ktq z9fxolr6dQ-RSvoda)-%p_Zxz@X$WMEL{ZX+Uy}h4rx#Qe3=J~`>vL{KY6$bGDnQap z6o`dh*qD_^MY#AU;hH9zlo$$_^oQ7mEaH*hr!hm_-yZGxlK0#r`+oL7x)+6Uo8P3C3JlRu}-NiA8!f zg#CObGnP`41pvG#003|>0Py@N0v`bYu1o;Hi2(q>lL`RfI%Kvg@_oJl8U2#{{NVqt zC($72+FezK#zkj`O za&gaoh{fcS0yow_JoyPwv+?q>9%k+tnhgQI2BV9>|Nqdg zV6GcDz!AD7R*eXXOEaDrAx3G57*#W3&q=h3ZeyC+t5Uw;3)!oBm)Z3c8BmdkWp}`x z-q$Nf;!4cjlx6CBGY@OVxo|0Sc)pMc6wQ|hHfWvI;njP{(CSB!uK#z-m!=4WapY=H zH)<{|yd1|?c_^j^A}YO@sbj0FX48M@h1k@nF)(6|3Q=gCj@*(tGoXz}Whu`olUgsK z5*%$_wnG!9MiX(P!T8f# z{Y4`Up_&gg%$AD`hKGSlB@g)0npt0$%*_Uel_?xB`oqO;RfoPuaV`i(Op%ez`xkU- zjX8KNrJ6+^4xb)qD#q|_)&mJP2p;ZsyKFQ+*Pl2A%S@50I+>M~c0>qtc(7=oY{sre zf0O6(Cn&4eoIXT?GL@@H605-)6B@D}Zfu;9=Xt8p%$G&gV(8qwmbHCTZ!(qvv#*pZ zh5fBU{+#>>WqLaT><@Lbz_@EINB>l|$?Le60H(VC<$IOCll{LPF{U(a5!<>uit zH#uIa`~(N$e?jFh(VjMK7eO8qFSNuTLTVX+__jbLG5`yc6%ivmeDF z^^-qimoPK-G0}LKIBA^8ns;Iac!oXQqra_!a-F$u<1Ew)G2;A!K0q>e2rYBrB+l7v zWN)^A0$p5W0EiUMOJ^z_#c`Ay^0CKr}B^Y%n&VK^*f&` z^YG!Gg78MebEH}w>IrP7moAj<%3n-QTVLP~p-w<^VnObj+W8g=v=<7|rU8~cerQH( zMZje@RP*EE=g)8xhSc&nxy;%sT$J^ca)*Bl`WA4)GC86lWvz}nbn~b0sp;VcjcclA zjJ}^kHdvps#;^grebaq-D#XnE@NHy1G65haX||dh2o?dDvMa-%utEyK=Vdpnw-ihB zs)=32ftSbDq!u&H*CEL+gPMOGA&n`02@a^p_B!8RnY(+CVQBnBMv|)>-bT{=@4Ok` zy}qEs0=iRMsP()FbjJ2NNtt*gC7g(JOUt3SGm2)DWplRME)TC;5ngOiX2WtajvU-* zbZR7f2p3b+czT2hg$=>nNbr=qW~Yun?3-0^ct&R{Gxv=L(TODX7c0m3g1N1R+bry)1E4r5*smAA3&F{W) zT2KFqd(m^|AzQgb@wAPL=2(YHok$44&F*03Cn_%Nud`uzr~lRx-W3Yd|6w>d=Q_gE zd3-K&@dB79A|ul%P>f?oBAngq`%5a{bAay(5_y1bD!yX3=P(}g#;J2;9_Aw%wLq-~ zo&)m0Xh44sRdv&Xe3lGrA6iA#_y7*#9HG90ze3b;#4tv>TdB76V&GB)6*K6sp%j?# zPXX+|7SXRFt(JSo0=6Qw(sa>tmf#uWjqxfin1KC;fs-&{IK8M*!m1;5o%wxgXSQ2= z2Os?kRRV|31!ib{86GSKG)&M$T0su`gc<_2R3u%459!pBDcG_J^ibi*z6R^cBJA|B^S_YsSBzBcf>ICqWJc1!T`w1LnQ`$w#};(6>Z!|u zXhKRbcfzV`J80C(1|2uI^`G$Jj)W)x?{QJqk?S=88eI`Y3By$==ZQx#_Jk%nvaMNUFMd$4<(AUJ2Sca zBjtSRO!&Bc3egy-&;chlG?V&~<+94$l-`J;sO!P>kXP?S-c^6@1Zx0zkZL78K-~GF zo7VSl?#JWz{=zlU8TuR{Sw{-EUwVCWBfHGcAy&v!ouOX{ec;`GkYf!W%#IT}${rqj zt6Z${=9fJDu$^wSrtGK49vN-N3vJ_;3eYgGMvbQU>&0Z7nNxJxQC@jbFPtOKjZM!Z zIFMapbzN7$L!ybJ+S9BqBHi(tRqV&9rSgRtS7R7SC%6~MjS zkh;r6kzzJ8*2e(MZKUMdeZy;y<0o;K^RY~+W%Qj^DyYrwu2;Y=;*r6mHJheP(7vcE z_s=q(ec6p2xYQ;YQrY}2gYv{YVJ3rwJDZq3WjVf(a6H3V!LykYwqY4%kJA}To%AQQ z5+A~5Tv~-!!16p(moxM_pOb^W!=%W{vPxEQU`|)tr%{fN^cJO`Lf`9ae+M+U$liE6 z6a6_s%bz{_Drg|xjQE>)@GKJDPc|o3o?;{L!@Cq4VC=s?+k6+nR%S+YU@=&Kf-aDL z!{v6F#wW1c->00@JD;=ODG6eH+xatMYHu8BZ0w~0DXw@sPX0UbmV^X&w9@+Kr|AtH z%}5w#xs51Ohp!yu$yW0U&F(d(=(+*9!sGPiJGLUoY9oQ1ODSZM+(1&x<&Tp{2|f|6 z0DT92ro3XkhKdRH7tx^7M5?wOWD(+5NK0a;Z~lC&8Exrz$Etxf*{w98p|NY=bMU>L zbH^*w^A`k~;i1_Wp|14Bs8TnYn*)-&-#2qQnaBfyVqnp3J!!vJ)}l>U>wsZpgQ)m3 zplEqXbm;ki7&@}?9709Wro~ta%d!%wDF@M7_#E5f)suBjdcWUJAmF93L$UU8m{|-) zRg3Q4gw1OAt-g8YWTNj>=WDi58aWyOaTY;+X(34-&Py3bPKq}dmeKF}8CG(~o*HI?nfn<=qwf%p`!C{V1#?dFb_o)*VOtjVT&P0R3fffJu7AY6gE(Xn$TDK=8TxOK7 zy~iR$E82b+ExP#+?V%1ClMWViX1{b&qi8;)rmHj%K!^tCs!0>d{Qi8kmirUD#IN1< zCSV&rlXht!QBCm$%XY9iUmB08<(Bll2jMF!BYRygB@QgEQA7+(AN8`Q$M&i>crbe% zk`7@_u+SSol0rH(j_*s=REr{oYz#nOHVUTJuItBAq$|HM9dL6TfQWpUZ~4UK%SW7BR&&>D^7N$^;=iEJ@aMV2A7GnbGKclOPU%wR*nDF z_8_h^?^*m~6fGUHwlAD)6~iF%M5-BUs5xUVlAzm1ouK;lkWyH72-j?J+LLYr?=?R~ z9W8urFFhfX>srUZgN`n!B~t+s`qGOYniFfaN^6W_Hw)Jlw12DezE8_#{&3ZsB^3L8 z3va)gta$$`v)+*OdcM}^7=;0F6nNDXT{!gSmdo~CAMj^9B*S^~rPpJEPRZ^YlqZXR zKnz|6Ys{*7FR*w@77+m8yVD-+CN~ony?OfB=d@?}DYM-(lEX ze`(Vp%k+qZ)eIZTjB5S<@M(|)E99WEGk2Xh(KV_YMf9cWrT%u86by~Qr8uiXp1;;< zvR;+C=G~PWU=7miX+gUWU1moGlrO_NTIpGQKj4Xq@Wl7Hdb4{ezxDTTJR0dypPjF| z@UPx$n!q*uS^ZzpvdwGfK4t4s_R(+%7w5%CDfy>5VXK18F5Vk(H?i-;Ro|y`lcuH% z)1hQsQz_=k75kd>EZCwqUD^2dHISeWH=|2b|D@*OLu`v`JcF($?MGhdMd7ax^CM0( z4D#&pW^JMe(k+!HalG!wemzJ%?&{zksBeafyOGTH%Ir3k_Y;aTbo&*}6x-ua%oeu4 zTx~RSQavqoxXD_|?YFQ^G4!=FL7Hy6#6jgNI!)emTQ@1O9+xmJj79O`MSCLHQt^6j5psaYN>*oa^shUPHxM z2_?(;c2=8jc6b|{+ea!Zt(G`NQ7!oLy6mWJu78`D?L4Gr9?ue7e>ZOCH=kkb?WqYl zX02O38@6UFH-`!%V3k((7B%!KcADj^y3Xv9YMe}LcO3TsvubkYm0!08_Tkmgj4S$9 zuGn_W&b`X`FC$#qeCMY%H9^`l?mO+LUFtdXf~Z3}O6KopQ*}>`Bn9yu2WG*(yJ=BH zD;ci>x?V4R%};-d&k=5MLz#|(@p6@f@eJuMY=?OP0>i>^`1YZ3O(2qi={ya{2VuLk4G;O}E+)3>)h2 zUdKF0+D-QZ`LH->@7G@K&a10B^>iBMJ7&ZyqMGK=0Gh~ICinZbxA~j|?S98FOg%}X z1YR@)dTM9!8JN%1YFJ?}q65*rD@)6~!yFCq=mf!|OB zZCu?w157EXk7<`X@A@~_?aiU%M#t*q?r~Qzli&2;Jz7sf2Pp8du+o@c^WMU$10Z2O z1l^x3U3m@(Nt9a(66HCczCrj#-*DP7#>ek`!}I$}jl7_7~X#+U5Y%OU8h_XQc0Dbi4C4r3iz zaHqx%)MUHo;*ZET|A+!+*iFOIiPU`jg2>uw|NaqlkymyLH9KoM|4{n#^Cf+)w;TZ-s455harYorzZS)-4JVtVsl z0>%SaIOA-y^h9l;hfd#K;QGVDBiHV#>h94@KozlrCVAbnfm1Ump*JdLu|twRmUrtg z(PdQ|C5lw7OEibB8Se$Y``=*d0b8pL69q59u2t!A-?Dt(dC7(DY&&l&c{HPDR0*na zWFH%g`*;2~&rv_xuQ5`yrtgFW5!QTXavsPg*&tX2=>@0p^tIT(ejTPM!IatFU$r-I zb6vkVamF0r8($7yJ#Z`}{Y}^1bF=gN=S6X=n3#z3A12=wabW>LBh;KU8EEu3j&bi& z1DuP#msisJdmWtTeWE;SGoAl3Uv(BL6&b^mSm%A^5_Bgg7NQfGjq~mS_ZEpxo^8d&_dgPkw@BStKCf%7$<0?R^iSlE`N^FVD{wBra{=X< zP1Tf!^uV7bDsseUb-c`Y(Q%XLqU-t+ z1i{^D>G=SaKfftWRdfPxGszAfiG8@XF-nK-om4i>?LR!1y9-Ajm}U&49&o44olh54 zZQWv!^ebAGP)5@KzTd8Lzm%`aTWin4Y--3j;T4qOK-|mRv%K-3^RGQQ4Xv8LD6<*s zcp_|&_-b~XkOyEL%`RhN~Q-}ajJvm`0p{p_^p5RQ@Z6(LyWtZS8(eXAot>hZ06O_)ql6EuTsQ! zG)v*iKh*+`>1(;=R;@bt(d*6wUcu#~8}lg8ui`$#Z8%vDk5mI3fod#vEXDU>U8h^= z&&Lu;k>VRo9bd^Ru_ssXSHQlx%V!{7ymj1Pl#ONr*8L{Spn$bIcTM&;lieAdPCZ*S zxvUpfn{f_Q8m^+MCH7R>J*dk8(%X8&noYbUw*F!G3lLmIsy`$sP}f~@nKnReOAru^ z2?VH`5;A+M4F+tK>dxp<(j2o?MAx0(38*A7P`Wt*gO&(i7wR@DMd}r|!g30JjnwyV0`+=`ns;21Nxl)JQ@7!LD%m}6#zIY+Mfk2L8GXT8%6X% z$k@S{+yW=y%`p07?(uC?1F%toR{kMATs!+RiO5%{9RmL0znLFU&wRML=APtT=~A6L zvB26-FqCz<-{&;^yZP1cs5I#cyB*Hy6@0u?NbxX3Ugauy#1kQy1=HV^L4At371M^R zFtUYiyneI!w8}Vmp4s1d6A;71|0Wdvr+r+J&+lJGu@?3cKP|hBEgz4YuOcpv`_>bZ zgdrnl9U2Vntr$q0oCrRz*rBmfUQgTEhs}P)!$zm0P%lKl?N97dHqdNh6cVoG!gbVv zs4Bs88hwgW!+D_8x_8ia6vMdg{r&lRpR5)l_q@WzK z3B&Zbjx>^&$H$HXPMY2C&qfynI@dX!T*0@l7LVUJ4`BWK`6k%@7+~^0>UD7Pk#*2_QS$^C8w-T5>>m?8K&gfnu+g}q=yLv;?J(oA+v9nEJ3PH!Rqx8{oI-Z*m7YlGp2IE= zi1UY?%E(f#LMC~d-l7D#^)@h)TxAZO`=}BQ&n#C*bT5<~`9kvQ2UEK~w&1eapD79% zH(nC+7VUMS4fbCEaG$IYi05HcSE9soqp$?481K`hkv~O#qq=Y1NSajKZh}8|1E&2b z_qYTaSU80Hm&Z*aX${1=C!Ko$W%*_U+JWwdh2m;yThLHncM*t|WV|N%JK%K-nAoY_ zU%6l~4>P?LxQ1Maa=SmG)v}gKJOLBWEA7 zcPZUC;`+#%2@KwNqwM(p}YG0{p2wRN`eQl8YKE!6TIgz}u_wx0n0# zKRUVsU>?`5WK#SE)7Vq{4PvqDWX7I6n`R?ktbkn{nw{G{W9{*XQSqU%3=YsBmgChi9JCyss6?WPa&fu zVfm-oOEKpYD+VJ&1cBQ;oF@CYBp<-j1~DCL-^X|k3F<87$NO$>9&fdOP2UIl!3Uqb z!|fe%+VXrfk}hF;W49S;=R>X!p*4bRKekkCH07>K3h)os&!VkEVurF2$lk8npLQG) zaCR_aR_`qaN8cFH1AO*FG&)V_F8Q3+w)=4uD#xT(3B;cScRGex9@3Xb74!NCkbz_- z?nXu5El{vhaDdo%*=rTU#MU0WA3+409bDn_EMC_htJsJ*-o4<}Ftu!hwY+GyOFKw2 zpivH?70{j3!LH>DcqrfCymv0IP3ZE$8{@H%;>+O+5_OP2D2hB%w2e{lm>F7 zp>{B$KyueYEetS;NQPZOp3*m6^@L@KIDWr2k(Um2rTrC-tbzMFrsAf+Fa?EX+4lT5W+X!iP@=MR6 zZfP^wdn$H*YZWK`FJJDPHU4YKG>`{s;wY{D6S*XGL#`Zus{qIu5TpY8AgTWm==y}y zTJ@8PLG8qs8|RyuJ#}Mo1qz zxtReEWC+!}dLLr#yt;R)FF=G_KXWS7t9Y9mrr*3?u5)y| zkY#sk3Ys+6zp0fZYYmwFtKT-{B-Qyb4hVZI=qB1b>Q6XsCv-1wefozDC;VYi%>a$x zUqT^-U1Oj^Xo5a!wvtUs9KNXY=rz>2b$Xis658DOmU5e`Mh2FTaM#KK~Mx}$!v$U!yS)nY9r6kqk zz+Q{Wk>i{G1o5h*Aqp97-z_he@P5BgNf{4WI2EdNld@<%C682?P^#7gQgmZ_vt_M6 zY`Gs`_~YT53W&@&S5a~BQwELXI!sGQUvo{SxA;nDLXNh-o7LeG5mM3OhhYfrU1o=M zo`^+5?A{2Q z0(3Hui;01lCP7t>ESWH7=EM!tr)CoZOpztBB|Jl=b%VoC-c&4IF{jSi#J2Soso|kH zYXqvNF3pB=)CcAP2arXf9lG}bMHF}dENd2SUS*f#bw#C>j% zA_DHL_yg(zGqevt=+{ujUp=181 z@BD})0`=t%~xaTtJl%;1@z!PqdGJU?5o2yyxhGwO|@ z4KwnHjs5`t0QUhuS%-nj=MTsrELKH4qFv5%h9s%LJ}{=YEy@h60aU6G01G$`sQK2V zoX}Rwwrd8UJ$);pdzu{rS5@YD`CUtd`E?k82(#O^A}%5@r))!*p=W_YUDr&I63)V! zZB(H&lIC{YUdR=vM6wVmu!;PrG&OGa^h5jKTV!>BBlDgnOCcDC#@`Ev_D#X+ZPU=+Mz`AsT!^Z%ADpbI}udL z$WYcGR_H?Vo)C0|7@1XGA2FgQUSRpR6n3B%kV7&sz64+kh{1SLUK9v1?jT>F86Y!4 z2jpjUs_gOD{u*lU*q5}DjEkB>0w1gxNEw)M$te63#vo7rZ$ggwZ|C09XO-3h6{O&o zc)Q!W$l#919%wBz>1DdCO`tzlw3D0>=8t;eCAy{VdjIHz9! zC=bC!YF*siwPa!?3KSSs&Fssm3rLHMf*PALC+$1%diWdg8om(ZQ>B5Q1#n6rM$OCj zA&F};wsq<|kQFW^?-kCdt4j{}<#yb2ZMyik_xvQdH&9=7+4;ZeBEx83XAaZLhr>lY!D`aRbQZK+`4sbf5ye1)ObVG>V#0s@DkDE9~F~%Sw zl|>ae)~;v{BNh~{Q3E4bAq?RF>n^|m43sEFt`+nTUSuXwW^pqk7Jw2=wG$h;7AMct z?^IS{m@r}{-iRVoHY3?0W6bVSPF{-eHA4!98B~sgSG}5l1GMK!9HpFUr}?hhnSM`Q z(L{gG+plS(5B|z+Q|M}u-SF1G)iGc2LmK_d(%_;qFtU~+)9Uj$dlmwwD zjaJ(|NhYSS2OPp-qHpcm!lm>m{0&gCMjz-U10Zu5k`dj1#iA0Yii6fy1tujX_PVJR zGgNq=N=z^qEs&k7eC2xNNd{LE#A%ZhwqN=KQ zdLuLj>FIW%n4xw1Gu*4!4yKu)L#ZfMFE>5MC)dz_BGf7^$EsLbO>}CxTI6^U_@}8_ zNsR1Y%X27YqlU%s&7}=~lOFO#n4;kE(fWW>^Y@)P6#y@+D4-fBk!!}UQ;EpYUQsNY zk_KF(5^va3CtHNPx(Vx>-T34Sz~XrI6`> zQ(}r;@92*oc$~SBdBgxz991hYBOo41DE#Kkn#HjLH5>}ya~;zG$k|Z2_0reNYyia!4Dd-KkZ-|d058} z#?9O-DlWi>W(TQfV^D*G02&al@83oO?gDiVCwCdDzYb(bp_O3#`SA2c`SpERj4F@< zPzfb`&T(xI2F(d_(v(;E*e4~#2UYSIio&L1!f%&rR;E=$Wv_i3*_nMdOOPeSj9#u8 zfWMi<3OKDu!FF%m)@U@UaxOoDXr$@pCBns^1P5_Iu@i1pWrmf`Y7S3nj{d?i+il|f z1w3=LtuwP527eO+u`Y4vGKWD+D#C;wTXavuCKaR*|ANNPI!2oXv8n5B4u7aw3=6ZvGLLE9L!dikd>v(_j z2N?d!D^hPj;dQ~pUx-#v`vukg zRS>;+O~y2YmD~E3%|=f!rPI#|>2hIU71s#8`MzbxE=$j~rviu5;wW$y75k8zYS?J6 z(!BqBfO7hmT1Z;0Q~gHCyaiyC`xGj~a`&6?5<(y`N@dm$X&5H%Fn%(xXb&R_<;55W zTJbZb!FR2EucdO{R{+PHAIei#o#c-JNn(gr#>Ov{G3Nla3)H;arXaNq)S@(>k(r8{ zFw#4d<1O~OY+b#zhh}WC14|l?mJrC17%n1CC_pG>4~wjGAB3)jQ9|J`&*xi&qrO|w^*GuDWi*`5Ou{;)BX)$hCB(H`Td7-(i4O7I7+K3ePLx{ zhZjpv=>MlGd#RZoexZ$#0RM0JtLtHgf9mP{#EKwFzOpb)w*od85r74%gX#lN_1nyK z2cSq|;_X?)DDj--u@-&owR;Sx92uNrWt}IHQ`(T;gDq;M4H_HemzUMd-nhEtS_Ja0Y|aBY(J^QXEqVOw!sC$TIE1TG&`?dS9j4dX5tKW!f@xhrXDin zq!uI0D|O0haHO!;xN9I0^x{ZHqlZO(vwUk@X4}e24=u~?x+OXrc%>!W$HUzk27qS*PO}`!lmrw z(DPOIcb^+;Dvp#Qb~?Le7kw!{EA1}+LW9g6taUD(KlB2fKWR`GVSdWH7BXOd`Hy*S z`y;AM`Ued7HK=O1vTraRmPVrRy2;FxdLg!rut$i6Zv%aJDgHlKlacV05Y4DFz+x#GA+!_)Rlx_nt&apCxhTL~T!F?abt+0aZpQko(Tu5=XU8dsuJ>;H ze4|P^DS!Spdp=`3+4UvjoFoX-yS|O0HGcg*upH9dLEC9yL4&6V^B?(gFy>M-}3kH8b{I@*WRIMu|6b*lS=) zmpM_T!|4LKTB4@F)eBbdpGNlTf@?AZe96{2J_U4n5IBOUU?^5IjVybsOe-Gu) zkawf%50!)t4dlF!T~3oE!diYmm4dXV1sZw)K0D-cxn?0s*CpzK<87%8NSH3G&YaW{1&Q9fxr63aAXTksk{A{MV+qr@S-+AC z<_mf(6BZ$%X66_mtaoenOEEKH{?b1k1k+}W;>o?cvYfph#(7T#4AY92EX2B(j32*C zQ9D@T_eX`!Z#%LMz7kZ#G9UF4t~Jme=7Lvj?N7eu3L`6#DVW5N5#P7O0CKVCD_?)N zYBXE!8Og@tt&kzO9?9!~#TB!+0Bcwp^le-KixB_fKzf&oE*6rw7p z@9_+`7@@Mxf1msau3j1zBz^(bBLD^YT#)wz$enk`$A)qW@Fmq&SALZgdf}ZEx*M%- zT`mC?O+;DV?<|2X4$-oL|4(@!Af($y2s3CTppSwL(*S0x8tOCf)@CA-e~^RIEOar^ z4<9Z&x_{xvB53S-97F50|6&$GFPps+$fTVK+Q(m%1MQn zLUqF6uNx=QJX9{7W~clAFg*C{0QVF!N)tM}%PQN>8w z^LpN8UDIvV(PS(}QWA{(Sp}K8G#nN#9$ z>gW65|KcR4MmU~%PjFT)iWu3?JJBk9E}#QQtXkQg4g9uH3Y20_j66fb!A~w)5yWr3 z|2+~w(Y=6Ej|n!lg8@ADk%hT0Q!>|fO&I#gFZbMsg*OOi9g!88T^1em0w+csI=X2G z{iE0mlIM~JvwSpvS(GJk0Pm9y$-K{Tf&--;#5DoX+vucg!fZRSWS>f zWn*iPhLWm|Pg^fontSJy2!bv8hf>4ZMclL>aEssSI6{$q`+(K=ar$NZMg#rD=Pa~P zM^|VpLF8zr?jujtVr2F|(HjNf3Z2}$=5DU(CBr5_j4es0EEz!HbuTSdR5g8vyKYyZwqszsR~bElH>9iU`G3aF z@W7wl=QF0OOn5d=Xu8vE+!`kTnx*(e8 zMk`ZY^iYib)Zl7GO+)+C8$^i@b7}w{fcq;iu;>@FW89Z7jjupP4WjR#9N)KdE;1yt z$iR{nqoFh0rARBlLZR*F@sIu*>d5tL^RiH8e(ug5nYWjP%dN81!9~|fzO%a(oH9R+ zt((7%EwFCQxEUAuG%Rmqz`8}oVza}gN4^)^yJKmb*;JW{f>}*f zd&THPhW++c_aF=UrE%Un67|<%_{&;mio$unD*|j3?RMVj2wMU&Yp|7S(CiXdFqZv3 zp7qQ<;bezGJgU1f*dVO?N&5pFk+NeT{h4q$x`qU4a2lkNDVT3Ot;PHoNXBkMY{H8d zU5|gMG{xFPB|leSBi3L}egfsOZr+p8+>56!kR8-n(^|_#%t_)rolxH-X=Lz1#me@h zFWe80!F?#JU_7Qy#_jo~(V`FmjE(QcFm8=#AdpXN3n)kDo=NP^?W-R2h+XVPBts8q zB-V443R>pWsi7W}@PQlJ=U+9v{gPtn;)=EN=7u*fr)Ft7k}mzjmcaXL$u1?YdAz5z z{#;c2dGG^0ZNmdBbCzW=P}k1?#cXW>YSZXlXPgKhrgtkVl*}|5oN&yfUE^JA4U6j z|H6U$A4wm+e$g;~2Cc%!Zk^YB9uX`HA;+b?v7RopWkyD0PFn}O?(q2@{{+xp-%L-b zj-eiQXI$BzM_wR|LEuAO8R#Bba+hdA<AfL8-sd5Rqqy=68qAOWj~*b z^tzBSEvG2&7)I%6;MlN`V+^Th*-tEm3i92$`VLrlz=Q5!xJ(;&VF{<3E4oP#GO=f< z)Jo0IvPjgA9X-)`5}&EnDa-q1aRNYgvyE#eT*+wa|lt z9B80mYAL{&?$s^H6E2wjKT;`##wo2D*sZ8gi8I&ftQ+@^Gr_D?aMObb30W%n0B|YOvH|IzC63A-MuUu)VTrvx%j& zgSD2P!TQOaxU$-dozH~Ct8}pBW$|)>P#*+66#tj7K1%6NH(mFOs~H6;0I$$+7s34L zKDdND{8Mwqm3lH)0rKcHMkDvc6s;!v<}uesb#P1O`V7iZs$B`d4Iw2-ijJabe>#>@EYk$6;VY=@_Ck#bRKpF}=c& zZvg@j#qdi-LcZ~u(kk(A7a<5bUurciG7ZC`pe~aUhZ+R}VUcK9#Ni00d20Wm!Sv-0 zucQudaD$;AiBaH!cTV_1H>s2x_`RIgP-M@&M1!o+Iu@r_7El8P)V5#2x(UZkWeX}x zuw_3*TWFh}7wly8uO$!~ZQC4gH5eTe-rKG2y^tQix34CW*XHvwQ6YTYWHBjU5s-{$ zXw_yeM>VJ&MhH<%>;TsO+zI7fMEX2;w;l5{1bcn_io(^E&Yp%9T9LWN<>#gQ`A>HN%eWq7W$0v(3>=efcQt;p zER!fQt(Zdyz8boMa5p?uDCx9tC4WrhHey|cO-Z{_<*%?!J%H8t z^NI*zP`IiI1YTrM0ZJ{t!$wN+e1;kZFaE2k8Hi1TFfVyNhC|LJ+%OFWuBVz&hm}7{ z$PXU-YmTlO`rP{+yWDc}&%aF0uFK{B<;!+m_?ig(F{NyLOPOBy_i-k`CVDx^ly_u; zPOFk^v(wV0YU6)7)z*i?67$*TQCuqF_qLwuf0pL65S?SN^1us{I6x^MoQOph)ewxir{okFJnN8sHytNb z8My_iLJhB2c2t$fbq@3~c02)iv(>*%F#KX3zaWZ{$!)}|PTks(5~{ZeHH0>!x-p&i zOZ&7IOB7iTJPTE~!q;wi$-r+!P{+1#!uWbdyCMrj_zA*=bhF5_@xsKj4dhEawe>tV zs=Q|7MEF}~;6_=D{NV?g0yl$UVDFW!mKN*Y#R%c$l!WFUSNXFq*BtB*ZL4b2k>2Tx zioWJ#>hvhgZo}MGDwL#*#wtqn8WiRF+H`2Zt7@8*{OYs%M`ncX$ZQ9B;zoTfmKzhA zn2?Q#HqZ9l!fNGp*c8v+(ryotkc|>t>(!=r_87C-kqW`}ZALwNU3;e~s{!vVNUd(n z)OJ(D^{>9SIE?7bJ=g@@U^<3X5g9-M9SV{mwv;B|sV$2hiT~kcwMr7+ZhOnL(rJC) zc+44pVN=K_zFH~yZig2i=Bu(=MG3u*udS;9VSA!?|PkH~Ux{yOO>qr{5d@QFFDPb_jTEk{$&o?qZ3 zw8AB+(z%M^iRDw_4t9sJvjS0vh+qv?ag?JJ=8ZIFw3n{xi;~Y{VXIGl8sizUS(x_X zP83vIBNW)-itu6JtBDhAR>cMMYa4X}s%u4TDBME#@06-(OrEWA`ml9n48DEifHy(! z`(FJELkC8qzZ%PcCe%^_)q%oH9F&WtVF_ZcG1{>`WT*Y>whJe&K=VZg8-B%*t6Uo& z%bSgj${@w2#-Nf#MwIp&mqB#^MWk_SkRce}uZ_*1z{D=@4URvxCn0AP7+3f5Q1Rg> zVc0AOREF}IXRR^2t|YYYK0{W(%FGSA$>#~l}g`kQ$#wl^>Bm~6y| z`RvRg^1f<<4PdL`_s#TMdkYgkF&D?R&&kUi{QFb1?qNOuT}Vi!xsD_uhuuCdL$=B$ z4_B1{C!XW=F1l$*1Qr)M2NxELORBML3U7Hj8(fz6gJcrJKV~Z^T4p`((X|J zC4R$8@6qZBh;~y{&o<_n5sc4I1tfLw{JpBXH10sbH|e%d-YzU2Vsyjoq%5+C&dtKm zxZg+|XMDlkd)3n2d57qJ#<(r-WxMj$x_&b2QO$$4LNS*ZyPuYmWZU%+ zwnhcYLi_exq*DjWr08v4(AY@+lVLGXQEbIilwP(WI7cUT$C*5bd?}+4_roCVVi7a` zJyd&qjHG^s&vjah^Z02e?T9ip8Y1V5Ws9}euQ6So0yw_fT|azo{i=a;u3NqcfGY^8 z*4Yn1Oi^tbRL5(zV_LM=63pnFw#UKh-D+{vW2*1T<2vux_vUVlnfmeFF)uVMREU5Z zD~`{)ILF;?V5UATYH4+W+?PljV%*`n8QFNHKpB#@ds}1|>hY=HW<>h zal%>lC0{tcoj?6wdv6gCSJOpnH||XckN}P4C3tYBaSaZ^gS!WJceen+JrDwfMuS@# zcXxMpZJ@dR4gbMEx#K%JXHtV*r(~a9&sv3!doK;>E&OQ3Qi{9UHtcKB;v39J>_Nh? zAc(JUye>f;D1`V+t8F~Pbs7*Q`--vPq-(u&MBeIqe!Bl~m2r;q=1wW>3wj#|-`1dG z)>$6fcrJJRaBO5jThpz{x~%0U1BM|N3Ob4*exc-3sGwDzJ@^OiF>w`Bd+{0{a{_Kg z1}b#nayv)IT^-!j7WuiEf?~_w2!@XnEAtW&nseWuRa_>-_fCMhgZFRTsu_D2=&vIZ z=XfyCmdHHri$dVqqygN|m3u&t@Fx+nW^YcN$yE28^axi;_2K6ciU)QGp^$ zrAWCGmdeSP#ZRvHnjO4^Wb1TFfPrtw-OsIYqx7|c6}5mrr^eZ4uqRPMkA7|j{OZsf z=hgnbG~f>N9WHEg(Z76jRpqVX_%8KqutZt~e;^dn`ZHST5S3FIz)@Cf%=j+OK=T|s zN;Dj?F04)+KJJ9|$wSp@wtB?Rvl#_DIiU`)H_Hu++>B^D`|c!j2=;(v(GRv{ z4Gw&MYbH+JkN3#Gc^^6;W$yC?#M|+Ha9hr+*y((%RW7jiV9^loPPJQ zt3;Y^!0<555Gmk z?=nyLsDSO?w4<{X zi}%|w@%SS}r$hIiss)_PS&oaeU1R?xh7-S9kI=I}nIj5?Q3FPZ8g>;)|Njb1a{q%J zN9}&35ayx(SIxJ_?{*SE-~sfpd;f`kS(I`pPF6!-6gI9Be>@cF>eBYv!9(=c_j(7a z)%ff#O>KyQJaFnTo}1{Pajv*@t99UF!QF7Ab#9gP6VqI3?)cF?{yut*R!+)|g`^4_ zY;|3GC5JNP5<#V*t^2aR|0BV{2b@m48m|<)eI#$Dee79~~Oi_=Q`aZ75k;-21f-Fij8-eH|1w5>fp)z5FQc$Jtipx*yIa|F_1n&=u zh^M~yms}dOP&vUm@Hl#0_>(pOxLzn+|K4fI+F<|krYeA=s^hk7I%!|hNkW%8gm*=$ z$z=QPb~FUG0{T-Gctj|8yVZ&qE^>-=3(gsmALvhRWpYh*W~NKYjFgpNpkXcHz=`XZ zGHB-hmw`YU$BcWCz4k`$#AC>dydcw~Jjoo#4)gNA<8;5+tA^#)8Q8;dR*lOo+CYJr zJ0<5-?#y_UDm$zP7k^JE zcYORR8&YWb=hL(=Mdpz%9YrpcKG^+kuDjFp*O^_rk)BdAeshKBzZ|MSaRY-h%XVnW8 zEpqe@yAsWnBei6Ly}`eoMs)#wSzIjg*q<4koPw9inQYu}G@3A3C!|{KZh_#Guek!5 zL{sNW*1-;0@T($EH6hP&fzWf-+uBWUTq)V&QZE8X?khovH~4F$%BVfov^yx(q+45U zuww5e!F@aAwmj%z8ZpwrgQFQ@%3e%eVt(?7Y1Y@kzSY=x^RSdaN_5wWUgo0wxjk&G zvu3`dRz1JeU0nrFm?9G9y75ql)J|L(G@~`?_Q-N;=f7w1P~-gAsBg$$+aV32Oc|gy zMJH0^KXI+~8}2knfsG>@OV{s%*+ar&Go!> z_({?lNyUbI8|Bae`cy$koLmOy&c+c9Tmu10%RJoWA=GU^fEy$3@J8yM=jNbF!nyz! zlZ#9W#WS%vw~XQy=;pcl%y)F+Mn7asxT8lMif;?wxRaQEpBkF0nQUNHS?oNtd#hJ- z)t!cPBYKa5+Y;#KKU^h$;gedzQ2PWd{+J}}s=Jx0LQpP{k=rQOAaYCRr5>=US}?u# zb`;Lkh?nw23b@p$xA>?6x0qqY%DNZI8gwW8Oj^ds2!%--8AH7?ZLj$d<@IyR+qO)i zGD?)WAifUTmb{BMRbKo)%N8AX831_~(f=q6p=%jt&D+jwTX**tMRWQaX& zt(ItF_dz(d$l$nHsP~L#9X_m`IFJc}P;;$767i)M^OJy9!MN1T zkF+z#F@a{k#=k=xI2DK-_3VnxGhq3 z!m6)A%5;uW62iJA(V0}kGi$cEPh8}6tk5pJR#9PauSn@eEv2@C{lL%8dpWHS^)ZU& z?N?ueVbs_TF)6|~h>1oaE5h;4=jrHra*hA0zlk>q_GG{F|3`IWPLw73D-0V8z zi(nPR;wIlO+2nSquB30 zjVvxgoc{JW+D?1?9NVsPlAaO~BnuBT?lNk#PkRZE?;_bxWuG4ru_#>eoPtL#P6e!$1iFSwtuC5nq%bfWGXgTI))S?@YSm^_z zwXJ6Cm|4#PWigeVcnci<7Ns;PrK98({JHu&qq_7HKdA=RrT2T^&w(-HmjLS5IsR%F z87SWE5fez5l08=hVpOcY1Rq*kSbLIJSbxvGwIDMtuABS2#S3qa)eD)%b3{O+v7?B; zu-Cm(D7mT@F*7)|g<~I4aE{gKKlBvxZ+{6V2){S|vXID_W#gtx(9R3HT1}bUsN}LS zwZ@}cRxBQl*k~ml^c_sTIG+b^LwDD=BA?}Mo_n}3-MYq+Z7%lA*grH86O#8q^hBf^ zUGdLl-h$Oo6uxGzhfNcTV7snVkUAD0*I)?E_WPLrOkW!dAY%Ko9#YZqfO^Vm*EH{f zPE0?+7M#e@Q*+q*-OtB%#KO0fQGhs9GLxi;R5bPJ@Nm)-t_IP2uK5}M;K}RyvoEGu zG#TQD+GXshkKK~X-b49Nb)+}%Ku6#9$>m*HBcF0-7)89Uh!>oP^WYI7{WS2y9Qg586w0j_tG%cF2p) zv3P~AH(B3|+04u@{#l6eCpG^Y21L@+0`3tQkx%LJN<>MDQH>snZ8N<$j)7)uS(D|x z;!wW0q+5B-9Db6fQGiXDgHcj)0ZJF0l2FdK_gTO14@kJ-+TW8GSZcS8Q&R4!Nc8II z;+Xs~x9u^CU&LX?cMTXCuZ=%?rqaE)FS;OXRH`sYI_QD%K_p;GG5`IyQajNjFY5c| zMm(m5_K|;+^9>=hmXH)kJW{s$f$TaxNhS2gpd>#pAI_bXzqcq5PgYGA9&m~O?~SZk z)acD6jIn8_(*bzrN)#w;^8t=>f$|F?DR-CRB$3@EMV|KTCL|NW)QrF7kx zh!;uW1*p8%X{Ovdn3=zPfeCu{1qW*KTv?_HS`07x*|>qPNApE{`kBZ3I!dR_E!ZE+ zOGDjR2X?n)Sd{w(w9omHIFkn>GO_>Q+eAD%6r{yYa*y7<7PV2URvSd|N~)Qji~e4&6VDUeGfh zS#JXh3gH-2Gr>OzKEbq}Dq4}rcTt%?Uk3l#qrSF(;~qwVS!_J~aV$e^pUmXC0ZraN zby}%G;Ea$0Q>f6+b}QFRyjt`p~U?zchc8|SI|Fu^Ucwje{ zaxOc%p24(qcn{y<`W{H%IW8T4w1E{~eI!v^51L6MD*sfJlcut19{g zV^B-fK}a(Gk8Tt~eXDPsOJ?An=Hq+P;W^!L(;UJ7R7iwEjr@7_RkOC`Bs0w5>LtJc zhljWNd!J3INw1mnImTt=DH@#UASnMt=|(-{Fuvp*Il48Db-G!lw|KQAnKnqf?OphC zhX_i){<5i&F4=i$^I>cGD>U)$>+=b_zh+Z(UbY`?kiiwNsGjx2IK1P5HYfH&7Dw5X z%D9R*@Q<&o_%jXp58=xm0`tix>V^~E#4lw1|0vwaaff3Mn(}6T^3XIdntsZw_m5?w zyxV-|e%HXY2qHuj&{Ob^g_P~TEAFq(wa z4`RtjGp%9!aB`{b;_}}P^F)^0xMDoPHlMm5Aoo6{(Tk2{Hik})`1K-_P=tEnoQ1-_ zZYe0u5C5}4X^t4HMTuy?YsU~0V4iPwu&K$&NZIy*(`A02#_AGry7snjDp^mp+6A(Y zFr1LabGNUvGWIb9xN@cLe=3T@D7c@ig6*3Vt`qFs+CkE>~4 z)UY)>kuAF}L_&5fLoZ#ms9Mg2$3<{lTFDLTOv&Hxq(R-QnHh35&mHug5XxEgeVuB+!eD*-TyfC&&jF8}+Jb4Bx5t-2!k=nW>7km35H;H`2QF z%jck|@6Wz9-m_W{%y;1GO>dV1@%6MjORh6tk}7&*jIE@)BhQh?7t4UBq0EKfPj-Iw zE5+)9E5kbhc$H*H6qQA7c#x}%V77~Lg0v@Qg=hcIIG6dhYnY-Gv#yl1e4NJ3i71(B zPO|w@@mYP-So@!Pd&I$W&k2v5WlI!X_?LLR|J)iP4@D^R4zA0je_75v^~IC$6#N|H zjByRB-_&Eb*szxW)|jJkySCX#7qUJ6=V!#IVAAFh64X}0xdw;B#5fl`u(2g8 zM4sjZzT(8GxtO1Hr&Y^m{mWl|Nke`8)&-e3wdRD!&;8y9P{8#qW*aY-*?X&Vxv7l?9W!`$ zwBTFa!Yz=a+j_4UIg&rxqefl%>la?Rq_3(j=z7kf;;Hf_dNQUDzvi#Q8jlEYz)an*+sWJUa&b1bM5f3n3PzTF5EUrB?ElVSY-H6UMbkO^b@NUPp z@c3z35;zJ%yG)hv3r?=}2VAP=GHtI@MOZK*m2sv_M7W;9+Qx{FrpJ}s?jcJ}@+il# zL;;RAeLEkjp_h?Y3*+#nC|XNK@t=rnG4!{Oa1Ytk|=N!t?n z@5fD5ru5i_@PjANd87qW)8KR}PrK57o<^`U_o95i{yNfI0^BuVTaR0@G?>%;KgHP7hXvV4)ao}jb+c7B(P=L6IHbVU8@_WrnmbHVN3 zv6hT~jrbkJrBD9s{i>6DiQW@-D#qQO!7r-{>-#bsrpl35&s4_x*iI-5v&0PRFlMdM zXKbU@l!#T2;zBmwz7K*8j;C}G3IJaDfZkArrD$X#ECDK>cm4@ZiAb^`k4|?S)@z3X zUR$gvxP%GYT}B+?@?1vStqJ+zf`2QD9OpfxHHIio5<18uDg?NP3QiBrG5YE{&6!I5 zQlcG=7LR|taMxdb>Ha;sht8_tKhcyt2ub=@+{W74V}(<>yO8NcctXBY4H0 zw(~cdB0R;LX+X_Ks=S)%0R!P6jIF}JQ-LTKTceb3zE#XyWQOCGGsLQv%+<*C?F1f9 z@4{{Sx_;-G2`_a}YqaUzUqkD4xQ|z;BKCoEOXALF^ck1S*CaQe&0B^jB=rgpqoK*2 z-^yVpIsNVqs--G?xj{XpM%9}~%80Y6xzWHVqmvgJ51gg5$Zy)4goY}XTz3p&xx)p_ zNZSn6W*>Akqn}4@7*=7x(r13c*vONb;7XXE0eLnfUoG<<0Ye=g5fXfg%--OhlqL6B z@b%7bHB^4ip~k9kuuDulV1-o6#3Qr}=B40p(| z;|)&-X!2GOLvSS}a~z=YzRMn6)$EPl#0S-~mME08ItDf~L9Ma;$aQ#KNU$(^P~4Ar zqE}BFtGk}nzKAC>v62t~DzhDfC)9WZ1P+qzs3xjizI`Rfib6grr#D!6YKcu+si*Qa zRY6un<|=@KBlHc7i!6)*ehJ5m|*=ebE@ za@>c4rVlHV=%fe~rUxkpl^Q+yLLFG}29c4Fqc59KYp7$X=)W6?LYg4|3Yy?G#_-2{ zQMdF8g_`ttne z3UN=rx$lG^&*IdXs?VR#1|nKn5IljRHm7bC11C|Qodl?2k_b2_rR+Ck50?ki{j$Ekiy9I+`Oj=dU zfLWxUnD!`XXu1Q-{7F;${$ru}gHIKrD3|l!5k9oP4sN4mUF#C~KF~Ge<9ga9A$JA+ zMf5XG6jZW|->#&iZaKJelgAlu7JV?q1K_D2(5}9m_?-%JOxbiN&E`bx+M%X$Hw2CU``^~N0s!@1yZTbovhD68InHiJ$Y2xE zkTt0d!BSACP;AU!Txhv&=);rj56RML%+F#(zQh(Ap`^LVD-V`2a!nz4Dix;+>x+zZ z{e}Q~eqeCS;zF%Gp{TE}KOa9ePv0v;zmB7;P!NMu%iJz1Q%yyU&+O^5RATq-p9UXC zXKwliYaHluY??bq>JgH~#~@562{BEz4{5vjdn^?gTPfLEV#tLH(Wp{2DpHqpYoxOT zSV~p0Zhl60eSB!RD7Zm|-5yAX6JNq!)HhJAic9?{))yPL#IATd^aE3s?JsEiy~e2_ zXf6PQL;Rw$4c7+ayE<4!HjrUps;iQpWUW}NDp0)Hr-ri?sT?acCT@m5Kt|~hp)P>s zrjJvGcdL|`P#M@?b|UPN`BmwJZwzF~{io!}(_N4h?-$vHu#y=^8yM@=QDq?^X1|hw zl|evzF@}smQfAwWFZnI_Nw4QSKdcw;UJEo-u$Pfone(D_iv#*Iw2$AkDEZW z2o(4`o+AcH9&6={vuZhE0h#!$Rv#8hVU}q*WB#b_;dGLS<9{+8Ex_97iUka;s3JK0 zMW0)cB9N)!&_$@f^d_uU87XrxsK%@a+nHn}ZNi87#0f|+M?*dkJp5HQSY9uE2TXMJ zUM-X^oCr7E+paVni|h{=Eh(dDVZTvTb55hThhD zA?Eqx@tZd{nn@6Qo*^7M*RhCb?%R2bHcPkB!Z!WOPDw<+a3}f^$M;y$|BGuuc>1(b z^Zpjl&m$7+1vIFCBZS^|tE%uz|u7v$(HdXVKg7SL49 z^S`~>uoeRc0cWXIH6=8AkDH6U-d%B8na!>cXI$^XJ@yDp@e$_Go2DB*dfQHGX>!&R zO~Mj|IE5?11nDb)ybQ05DjgE7ogJhvL0YL5t%2fUuV|Of;7_ z*rhZ&?Igs~%*n|eSn3hP)PV{1b4)&6k~n6K zict{bpUA^yPEblmOTv(6OsYk~{#OItSs*^Sv;1eIju)s&DYWKh?ue@%pe6Et*S;_H zJ_Znm-&`bdB86P^z?@+{#f&63$ST$AWvs)&o*KdlrM~)bfKyaY9d%n=fr(j%8}|R4 z^Z)N|4>-DeU2f%_MKU!1hq&*6)=gT+&D_MzLeR{`0`UNFvUBpXu=BETa%!-%3$k+y sa`Q6(?}gn^pEU6Q)4;*e+{V)T|GxnnQX%4M1pq)!T3M<}!Z_sr0J`?EssI20 diff --git a/api/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/api/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 9f8bc3a74e78d8f5b63165aaa15d233d446f880c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12029 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 Iol`;+0EQYKVE_OC diff --git a/api/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/api/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index d795e8a29318f7a09b35c1b51cda118c52c603f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37769 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 Iol`;+0EQYKVE_OC diff --git a/api/Android/app/src/main/res/values/colors.xml b/api/Android/app/src/main/res/values/colors.xml deleted file mode 100644 index 558d406..0000000 --- a/api/Android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #080B16 - #6D7BFF - #6D7BFF - diff --git a/api/Android/app/src/main/res/values/strings.xml b/api/Android/app/src/main/res/values/strings.xml deleted file mode 100644 index 516ec34..0000000 --- a/api/Android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - AI Notebook - diff --git a/api/Android/app/src/main/res/values/themes.xml b/api/Android/app/src/main/res/values/themes.xml deleted file mode 100644 index dd0959f..0000000 --- a/api/Android/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - diff --git a/api/Android/build.gradle.kts b/api/Android/build.gradle.kts deleted file mode 100644 index 0fe40d0..0000000 --- a/api/Android/build.gradle.kts +++ /dev/null @@ -1,6 +0,0 @@ -// Top-level build file -plugins { - id("com.android.application") version "8.5.2" apply false - id("org.jetbrains.kotlin.android") version "1.9.24" apply false - id("org.jetbrains.kotlin.plugin.serialization") version "1.9.24" apply false -} diff --git a/api/Android/gradle.properties b/api/Android/gradle.properties deleted file mode 100644 index f0a2e55..0000000 --- a/api/Android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -android.useAndroidX=true -kotlin.code.style=official -android.nonTransitiveRClass=true diff --git a/api/Android/gradle/wrapper/gradle-wrapper.jar b/api/Android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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