diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index e405e9a..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-*.iml
-.gradle
-/local.properties
-/.idea
-.DS_Store
-/build
-/captures
-.externalNativeBuild
-.cxx
-local.properties
-/tmp
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 7203af6..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2026 shuiyu
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/README.md b/README.md
index 4e0bb4f..c90db1e 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,7 @@
你好呀~这个仓库已经搬到更好用的地方啦。
-为了让代码管理更清爽、多平台同步更省心,我们把原先分散的镜像统一收拢到
-**Gitee** 与 **GitHub** 主仓维护,这里就只保留这张"迁移小纸条"咯。
+为了让代码管理更清爽、多平台同步更省心,我们把原先分散的镜像统一收拢到主仓维护,这里就只保留这张"迁移小纸条"咯。
📦 新家在这里:
- Gitee:https://gitee.com/shuiyu1123/mimo-studio-android
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
deleted file mode 100644
index 0e82ffd..0000000
--- a/app/build.gradle.kts
+++ /dev/null
@@ -1,66 +0,0 @@
-plugins {
- id("com.android.application")
- id("org.jetbrains.kotlin.android")
- id("org.jetbrains.kotlin.plugin.serialization") version "2.0.21"
-}
-
-android {
- namespace = "com.mimo.studio"
- compileSdk = 35
-
- defaultConfig {
- applicationId = "com.mimo.studio"
- minSdk = 26
- targetSdk = 35
- versionCode = 1
- versionName = "1.0.0"
- }
-
- buildTypes {
- release {
- isMinifyEnabled = true
- isShrinkResources = true
- proguardFiles(
- getDefaultProguardFile("proguard-android-optimize.txt"),
- "proguard-rules.pro"
- )
- }
- }
-
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
- }
-
- kotlinOptions {
- jvmTarget = "17"
- }
-
- buildFeatures {
- viewBinding = true
- }
-}
-
-dependencies {
- implementation("androidx.core:core-ktx:1.15.0")
- implementation("androidx.appcompat:appcompat:1.7.0")
- implementation("com.google.android.material:material:1.12.0")
- implementation("androidx.constraintlayout:constraintlayout:2.2.1")
- implementation("androidx.recyclerview:recyclerview:1.4.0")
- implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
- implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
- implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
-
- // Retrofit + OkHttp
- implementation("com.squareup.retrofit2:retrofit:2.11.0")
- implementation("com.squareup.retrofit2:converter-gson:2.11.0")
- implementation("com.squareup.okhttp3:okhttp:4.12.0")
- implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
- implementation("com.squareup.okhttp3:okhttp-sse:4.12.0")
-
- // Gson
- implementation("com.google.code.gson:gson:2.11.0")
-
- // Coroutines
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
-}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
deleted file mode 100644
index 65d549e..0000000
--- a/app/proguard-rules.pro
+++ /dev/null
@@ -1,5 +0,0 @@
--dontwarn okhttp3.**
--dontwarn okio.**
--dontwarn javax.annotation.**
--keep class com.mimo.studio.model.** { *; }
--keep class com.mimo.studio.api.** { *; }
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 7865050..0000000
--- a/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/java/com/mimo/studio/MainActivity.kt b/app/src/main/java/com/mimo/studio/MainActivity.kt
deleted file mode 100644
index e593924..0000000
--- a/app/src/main/java/com/mimo/studio/MainActivity.kt
+++ /dev/null
@@ -1,266 +0,0 @@
-package com.mimo.studio
-
-import android.content.Intent
-import android.os.Bundle
-import android.view.View
-import android.widget.*
-import androidx.appcompat.app.ActionBarDrawerToggle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.view.GravityCompat
-import androidx.drawerlayout.widget.DrawerLayout
-import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import com.google.android.material.appbar.MaterialToolbar
-import com.google.android.material.button.MaterialButton
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.google.android.material.navigation.NavigationView
-import com.google.android.material.switchmaterial.SwitchMaterial
-import com.google.android.material.textfield.TextInputEditText
-import com.mimo.studio.api.RetrofitClient
-import com.mimo.studio.model.ChatMessage
-import com.mimo.studio.model.ModelInfo
-import com.mimo.studio.ui.ChatAdapter
-import com.mimo.studio.ui.ModelsActivity
-import com.mimo.studio.viewmodel.MainViewModel
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
-
-class MainActivity : AppCompatActivity() {
-
- private lateinit var viewModel: MainViewModel
- private lateinit var chatAdapter: ChatAdapter
- private lateinit var drawerLayout: DrawerLayout
- private lateinit var recyclerChat: RecyclerView
- private lateinit var etMessage: EditText
- private lateinit var btnSend: ImageButton
- private lateinit var progressBar: ProgressBar
- private lateinit var tvStreaming: TextView
- private lateinit var spinnerModel: Spinner
-
- private var modelNames = listOf("xiaomi/mimo-v2-flash", "xiaomi/mimo-v2-pro", "xiaomi/mimo-v2-omni", "xiaomi/mimo-v2.5-pro", "xiaomi/mimo-v2.5")
- private var modelDisplayNames = listOf("MiMo-V2-Flash", "MiMo-V2-Pro", "MiMo-V2-Omni", "MiMo-V2.5-Pro", "MiMo-V2.5")
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
-
- viewModel = MainViewModel(application)
-
- initViews()
- setupDrawer()
- setupChat()
- setupModelSpinner()
- observeState()
-
- // Check if API key is configured
- if (viewModel.getApiKey().isBlank()) {
- showSettingsDialog()
- } else {
- viewModel.fetchModels()
- }
- }
-
- private fun initViews() {
- drawerLayout = findViewById(R.id.drawerLayout)
- recyclerChat = findViewById(R.id.recyclerChat)
- etMessage = findViewById(R.id.etMessage)
- btnSend = findViewById(R.id.btnSend)
- progressBar = findViewById(R.id.progressBar)
- tvStreaming = findViewById(R.id.tvStreaming)
- spinnerModel = findViewById(R.id.spinnerModel)
- }
-
- private fun setupDrawer() {
- val toolbar = findViewById(R.id.toolbar)
- val toggle = ActionBarDrawerToggle(
- this, drawerLayout, toolbar,
- R.string.app_name, R.string.app_name
- )
- drawerLayout.addDrawerListener(toggle)
- toggle.syncState()
-
- val navView = findViewById(R.id.navView)
- navView.setNavigationItemSelectedListener { item ->
- drawerLayout.closeDrawer(GravityCompat.START)
- when (item.itemId) {
- R.id.nav_new_chat -> viewModel.newConversation()
- R.id.nav_models -> {
- startActivity(Intent(this, ModelsActivity::class.java))
- }
- R.id.nav_settings -> showSettingsDialog()
- }
- true
- }
- }
-
- private fun setupChat() {
- chatAdapter = ChatAdapter()
- recyclerChat.layoutManager = LinearLayoutManager(this).apply {
- stackFromEnd = true
- }
- recyclerChat.adapter = chatAdapter
-
- btnSend.setOnClickListener {
- val text = etMessage.text.toString().trim()
- if (text.isNotEmpty()) {
- viewModel.sendMessage(text)
- etMessage.text.clear()
- }
- }
- }
-
- private fun setupModelSpinner() {
- val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, modelDisplayNames)
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
- spinnerModel.adapter = adapter
-
- spinnerModel.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
- override fun onItemSelected(parent: AdapterView<*>?, view: View?, pos: Int, id: Long) {
- viewModel.setSelectedModel(modelNames[pos])
- }
- override fun onNothingSelected(parent: AdapterView<*>?) {}
- }
- }
-
- private fun observeState() {
- lifecycleScope.launch {
- viewModel.currentConversation.collectLatest { conv ->
- if (conv != null) {
- chatAdapter.submitList(conv.messages.toList())
- if (conv.messages.isNotEmpty()) {
- recyclerChat.post {
- recyclerChat.smoothScrollToPosition(conv.messages.size - 1)
- }
- }
- }
- }
- }
-
- lifecycleScope.launch {
- viewModel.isLoading.collectLatest { loading ->
- progressBar.visibility = if (loading) View.VISIBLE else View.GONE
- btnSend.isEnabled = !loading
- }
- }
-
- lifecycleScope.launch {
- viewModel.isStreaming.collectLatest { streaming ->
- tvStreaming.visibility = if (streaming) View.VISIBLE else View.GONE
- }
- }
-
- lifecycleScope.launch {
- viewModel.streamingContent.collectLatest { content ->
- if (content.isNotEmpty()) {
- tvStreaming.text = content
- chatAdapter.updateStreamingContent(content)
- recyclerChat.post {
- recyclerChat.smoothScrollToPosition(chatAdapter.itemCount - 1)
- }
- }
- }
- }
-
- lifecycleScope.launch {
- viewModel.error.collectLatest { error ->
- error?.let {
- Toast.makeText(this@MainActivity, it, Toast.LENGTH_LONG).show()
- viewModel.clearError()
- }
- }
- }
-
- lifecycleScope.launch {
- viewModel.selectedModel.collectLatest { model ->
- val idx = modelNames.indexOf(model)
- if (idx >= 0 && spinnerModel.selectedItemPosition != idx) {
- spinnerModel.setSelection(idx)
- }
- }
- }
-
- lifecycleScope.launch {
- viewModel.models.collectLatest { models ->
- if (models.isNotEmpty()) {
- updateModelList(models)
- }
- }
- }
- }
-
- private fun updateModelList(models: List) {
- modelNames = models.map { it.id }
- modelDisplayNames = models.map { it.name.removePrefix("Xiaomi MiMo:").removePrefix("Xiaomi MiMo:") }
- val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, modelDisplayNames)
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
- spinnerModel.adapter = adapter
-
- val idx = modelNames.indexOf(viewModel.selectedModel.value)
- if (idx >= 0) spinnerModel.setSelection(idx)
- }
-
- private fun showSettingsDialog() {
- val dialogView = layoutInflater.inflate(R.layout.dialog_settings, null)
- val etApiKey = dialogView.findViewById(R.id.etApiKey)
- val etBaseUrl = dialogView.findViewById(R.id.etBaseUrl)
- val etSystemPrompt = dialogView.findViewById(R.id.etSystemPrompt)
- val seekTemp = dialogView.findViewById(R.id.seekTemperature)
- val tvTemp = dialogView.findViewById(R.id.tvTemperature)
- val etMaxTokens = dialogView.findViewById(R.id.etMaxTokens)
- val switchStreaming = dialogView.findViewById(R.id.switchStreaming)
-
- etApiKey.setText(viewModel.getApiKey())
- etBaseUrl.setText(viewModel.getBaseUrl())
- etSystemPrompt.setText(viewModel.currentConversation.value?.systemPrompt ?: "")
- seekTemp.progress = (viewModel.temperature.value * 100).toInt()
- tvTemp.text = String.format("%.2f", viewModel.temperature.value)
- etMaxTokens.setText(viewModel.maxTokens.value.toString())
- switchStreaming.isChecked = viewModel.useStreaming.value
-
- seekTemp.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
- override fun onProgressChanged(sb: SeekBar?, progress: Int, fromUser: Boolean) {
- tvTemp.text = String.format("%.2f", progress / 100f)
- }
- override fun onStartTrackingTouch(sb: SeekBar?) {}
- override fun onStopTrackingTouch(sb: SeekBar?) {}
- })
-
- MaterialAlertDialogBuilder(this)
- .setTitle("设置")
- .setView(dialogView)
- .setPositiveButton("保存") { _, _ ->
- val apiKey = etApiKey.text.toString().trim()
- val baseUrl = etBaseUrl.text.toString().trim().ifEmpty { "https://api.xiaomimimo.com/" }
- val systemPrompt = etSystemPrompt.text.toString().trim()
- val temp = seekTemp.progress / 100f
- val maxTokens = etMaxTokens.text.toString().trim().toIntOrNull() ?: 4096
-
- viewModel.saveSettings(apiKey, baseUrl)
- viewModel.setTemperature(temp)
- viewModel.setMaxTokens(maxTokens)
- viewModel.setStreaming(switchStreaming.isChecked)
-
- // Update system prompt on current conversation
- viewModel.currentConversation.value?.let { conv ->
- val updated = conv.copy(systemPrompt = systemPrompt)
- // Update through viewmodel would be cleaner, but this works
- }
-
- if (apiKey.isNotBlank()) {
- viewModel.fetchModels()
- }
- }
- .setNegativeButton("取消", null)
- .show()
- }
-
- @Deprecated("Use OnBackPressedCallback")
- override fun onBackPressed() {
- if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
- drawerLayout.closeDrawer(GravityCompat.START)
- } else {
- super.onBackPressed()
- }
- }
-}
diff --git a/app/src/main/java/com/mimo/studio/api/MimoApiService.kt b/app/src/main/java/com/mimo/studio/api/MimoApiService.kt
deleted file mode 100644
index 4d9fed8..0000000
--- a/app/src/main/java/com/mimo/studio/api/MimoApiService.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.mimo.studio.api
-
-import com.mimo.studio.model.*
-import okhttp3.ResponseBody
-import retrofit2.http.*
-
-interface MimoApiService {
-
- /** List all available models */
- @GET("v1/models")
- suspend fun listModels(): ModelsResponse
-
- /** Get a specific model */
- @GET("v1/models/{model_id}")
- suspend fun getModel(@Path("model_id") modelId: String): ModelInfo
-
- /** Create a chat completion */
- @POST("v1/chat/completions")
- suspend fun chatCompletions(@Body request: ChatRequest): ChatResponse
-
- /** Create a streaming chat completion */
- @POST("v1/chat/completions")
- @Streaming
- suspend fun chatCompletionsStream(@Body request: ChatRequest): ResponseBody
-
- /** Create a text completion */
- @POST("v1/completions")
- suspend fun completions(@Body request: CompletionRequest): CompletionResponse
-
- /** Create a streaming text completion */
- @POST("v1/completions")
- @Streaming
- suspend fun completionsStream(@Body request: CompletionRequest): ResponseBody
-}
diff --git a/app/src/main/java/com/mimo/studio/api/RetrofitClient.kt b/app/src/main/java/com/mimo/studio/api/RetrofitClient.kt
deleted file mode 100644
index 56a8c84..0000000
--- a/app/src/main/java/com/mimo/studio/api/RetrofitClient.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.mimo.studio.api
-
-import okhttp3.Interceptor
-import okhttp3.OkHttpClient
-import okhttp3.logging.HttpLoggingInterceptor
-import retrofit2.Retrofit
-import retrofit2.converter.gson.GsonConverterFactory
-import java.util.concurrent.TimeUnit
-
-object RetrofitClient {
-
- private const val BASE_URL = "https://api.xiaomimimo.com/"
-
- private var apiKey: String = ""
- private var baseUrl: String = BASE_URL
-
- fun configure(apiKey: String, baseUrl: String = BASE_URL) {
- this.apiKey = apiKey
- this.baseUrl = baseUrl
- }
-
- fun isConfigured(): Boolean = apiKey.isNotBlank()
-
- private val authInterceptor = Interceptor { chain ->
- val original = chain.request()
- val request = original.newBuilder()
- .header("Authorization", "Bearer $apiKey")
- .header("Content-Type", "application/json")
- .build()
- chain.proceed(request)
- }
-
- private val loggingInterceptor = HttpLoggingInterceptor().apply {
- level = HttpLoggingInterceptor.Level.BODY
- }
-
- private val okHttpClient = OkHttpClient.Builder()
- .addInterceptor(authInterceptor)
- .addInterceptor(loggingInterceptor)
- .connectTimeout(60, TimeUnit.SECONDS)
- .readTimeout(120, TimeUnit.SECONDS)
- .writeTimeout(60, TimeUnit.SECONDS)
- .build()
-
- private var retrofit: Retrofit? = null
- private var currentBaseUrl: String = ""
-
- val api: MimoApiService
- get() {
- if (retrofit == null || currentBaseUrl != baseUrl) {
- retrofit = Retrofit.Builder()
- .baseUrl(baseUrl)
- .client(okHttpClient)
- .addConverterFactory(GsonConverterFactory.create())
- .build()
- currentBaseUrl = baseUrl
- }
- return retrofit!!.create(MimoApiService::class.java)
- }
-}
diff --git a/app/src/main/java/com/mimo/studio/model/ApiModels.kt b/app/src/main/java/com/mimo/studio/model/ApiModels.kt
deleted file mode 100644
index 086ea7d..0000000
--- a/app/src/main/java/com/mimo/studio/model/ApiModels.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-package com.mimo.studio.model
-
-import com.google.gson.annotations.SerializedName
-
-// ===== Models API =====
-data class ModelsResponse(
- val data: List
-)
-
-data class ModelInfo(
- val id: String,
- val name: String,
- val description: String,
- @SerializedName("context_length") val contextLength: Int,
- @SerializedName("max_output_length") val maxOutputLength: Int,
- val architecture: Architecture?,
- val pricing: Any?, // Can be object or array
- @SerializedName("supported_parameters") val supportedParameters: List?
-)
-
-data class Architecture(
- val modality: String,
- @SerializedName("input_modalities") val inputModalities: List,
- @SerializedName("output_modalities") val outputModalities: List
-)
-
-// ===== Chat Completions API =====
-data class ChatRequest(
- val model: String,
- val messages: List,
- val stream: Boolean = false,
- @SerializedName("max_tokens") val maxTokens: Int? = null,
- val temperature: Float? = null,
- @SerializedName("top_p") val topP: Float? = null,
- val stop: List? = null,
- @SerializedName("frequency_penalty") val frequencyPenalty: Float? = null,
- @SerializedName("presence_penalty") val presencePenalty: Float? = null,
- @SerializedName("response_format") val responseFormat: ResponseFormat? = null,
- val reasoning: Boolean? = null,
- @SerializedName("include_reasoning") val includeReasoning: Boolean? = null
-)
-
-data class ResponseFormat(
- val type: String // "text" or "json_object"
-)
-
-data class ChatMessage(
- val role: String, // "system", "user", "assistant"
- val content: String
-)
-
-data class ChatResponse(
- val id: String?,
- val choices: List?,
- val usage: Usage?,
- val model: String?
-)
-
-data class Choice(
- val index: Int,
- val message: ChatMessage?,
- @SerializedName("finish_reason") val finishReason: String?,
- val delta: ChatMessage? // for streaming
-)
-
-data class Usage(
- @SerializedName("prompt_tokens") val promptTokens: Int,
- @SerializedName("completion_tokens") val completionTokens: Int,
- @SerializedName("total_tokens") val totalTokens: Int
-)
-
-// ===== Streaming =====
-data class StreamChunk(
- val id: String?,
- val choices: List?,
- val model: String?
-)
-
-data class StreamChoice(
- val index: Int,
- val delta: DeltaMessage?,
- @SerializedName("finish_reason") val finishReason: String?
-)
-
-data class DeltaMessage(
- val role: String?,
- val content: String?
-)
-
-// ===== Completions API =====
-data class CompletionRequest(
- val model: String,
- val prompt: String,
- val stream: Boolean = false,
- @SerializedName("max_tokens") val maxTokens: Int? = null,
- val temperature: Float? = null,
- @SerializedName("top_p") val topP: Float? = null,
- val stop: List? = null
-)
-
-data class CompletionResponse(
- val id: String?,
- val choices: List?,
- val usage: Usage?,
- val model: String?
-)
-
-data class CompletionChoice(
- val index: Int,
- val text: String?,
- @SerializedName("finish_reason") val finishReason: String?
-)
-
-// ===== Local chat state =====
-data class Conversation(
- val id: String = java.util.UUID.randomUUID().toString(),
- val title: String = "新对话",
- val messages: MutableList = mutableListOf(),
- val model: String = "xiaomi/mimo-v2-flash",
- val systemPrompt: String = "",
- val createdAt: Long = System.currentTimeMillis()
-)
diff --git a/app/src/main/java/com/mimo/studio/ui/ChatAdapter.kt b/app/src/main/java/com/mimo/studio/ui/ChatAdapter.kt
deleted file mode 100644
index 2283b26..0000000
--- a/app/src/main/java/com/mimo/studio/ui/ChatAdapter.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-package com.mimo.studio.ui
-
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.recyclerview.widget.DiffUtil
-import androidx.recyclerview.widget.ListAdapter
-import androidx.recyclerview.widget.RecyclerView
-import com.mimo.studio.R
-import com.mimo.studio.model.ChatMessage
-import java.text.SimpleDateFormat
-import java.util.*
-
-class ChatAdapter : ListAdapter(ChatDiffCallback()) {
-
- companion object {
- private const val TYPE_USER = 0
- private const val TYPE_ASSISTANT = 1
- private const val TYPE_SYSTEM = 2
- }
-
- private var timestamp = System.currentTimeMillis()
-
- override fun getItemViewType(position: Int): Int {
- return when (getItem(position).role) {
- "user" -> TYPE_USER
- "assistant" -> TYPE_ASSISTANT
- else -> TYPE_SYSTEM
- }
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- val inflater = LayoutInflater.from(parent.context)
- return when (viewType) {
- TYPE_USER -> UserViewHolder(inflater.inflate(R.layout.item_chat_user, parent, false))
- TYPE_ASSISTANT -> AssistantViewHolder(inflater.inflate(R.layout.item_chat_assistant, parent, false))
- else -> SystemViewHolder(inflater.inflate(R.layout.item_chat_assistant, parent, false))
- }
- }
-
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- val message = getItem(position)
- val timeStr = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(timestamp + position * 1000))
- when (holder) {
- is UserViewHolder -> holder.bind(message, timeStr)
- is AssistantViewHolder -> holder.bind(message, timeStr)
- is SystemViewHolder -> holder.bind(message, timeStr)
- }
- }
-
- fun updateStreamingContent(content: String) {
- // Update the last assistant message with streaming content
- // or add a temporary one
- val currentList = currentList.toMutableList()
- if (currentList.isNotEmpty() && currentList.last().role == "assistant" && currentList.last().content == "") {
- currentList[currentList.size - 1] = ChatMessage(role = "assistant", content = content)
- } else {
- currentList.add(ChatMessage(role = "assistant", content = content))
- }
- submitList(currentList)
- }
-
- class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- private val tvMessage: TextView = itemView.findViewById(R.id.tvMessage)
- private val tvTimestamp: TextView = itemView.findViewById(R.id.tvTimestamp)
-
- fun bind(message: ChatMessage, time: String) {
- tvMessage.text = message.content
- tvTimestamp.text = time
- }
- }
-
- class AssistantViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- private val tvMessage: TextView = itemView.findViewById(R.id.tvMessage)
- private val tvTimestamp: TextView = itemView.findViewById(R.id.tvTimestamp)
-
- fun bind(message: ChatMessage, time: String) {
- tvMessage.text = message.content
- tvTimestamp.text = time
- }
- }
-
- class SystemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- private val tvMessage: TextView = itemView.findViewById(R.id.tvMessage)
- private val tvTimestamp: TextView = itemView.findViewById(R.id.tvTimestamp)
-
- fun bind(message: ChatMessage, time: String) {
- tvMessage.text = "⚙️ ${message.content}"
- tvTimestamp.text = time
- }
- }
-
- class ChatDiffCallback : DiffUtil.ItemCallback() {
- override fun areItemsTheSame(oldItem: ChatMessage, newItem: ChatMessage): Boolean {
- return oldItem === newItem
- }
-
- override fun areContentsTheSame(oldItem: ChatMessage, newItem: ChatMessage): Boolean {
- return oldItem.role == newItem.role && oldItem.content == newItem.content
- }
- }
-}
diff --git a/app/src/main/java/com/mimo/studio/ui/ModelsActivity.kt b/app/src/main/java/com/mimo/studio/ui/ModelsActivity.kt
deleted file mode 100644
index 969fe27..0000000
--- a/app/src/main/java/com/mimo/studio/ui/ModelsActivity.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.mimo.studio.ui
-
-import android.os.Bundle
-import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
-import androidx.lifecycle.lifecycleScope
-import androidx.recyclerview.widget.LinearLayoutManager
-import com.google.android.material.appbar.MaterialToolbar
-import com.mimo.studio.R
-import com.mimo.studio.api.RetrofitClient
-import com.mimo.studio.model.ModelInfo
-import kotlinx.coroutines.launch
-
-class ModelsActivity : AppCompatActivity() {
-
- private lateinit var adapter: ModelsAdapter
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_models)
-
- val toolbar = findViewById(R.id.toolbar)
- toolbar.setNavigationOnClickListener { finish() }
-
- adapter = ModelsAdapter { model ->
- val intent = intent.putExtra("selected_model", model.id)
- setResult(RESULT_OK, intent)
- Toast.makeText(this, "已选择: ${model.name}", Toast.LENGTH_SHORT).show()
- finish()
- }
-
- val recycler = findViewById(R.id.recyclerModels)
- recycler.layoutManager = LinearLayoutManager(this)
- recycler.adapter = adapter
-
- val swipeRefresh = findViewById(R.id.swipeRefresh)
- swipeRefresh.setOnRefreshListener { fetchModels() }
-
- fetchModels()
- }
-
- private fun fetchModels() {
- val swipeRefresh = findViewById(R.id.swipeRefresh)
- lifecycleScope.launch {
- try {
- val response = RetrofitClient.api.listModels()
- adapter.submitList(response.data)
- } catch (e: Exception) {
- Toast.makeText(this@ModelsActivity, "加载失败: ${e.message}", Toast.LENGTH_LONG).show()
- } finally {
- swipeRefresh.isRefreshing = false
- }
- }
- }
-}
diff --git a/app/src/main/java/com/mimo/studio/ui/ModelsAdapter.kt b/app/src/main/java/com/mimo/studio/ui/ModelsAdapter.kt
deleted file mode 100644
index 258debf..0000000
--- a/app/src/main/java/com/mimo/studio/ui/ModelsAdapter.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.mimo.studio.ui
-
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.recyclerview.widget.RecyclerView
-import com.google.android.material.button.MaterialButton
-import com.mimo.studio.R
-import com.mimo.studio.model.ModelInfo
-
-class ModelsAdapter(
- private val onSelect: (ModelInfo) -> Unit
-) : RecyclerView.Adapter() {
-
- private var models: List = emptyList()
-
- fun submitList(list: List) {
- models = list
- notifyDataSetChanged()
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ModelViewHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.item_model, parent, false)
- return ModelViewHolder(view)
- }
-
- override fun onBindViewHolder(holder: ModelViewHolder, position: Int) {
- holder.bind(models[position])
- }
-
- override fun getItemCount() = models.size
-
- inner class ModelViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- private val tvName: TextView = itemView.findViewById(R.id.tvModelName)
- private val tvId: TextView = itemView.findViewById(R.id.tvModelId)
- private val tvModality: TextView = itemView.findViewById(R.id.tvModality)
- private val tvContext: TextView = itemView.findViewById(R.id.tvContext)
- private val tvDesc: TextView = itemView.findViewById(R.id.tvDescription)
- private val btnSelect: MaterialButton = itemView.findViewById(R.id.btnSelect)
-
- fun bind(model: ModelInfo) {
- tvName.text = model.name
- tvId.text = model.id
- tvModality.text = "模态: ${model.architecture?.modality ?: "text->text"}"
- tvContext.text = "上下文: ${formatTokens(model.contextLength)} tokens | 最大输出: ${formatTokens(model.maxOutputLength)} tokens"
- tvDesc.text = model.description
- btnSelect.setOnClickListener { onSelect(model) }
- }
-
- private fun formatTokens(tokens: Int): String {
- return when {
- tokens >= 1_000_000 -> "${tokens / 1_000_000}M"
- tokens >= 1_000 -> "${tokens / 1_000}K"
- else -> tokens.toString()
- }
- }
- }
-}
diff --git a/app/src/main/java/com/mimo/studio/viewmodel/MainViewModel.kt b/app/src/main/java/com/mimo/studio/viewmodel/MainViewModel.kt
deleted file mode 100644
index e42333f..0000000
--- a/app/src/main/java/com/mimo/studio/viewmodel/MainViewModel.kt
+++ /dev/null
@@ -1,303 +0,0 @@
-package com.mimo.studio.viewmodel
-
-import android.app.Application
-import android.content.Context
-import androidx.lifecycle.AndroidViewModel
-import androidx.lifecycle.viewModelScope
-import com.google.gson.Gson
-import com.google.gson.reflect.TypeToken
-import com.mimo.studio.api.RetrofitClient
-import com.mimo.studio.model.*
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.io.BufferedReader
-import java.io.InputStreamReader
-
-class MainViewModel(application: Application) : AndroidViewModel(application) {
-
- private val prefs = application.getSharedPreferences("mimo_prefs", Context.MODE_PRIVATE)
- private val gson = Gson()
-
- // State
- private val _models = MutableStateFlow>(emptyList())
- val models: StateFlow> = _models
-
- private val _conversations = MutableStateFlow>(emptyList())
- val conversations: StateFlow> = _conversations
-
- private val _currentConversation = MutableStateFlow(null)
- val currentConversation: StateFlow = _currentConversation
-
- private val _isLoading = MutableStateFlow(false)
- val isLoading: StateFlow = _isLoading
-
- private val _isStreaming = MutableStateFlow(false)
- val isStreaming: StateFlow = _isStreaming
-
- private val _streamingContent = MutableStateFlow("")
- val streamingContent: StateFlow = _streamingContent
-
- private val _error = MutableStateFlow(null)
- val error: StateFlow = _error
-
- private val _selectedModel = MutableStateFlow("xiaomi/mimo-v2-flash")
- val selectedModel: StateFlow = _selectedModel
-
- private val _useStreaming = MutableStateFlow(true)
- val useStreaming: StateFlow = _useStreaming
-
- private val _temperature = MutableStateFlow(1.0f)
- val temperature: StateFlow = _temperature
-
- private val _maxTokens = MutableStateFlow(4096)
- val maxTokens: StateFlow = _maxTokens
-
- init {
- loadSettings()
- loadConversations()
- if (conversations.value.isEmpty()) {
- newConversation()
- }
- }
-
- // ===== Settings =====
- fun getApiKey(): String = prefs.getString("api_key", "") ?: ""
- fun getBaseUrl(): String = prefs.getString("base_url", "https://api.xiaomimimo.com/") ?: "https://api.xiaomimimo.com/"
-
- fun saveSettings(apiKey: String, baseUrl: String) {
- prefs.edit()
- .putString("api_key", apiKey)
- .putString("base_url", baseUrl)
- .apply()
- RetrofitClient.configure(apiKey, baseUrl)
- }
-
- private fun loadSettings() {
- val key = getApiKey()
- val url = getBaseUrl()
- if (key.isNotBlank()) {
- RetrofitClient.configure(key, url)
- }
- _selectedModel.value = prefs.getString("selected_model", "xiaomi/mimo-v2-flash") ?: "xiaomi/mimo-v2-flash"
- _useStreaming.value = prefs.getBoolean("use_streaming", true)
- _temperature.value = prefs.getFloat("temperature", 1.0f)
- _maxTokens.value = prefs.getInt("max_tokens", 4096)
- }
-
- fun setSelectedModel(model: String) {
- _selectedModel.value = model
- prefs.edit().putString("selected_model", model).apply()
- }
-
- fun setStreaming(enabled: Boolean) {
- _useStreaming.value = enabled
- prefs.edit().putBoolean("use_streaming", enabled).apply()
- }
-
- fun setTemperature(temp: Float) {
- _temperature.value = temp
- prefs.edit().putFloat("temperature", temp).apply()
- }
-
- fun setMaxTokens(tokens: Int) {
- _maxTokens.value = tokens
- prefs.edit().putInt("max_tokens", tokens).apply()
- }
-
- // ===== Models =====
- fun fetchModels() {
- if (!RetrofitClient.isConfigured()) {
- _error.value = "请先配置 API Key"
- return
- }
- viewModelScope.launch {
- try {
- val response = withContext(Dispatchers.IO) { RetrofitClient.api.listModels() }
- _models.value = response.data
- _error.value = null
- } catch (e: Exception) {
- _error.value = "获取模型列表失败: ${e.message}"
- }
- }
- }
-
- // ===== Conversations =====
- fun newConversation() {
- val conv = Conversation(model = _selectedModel.value)
- val list = _conversations.value.toMutableList()
- list.add(0, conv)
- _conversations.value = list
- _currentConversation.value = conv
- saveConversations()
- }
-
- fun selectConversation(id: String) {
- _currentConversation.value = _conversations.value.find { it.id == id }
- }
-
- fun deleteConversation(id: String) {
- val list = _conversations.value.filter { it.id != id }.toMutableList()
- _conversations.value = list
- if (_currentConversation.value?.id == id) {
- _currentConversation.value = list.firstOrNull()
- }
- saveConversations()
- }
-
- private fun saveConversations() {
- val json = gson.toJson(_conversations.value)
- prefs.edit().putString("conversations", json).apply()
- }
-
- private fun loadConversations() {
- val json = prefs.getString("conversations", null)
- if (json != null) {
- val type = object : TypeToken>() {}.type
- try {
- val list: List = gson.fromJson(json, type)
- _conversations.value = list
- _currentConversation.value = list.firstOrNull()
- } catch (_: Exception) {}
- }
- }
-
- // ===== Chat =====
- fun sendMessage(content: String) {
- val conv = _currentConversation.value ?: return
- if (!RetrofitClient.isConfigured()) {
- _error.value = "请先在设置中配置 API Key"
- return
- }
-
- // Add user message
- conv.messages.add(ChatMessage(role = "user", content = content))
- if (conv.messages.size == 1 && conv.title == "新对话") {
- // Auto-title from first message
- val newConv = conv.copy(title = content.take(30) + if (content.length > 30) "..." else "")
- updateConversation(newConv)
- } else {
- _currentConversation.value = conv.copy()
- }
-
- if (_useStreaming.value) {
- sendStreamingMessage(conv)
- } else {
- sendNormalMessage(conv)
- }
- }
-
- private fun sendNormalMessage(conv: Conversation) {
- _isLoading.value = true
- _error.value = null
-
- viewModelScope.launch {
- try {
- val messages = buildMessages(conv)
- val request = ChatRequest(
- model = conv.model,
- messages = messages,
- temperature = _temperature.value,
- maxTokens = _maxTokens.value
- )
- val response = withContext(Dispatchers.IO) {
- RetrofitClient.api.chatCompletions(request)
- }
- val assistantMsg = response.choices?.firstOrNull()?.message
- if (assistantMsg != null) {
- conv.messages.add(assistantMsg)
- updateConversation(conv.copy())
- }
- _error.value = null
- } catch (e: Exception) {
- _error.value = "请求失败: ${e.message}"
- } finally {
- _isLoading.value = false
- }
- }
- }
-
- private fun sendStreamingMessage(conv: Conversation) {
- _isStreaming.value = true
- _streamingContent.value = ""
- _error.value = null
-
- viewModelScope.launch {
- try {
- val messages = buildMessages(conv)
- val request = ChatRequest(
- model = conv.model,
- messages = messages,
- stream = true,
- temperature = _temperature.value,
- maxTokens = _maxTokens.value
- )
- val responseBody = withContext(Dispatchers.IO) {
- RetrofitClient.api.chatCompletionsStream(request)
- }
-
- val reader = BufferedReader(InputStreamReader(responseBody.byteStream()))
- val fullContent = StringBuilder()
-
- try {
- var line: String?
- while (reader.readLine().also { line = it } != null) {
- val l = line ?: continue
- if (!l.startsWith("data: ")) continue
- val data = l.removePrefix("data: ").trim()
- if (data == "[DONE]") break
-
- try {
- val chunk = gson.fromJson(data, StreamChunk::class.java)
- val delta = chunk.choices?.firstOrNull()?.delta
- if (delta?.content != null) {
- fullContent.append(delta.content)
- _streamingContent.value = fullContent.toString()
- }
- } catch (_: Exception) {}
- }
- } finally {
- reader.close()
- responseBody.close()
- }
-
- if (fullContent.isNotEmpty()) {
- conv.messages.add(ChatMessage(role = "assistant", content = fullContent.toString()))
- updateConversation(conv.copy())
- }
- _streamingContent.value = ""
- } catch (e: Exception) {
- _error.value = "流式请求失败: ${e.message}"
- _streamingContent.value = ""
- } finally {
- _isStreaming.value = false
- }
- }
- }
-
- private fun buildMessages(conv: Conversation): List {
- val messages = mutableListOf()
- if (conv.systemPrompt.isNotBlank()) {
- messages.add(ChatMessage(role = "system", content = conv.systemPrompt))
- }
- messages.addAll(conv.messages)
- return messages
- }
-
- private fun updateConversation(conv: Conversation) {
- _currentConversation.value = conv
- val list = _conversations.value.toMutableList()
- val idx = list.indexOfFirst { it.id == conv.id }
- if (idx >= 0) {
- list[idx] = conv
- }
- _conversations.value = list
- saveConversations()
- }
-
- fun clearError() {
- _error.value = null
- }
-}
diff --git a/app/src/main/res/drawable/bg_assistant_bubble.xml b/app/src/main/res/drawable/bg_assistant_bubble.xml
deleted file mode 100644
index 49633a5..0000000
--- a/app/src/main/res/drawable/bg_assistant_bubble.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/drawable/bg_card.xml b/app/src/main/res/drawable/bg_card.xml
deleted file mode 100644
index 58b70d8..0000000
--- a/app/src/main/res/drawable/bg_card.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/bg_input.xml b/app/src/main/res/drawable/bg_input.xml
deleted file mode 100644
index 1885ad6..0000000
--- a/app/src/main/res/drawable/bg_input.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/bg_send_button.xml b/app/src/main/res/drawable/bg_send_button.xml
deleted file mode 100644
index 3c0ba1c..0000000
--- a/app/src/main/res/drawable/bg_send_button.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
diff --git a/app/src/main/res/drawable/bg_user_bubble.xml b/app/src/main/res/drawable/bg_user_bubble.xml
deleted file mode 100644
index 814953c..0000000
--- a/app/src/main/res/drawable/bg_user_bubble.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
deleted file mode 100644
index 86ac5ac..0000000
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index bb70daa..0000000
--- a/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,146 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/activity_models.xml b/app/src/main/res/layout/activity_models.xml
deleted file mode 100644
index 62f35c4..0000000
--- a/app/src/main/res/layout/activity_models.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/dialog_settings.xml b/app/src/main/res/layout/dialog_settings.xml
deleted file mode 100644
index e52cb50..0000000
--- a/app/src/main/res/layout/dialog_settings.xml
+++ /dev/null
@@ -1,122 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/item_chat_assistant.xml b/app/src/main/res/layout/item_chat_assistant.xml
deleted file mode 100644
index 422f0bf..0000000
--- a/app/src/main/res/layout/item_chat_assistant.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/item_chat_user.xml b/app/src/main/res/layout/item_chat_user.xml
deleted file mode 100644
index 85cdbee..0000000
--- a/app/src/main/res/layout/item_chat_user.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/item_model.xml b/app/src/main/res/layout/item_model.xml
deleted file mode 100644
index 80aea68..0000000
--- a/app/src/main/res/layout/item_model.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/nav_header.xml b/app/src/main/res/layout/nav_header.xml
deleted file mode 100644
index a0a2294..0000000
--- a/app/src/main/res/layout/nav_header.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
diff --git a/app/src/main/res/menu/nav_menu.xml b/app/src/main/res/menu/nav_menu.xml
deleted file mode 100644
index 0867dba..0000000
--- a/app/src/main/res/menu/nav_menu.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.xml b/app/src/main/res/mipmap-hdpi/ic_launcher.xml
deleted file mode 100644
index f9890cc..0000000
--- a/app/src/main/res/mipmap-hdpi/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.xml b/app/src/main/res/mipmap-xhdpi/ic_launcher.xml
deleted file mode 100644
index f9890cc..0000000
--- a/app/src/main/res/mipmap-xhdpi/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.xml b/app/src/main/res/mipmap-xxhdpi/ic_launcher.xml
deleted file mode 100644
index f9890cc..0000000
--- a/app/src/main/res/mipmap-xxhdpi/ic_launcher.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
deleted file mode 100644
index a0c588c..0000000
--- a/app/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FFFFFFFF
- #FF000000
- #FFF5F5F5
- #FF121212
- #FFE3F2FD
- #FFFFFFFF
- #FF212121
- #FF757575
- #FFE0E0E0
-
-
- #FF4A90D9
- #FF3A7BC8
- #FFFF6B35
- #FFF8F9FA
- #FFFFFFFF
- #FFE8F0FE
- #FFF1F3F4
- #FFF0F2F5
-
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
deleted file mode 100644
index 2ba148f..0000000
--- a/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- MiMo Studio
-
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
deleted file mode 100644
index fb4cb71..0000000
--- a/app/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/build.gradle.kts b/build.gradle.kts
deleted file mode 100644
index 2fb8337..0000000
--- a/build.gradle.kts
+++ /dev/null
@@ -1,5 +0,0 @@
-// Top-level build file
-plugins {
- id("com.android.application") version "8.7.3" apply false
- id("org.jetbrains.kotlin.android") version "2.0.21" apply false
-}
diff --git a/gradle.properties b/gradle.properties
deleted file mode 100644
index f0a2e55..0000000
--- a/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/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index a4b76b9..0000000
Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index e2847c8..0000000
--- a/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
-networkTimeout=10000
-validateDistributionUrl=true
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
deleted file mode 100755
index ceaef6e..0000000
--- a/gradlew
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/bin/sh
-
-#
-# Copyright © 2015-2021 the original authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-##############################################################################
-#
-# Gradle start up script for POSIX generated by Gradle.
-#
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-app_path=$0
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld -- "$app_path" )
- link=${ls#*' -> '}
- 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 -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || 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*)
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- ;;
- esac
- case $MAX_FD in
- '' | soft) :;;
- *)
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- ;;
- esac
-fi
-
-# Collect all arguments for the java command, stracks://am/LF://the current directory://
-# temporary://build://for://long://args://
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-fi
-
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and/or backslashes, so put them in
-# temporary variables so that the://shell://can://split://them://up (https://github.com/gradle/gradle/issues/25036)
-# * Put://all://options://into://a://single://quoted://word://so://they://are://not://split
-set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
- "$@"
-
-# Stop when "xeli" is available and://the://GRADLE_OPTS does not contain://any://-J flags
-if ! "$cygwin" && ! "$msys" && [ -n "$TERM" ] ; then
- :
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/settings.gradle.kts b/settings.gradle.kts
deleted file mode 100644
index 7cd214b..0000000
--- a/settings.gradle.kts
+++ /dev/null
@@ -1,16 +0,0 @@
-pluginManagement {
- repositories {
- google()
- mavenCentral()
- gradlePluginPortal()
- }
-}
-dependencyResolution {
- repositories {
- google()
- mavenCentral()
- }
-}
-
-rootProject.name = "MimoStudio"
-include(":app")