Add drawer menu with flat structure, unified panel styling, Room/SQLCipher setup
This commit is contained in:
parent
21505aae75
commit
7eadec669c
45 changed files with 1378 additions and 18 deletions
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'com.google.devtools.ksp' version '1.9.22-1.0.17'
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
@ -50,4 +51,10 @@ dependencies {
|
|||
implementation 'io.noties.markwon:ext-strikethrough:4.6.2'
|
||||
implementation 'io.noties.markwon:ext-tables:4.6.2'
|
||||
implementation 'io.noties.markwon:ext-tasklist:4.6.2'
|
||||
|
||||
implementation 'androidx.room:room-runtime:2.6.1'
|
||||
implementation 'androidx.room:room-ktx:2.6.1'
|
||||
ksp 'androidx.room:room-compiler:2.6.1'
|
||||
implementation 'net.zetetic:android-database-sqlcipher:4.5.4'
|
||||
implementation 'androidx.sqlite:sqlite-ktx:2.4.0'
|
||||
}
|
||||
64
app/src/main/java/com/mistral/chat/data/ChatDatabase.kt
Normal file
64
app/src/main/java/com/mistral/chat/data/ChatDatabase.kt
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import net.sqlcipher.database.SupportFactory
|
||||
|
||||
@Database(
|
||||
entities = [Profile::class, Session::class, MessageEntity::class, Setting::class],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class ChatDatabase : RoomDatabase() {
|
||||
abstract fun profileDao(): ProfileDao
|
||||
abstract fun sessionDao(): SessionDao
|
||||
abstract fun messageDao(): MessageDao
|
||||
abstract fun settingDao(): SettingDao
|
||||
|
||||
companion object {
|
||||
private const val DATABASE_NAME = "mistral_chat.db"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: ChatDatabase? = null
|
||||
|
||||
fun getInstance(context: Context): ChatDatabase {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDatabase(context: Context): ChatDatabase {
|
||||
val passphrase = getOrCreatePassphrase(context)
|
||||
val factory = SupportFactory(passphrase)
|
||||
|
||||
return Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
ChatDatabase::class.java,
|
||||
DATABASE_NAME
|
||||
)
|
||||
.openHelperFactory(factory)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getOrCreatePassphrase(context: Context): ByteArray {
|
||||
val prefs = context.getSharedPreferences("db_prefs", Context.MODE_PRIVATE)
|
||||
val existingKey = prefs.getString("db_key", null)
|
||||
|
||||
return if (existingKey != null) {
|
||||
existingKey.toByteArray(Charsets.UTF_8)
|
||||
} else {
|
||||
val newKey = generateSecureKey()
|
||||
prefs.edit().putString("db_key", newKey).apply()
|
||||
newKey.toByteArray(Charsets.UTF_8)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateSecureKey(): String {
|
||||
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*"
|
||||
return (1..32).map { chars.random() }.joinToString("")
|
||||
}
|
||||
}
|
||||
}
|
||||
31
app/src/main/java/com/mistral/chat/data/MessageDao.kt
Normal file
31
app/src/main/java/com/mistral/chat/data/MessageDao.kt
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface MessageDao {
|
||||
@Query("SELECT * FROM messages WHERE sessionId = :sessionId ORDER BY timestamp ASC")
|
||||
fun getMessagesBySession(sessionId: Long): Flow<List<MessageEntity>>
|
||||
|
||||
@Query("SELECT * FROM messages WHERE sessionId = :sessionId ORDER BY timestamp ASC")
|
||||
suspend fun getMessagesBySessionSync(sessionId: Long): List<MessageEntity>
|
||||
|
||||
@Query("SELECT COUNT(*) FROM messages WHERE sessionId = :sessionId")
|
||||
suspend fun getMessageCount(sessionId: Long): Int
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(message: MessageEntity): Long
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(messages: List<MessageEntity>)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(message: MessageEntity)
|
||||
|
||||
@Query("DELETE FROM messages WHERE sessionId = :sessionId")
|
||||
suspend fun deleteBySession(sessionId: Long)
|
||||
|
||||
@Query("DELETE FROM messages")
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
15
app/src/main/java/com/mistral/chat/data/Profile.kt
Normal file
15
app/src/main/java/com/mistral/chat/data/Profile.kt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "profiles")
|
||||
data class Profile(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Long = 0,
|
||||
val name: String,
|
||||
val bio: String = "",
|
||||
val preferences: String = "",
|
||||
val createdAt: Long = System.currentTimeMillis(),
|
||||
val updatedAt: Long = System.currentTimeMillis()
|
||||
)
|
||||
28
app/src/main/java/com/mistral/chat/data/ProfileDao.kt
Normal file
28
app/src/main/java/com/mistral/chat/data/ProfileDao.kt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface ProfileDao {
|
||||
@Query("SELECT * FROM profiles ORDER BY updatedAt DESC")
|
||||
fun getAllProfiles(): Flow<List<Profile>>
|
||||
|
||||
@Query("SELECT * FROM profiles WHERE id = :id")
|
||||
suspend fun getProfileById(id: Long): Profile?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(profile: Profile): Long
|
||||
|
||||
@Update
|
||||
suspend fun update(profile: Profile)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(profile: Profile)
|
||||
|
||||
@Query("DELETE FROM profiles WHERE id = :id")
|
||||
suspend fun deleteById(id: Long)
|
||||
|
||||
@Query("DELETE FROM profiles")
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
29
app/src/main/java/com/mistral/chat/data/Session.kt
Normal file
29
app/src/main/java/com/mistral/chat/data/Session.kt
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(
|
||||
tableName = "sessions",
|
||||
foreignKeys = [
|
||||
ForeignKey(
|
||||
entity = Profile::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["profileId"],
|
||||
onDelete = ForeignKey.SET_NULL
|
||||
)
|
||||
],
|
||||
indices = [Index("profileId")]
|
||||
)
|
||||
data class Session(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Long = 0,
|
||||
val profileId: Long? = null,
|
||||
val title: String = "Новая сессия",
|
||||
val isManuallyRenamed: Boolean = false,
|
||||
val isTitleGenerated: Boolean = false,
|
||||
val createdAt: Long = System.currentTimeMillis(),
|
||||
val updatedAt: Long = System.currentTimeMillis()
|
||||
)
|
||||
40
app/src/main/java/com/mistral/chat/data/SessionDao.kt
Normal file
40
app/src/main/java/com/mistral/chat/data/SessionDao.kt
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SessionDao {
|
||||
@Query("SELECT * FROM sessions ORDER BY updatedAt DESC")
|
||||
fun getAllSessions(): Flow<List<Session>>
|
||||
|
||||
@Query("SELECT * FROM sessions WHERE profileId = :profileId ORDER BY updatedAt DESC")
|
||||
fun getSessionsByProfile(profileId: Long): Flow<List<Session>>
|
||||
|
||||
@Query("SELECT * FROM sessions WHERE profileId IS NULL ORDER BY updatedAt DESC")
|
||||
fun getSessionsWithoutProfile(): Flow<List<Session>>
|
||||
|
||||
@Query("SELECT * FROM sessions WHERE id = :id")
|
||||
suspend fun getSessionById(id: Long): Session?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(session: Session): Long
|
||||
|
||||
@Update
|
||||
suspend fun update(session: Session)
|
||||
|
||||
@Delete
|
||||
suspend fun delete(session: Session)
|
||||
|
||||
@Query("DELETE FROM sessions WHERE id = :id")
|
||||
suspend fun deleteById(id: Long)
|
||||
|
||||
@Query("DELETE FROM sessions")
|
||||
suspend fun deleteAll()
|
||||
|
||||
@Query("UPDATE sessions SET updatedAt = :timestamp WHERE id = :sessionId")
|
||||
suspend fun updateTimestamp(sessionId: Long, timestamp: Long = System.currentTimeMillis())
|
||||
|
||||
@Query("UPDATE sessions SET title = :title, isManuallyRenamed = 1 WHERE id = :sessionId")
|
||||
suspend fun updateTitle(sessionId: Long, title: String)
|
||||
}
|
||||
11
app/src/main/java/com/mistral/chat/data/Setting.kt
Normal file
11
app/src/main/java/com/mistral/chat/data/Setting.kt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "settings")
|
||||
data class Setting(
|
||||
@PrimaryKey
|
||||
val key: String,
|
||||
val value: String
|
||||
)
|
||||
22
app/src/main/java/com/mistral/chat/data/SettingDao.kt
Normal file
22
app/src/main/java/com/mistral/chat/data/SettingDao.kt
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package com.mistral.chat.data
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SettingDao {
|
||||
@Query("SELECT * FROM settings WHERE `key` = :key")
|
||||
suspend fun getSetting(key: String): Setting?
|
||||
|
||||
@Query("SELECT value FROM settings WHERE `key` = :key")
|
||||
suspend fun getValue(key: String): String?
|
||||
|
||||
@Query("SELECT value FROM settings WHERE `key` = :key")
|
||||
fun getValueFlow(key: String): Flow<String?>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(setting: Setting)
|
||||
|
||||
@Query("DELETE FROM settings WHERE `key` = :key")
|
||||
suspend fun delete(key: String)
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package com.mistral.chat.ui
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mistral.chat.R
|
||||
|
||||
class DrawerSubmenuAdapter(
|
||||
private val items: List<DrawerMenuItem>,
|
||||
private val onItemClick: (DrawerMenuItem) -> Unit
|
||||
) : RecyclerView.Adapter<DrawerSubmenuAdapter.ViewHolder>() {
|
||||
|
||||
data class DrawerMenuItem(
|
||||
val id: String,
|
||||
val title: String,
|
||||
val icon: Int? = null,
|
||||
val isSelected: Boolean = false
|
||||
)
|
||||
|
||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val icon: ImageView = itemView.findViewById(R.id.itemIcon)
|
||||
val title: TextView = itemView.findViewById(R.id.itemTitle)
|
||||
val check: ImageView = itemView.findViewById(R.id.itemCheck)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_drawer, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
holder.title.text = item.title
|
||||
|
||||
if (item.icon != null) {
|
||||
holder.icon.setImageResource(item.icon)
|
||||
holder.icon.visibility = View.VISIBLE
|
||||
} else {
|
||||
holder.icon.visibility = View.GONE
|
||||
}
|
||||
|
||||
holder.check.visibility = if (item.isSelected) View.VISIBLE else View.GONE
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
onItemClick(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = items.size
|
||||
}
|
||||
|
|
@ -90,6 +90,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
private const val KEY_NEW_SESSION_ON_START = "new_session_on_start"
|
||||
private const val KEY_LAST_PROFILE_ID = "last_profile_id"
|
||||
private const val KEY_SELECTED_MODEL = "selected_model"
|
||||
private const val KEY_THEME_MODE = "theme_mode"
|
||||
private const val MAX_PROFILES = 10
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +194,10 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
R.id.action_clear_all -> {
|
||||
showClearAllDialog()
|
||||
}
|
||||
R.id.action_settings -> {
|
||||
R.id.action_appearance -> {
|
||||
showThemeDialog()
|
||||
}
|
||||
R.id.action_session -> {
|
||||
showSettingsDialog()
|
||||
}
|
||||
R.id.action_about -> {
|
||||
|
|
@ -298,6 +302,31 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
.show()
|
||||
}
|
||||
|
||||
private fun showThemeDialog() {
|
||||
val currentTheme = prefs.getInt(KEY_THEME_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
val options = arrayOf("Системная", "Светлая", "Тёмная")
|
||||
val selectedIndex = when (currentTheme) {
|
||||
AppCompatDelegate.MODE_NIGHT_NO -> 1
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> 2
|
||||
else -> 0
|
||||
}
|
||||
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.appearance_settings)
|
||||
.setSingleChoiceItems(options, selectedIndex) { dialog, which ->
|
||||
val mode = when (which) {
|
||||
1 -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
2 -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
}
|
||||
prefs.edit().putInt(KEY_THEME_MODE, mode).apply()
|
||||
AppCompatDelegate.setDefaultNightMode(mode)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showAboutDialog() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.about)
|
||||
|
|
@ -707,22 +736,16 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
}
|
||||
|
||||
private fun addMessage(message: Message) {
|
||||
val isAssistantMessage = !message.isUser
|
||||
val newPosition = messages.size - 1
|
||||
|
||||
messages.add(message)
|
||||
adapter.notifyItemInserted(newPosition)
|
||||
|
||||
// Scroll to beginning of assistant messages so user sees the sender name first
|
||||
if (isAssistantMessage) {
|
||||
recyclerView.post {
|
||||
recyclerView.scrollToPosition(0)
|
||||
// Then scroll to show the new message from beginning
|
||||
val scrollAmount = (recyclerView.computeVerticalScrollExtent() - 200).coerceAtLeast(0)
|
||||
recyclerView.post {
|
||||
recyclerView.scrollBy(0, scrollAmount)
|
||||
}
|
||||
}
|
||||
// Scroll to show new AI response
|
||||
if (!message.isUser) {
|
||||
recyclerView.postDelayed({
|
||||
recyclerView.scrollToPosition(newPosition)
|
||||
}, 150)
|
||||
}
|
||||
|
||||
val sessionId = currentSessionId
|
||||
|
|
@ -738,10 +761,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
database.sessionDao().updateTimestamp(sessionId)
|
||||
}
|
||||
}
|
||||
|
||||
recyclerView.postDelayed({
|
||||
recyclerView.scrollToPosition(messages.size - 1)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
private fun saveMessageToDatabase(sessionId: Long?, content: String, isUser: Boolean, senderName: String?) {
|
||||
|
|
|
|||
55
app/src/main/java/com/mistral/chat/ui/ProfilesAdapter.kt
Normal file
55
app/src/main/java/com/mistral/chat/ui/ProfilesAdapter.kt
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package com.mistral.chat.ui
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mistral.chat.R
|
||||
import com.mistral.chat.data.Profile
|
||||
|
||||
class ProfilesAdapter(
|
||||
private val profiles: List<Profile>,
|
||||
private val onProfileClick: (Profile) -> Unit,
|
||||
private val onProfileLongClick: (Profile) -> Unit,
|
||||
private val getSelectedProfileId: () -> Long?
|
||||
) : RecyclerView.Adapter<ProfilesAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val icon: ImageView = view.findViewById(R.id.profileIcon)
|
||||
val name: TextView = view.findViewById(R.id.profileName)
|
||||
val checkmark: ImageView = view.findViewById(R.id.profileCheckmark)
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.item_profile, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val profile = profiles[position]
|
||||
val selectedId = getSelectedProfileId()
|
||||
|
||||
holder.name.text = if (profile.name.length > 12) {
|
||||
profile.name.take(12) + "..."
|
||||
} else {
|
||||
profile.name
|
||||
}
|
||||
holder.name.alpha = if (profile.id == selectedId) 1.0f else 0.7f
|
||||
holder.checkmark.visibility = if (profile.id == selectedId) View.VISIBLE else View.GONE
|
||||
|
||||
holder.itemView.setOnClickListener { onProfileClick(profile) }
|
||||
holder.itemView.setOnLongClickListener {
|
||||
onProfileLongClick(profile)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = profiles.size
|
||||
}
|
||||
45
app/src/main/java/com/mistral/chat/ui/SessionsAdapter.kt
Normal file
45
app/src/main/java/com/mistral/chat/ui/SessionsAdapter.kt
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package com.mistral.chat.ui
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mistral.chat.R
|
||||
import com.mistral.chat.data.Session
|
||||
|
||||
class SessionsAdapter(
|
||||
private val sessions: List<Session>,
|
||||
private val getCurrentSessionId: () -> Long?,
|
||||
private val onSessionClick: (Session) -> Unit,
|
||||
private val onSessionLongClick: (Session) -> Unit
|
||||
) : RecyclerView.Adapter<SessionsAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val title: TextView = view.findViewById(R.id.sessionTitle)
|
||||
val checkmark: ImageView = view.findViewById(R.id.sessionCheckmark)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.item_session, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val session = sessions[position]
|
||||
val currentId = getCurrentSessionId()
|
||||
holder.title.text = session.title
|
||||
holder.title.alpha = if (session.id == currentId) 1.0f else 0.7f
|
||||
holder.checkmark.visibility = if (session.id == currentId) View.VISIBLE else View.GONE
|
||||
|
||||
holder.itemView.setOnClickListener { onSessionClick(session) }
|
||||
holder.itemView.setOnLongClickListener {
|
||||
onSessionLongClick(session)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = sessions.size
|
||||
}
|
||||
10
app/src/main/res/drawable/ic_add.xml
Normal file
10
app/src/main/res/drawable/ic_add.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_arrow_back.xml
Normal file
10
app/src/main/res/drawable/ic_arrow_back.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorOnSurface">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_check.xml
Normal file
10
app/src/main/res/drawable/ic_check.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm-2,15l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_delete.xml
Normal file
10
app/src/main/res/drawable/ic_delete.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
|
||||
</vector>
|
||||
11
app/src/main/res/drawable/ic_edit.xml
Normal file
11
app/src/main/res/drawable/ic_edit.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorOnSurface">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_info.xml
Normal file
10
app/src/main/res/drawable/ic_info.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-6h2v6zm0,-8h-2V7h2v2z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_key.xml
Normal file
10
app/src/main/res/drawable/ic_key.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M12.65,10C11.83,7.67 9.61,6 7,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6c2.61,0 4.83,-1.67 5.65,-4H17v4h4v-4h2v-4H12.65zM7,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_menu_hamburger.xml
Normal file
10
app/src/main/res/drawable/ic_menu_hamburger.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M3,18h18v-2H3v2zm0,-5h18v-2H3v2zm0,-7v2h18V6H3z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_person.xml
Normal file
10
app/src/main/res/drawable/ic_person.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zm0,2c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_settings.xml
Normal file
10
app/src/main/res/drawable/ic_settings.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?attr/colorOnSurface"
|
||||
android:pathData="M19.14,12.94c0.04,-0.31 0.06,-0.63 0.06,-0.94c0,-0.31 -0.02,-0.63 -0.06,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.37 4.8,11.69 4.8,12s0.02,0.63 0.06,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
|
||||
</vector>
|
||||
22
app/src/main/res/layout/dialog_clear_all.xml
Normal file
22
app/src/main/res/layout/dialog_clear_all.xml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/clear_all_confirm"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/deleteProfilesCheckbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/clear_all_delete_profiles"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
55
app/src/main/res/layout/dialog_profile_edit.xml
Normal file
55
app/src/main/res/layout/dialog_profile_edit.xml
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/profile_name"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/profileNameInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPersonName" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/profile_bio"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/profileBioInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="3" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/profile_preferences"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/profilePreferencesInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="2" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
22
app/src/main/res/layout/dialog_profiles.xml
Normal file
22
app/src/main/res/layout/dialog_profiles.xml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/profilesList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxHeight="300dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/addProfileButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/new_profile"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
</LinearLayout>
|
||||
73
app/src/main/res/layout/drawer_main_menu.xml
Normal file
73
app/src/main/res/layout/drawer_main_menu.xml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnProfiles"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/profiles"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:icon="@drawable/ic_person"
|
||||
app:iconGravity="start"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnSettings"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:icon="@drawable/ic_settings"
|
||||
app:iconGravity="start"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnClearHistory"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/clear_history"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:icon="@drawable/ic_delete"
|
||||
app:iconGravity="start"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnApiKey"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/api_key"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:icon="@drawable/ic_key"
|
||||
app:iconGravity="start"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnAbout"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/about"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:icon="@drawable/ic_info"
|
||||
app:iconGravity="start"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
</LinearLayout>
|
||||
88
app/src/main/res/layout/drawer_profile_edit.xml
Normal file
88
app/src/main/res/layout/drawer_profile_edit.xml
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/profile_name"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/nameInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPersonName" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/profile_bio"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/bioInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="3" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/profile_preferences"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/preferencesInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="2" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/saveButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/save" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/deleteButton"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/delete"
|
||||
android:textColor="?attr/colorError"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
45
app/src/main/res/layout/drawer_settings_menu.xml
Normal file
45
app/src/main/res/layout/drawer_settings_menu.xml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnBack"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/back"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="?attr/colorOutline" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnAppearance"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/appearance_settings"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnSession"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/session_settings"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
50
app/src/main/res/layout/drawer_submenu.xml
Normal file
50
app/src/main/res/layout/drawer_submenu.xml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/drawerSubmenuContainer"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:background="?attr/colorSurface"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/backButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_arrow_back"
|
||||
android:contentDescription="@string/back" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/submenuTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/colorOutlineVariant" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/submenuRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
36
app/src/main/res/layout/item_drawer.xml
Normal file
36
app/src/main/res/layout/item_drawer.xml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="16dp"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemIcon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_person"
|
||||
app:tint="?attr/colorOnSurface"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemCheck"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_check"
|
||||
android:visibility="gone"
|
||||
app:tint="?attr/colorPrimary"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto" />
|
||||
|
||||
</LinearLayout>
|
||||
34
app/src/main/res/layout/item_profile.xml
Normal file
34
app/src/main/res/layout/item_profile.xml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/profileIcon"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:src="@drawable/ic_person"
|
||||
android:contentDescription="@string/profile" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/profileName"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="12dp"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/profileCheckmark"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/ic_check"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/selected" />
|
||||
|
||||
</LinearLayout>
|
||||
28
app/src/main/res/layout/item_session.xml
Normal file
28
app/src/main/res/layout/item_session.xml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="8dp"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sessionTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sessionCheckmark"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/ic_check"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/save" />
|
||||
|
||||
</LinearLayout>
|
||||
17
app/src/main/res/layout/nav_header.xml
Normal file
17
app/src/main/res/layout/nav_header.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp"
|
||||
android:background="?attr/colorPrimaryContainer">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/colorOnPrimaryContainer" />
|
||||
|
||||
</LinearLayout>
|
||||
56
app/src/main/res/layout/panel_right.xml
Normal file
56
app/src/main/res/layout/panel_right.xml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/panelRightContent"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="@string/profiles"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/colorOnSurfaceVariant" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/profilesRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="8dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?attr/colorOutlineVariant" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="@string/sessions"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/colorOnSurfaceVariant" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/sessionsRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingHorizontal="8dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/newSessionButton"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/new_session"
|
||||
app:icon="@drawable/ic_add" />
|
||||
|
||||
</LinearLayout>
|
||||
30
app/src/main/res/layout/screen_api_key.xml
Normal file
30
app/src/main/res/layout/screen_api_key.xml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/currentKeyText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/changeKeyButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Изменить ключ" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
31
app/src/main/res/layout/screen_appearance.xml
Normal file
31
app/src/main/res/layout/screen_appearance.xml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/themeSystemButton"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/system_theme" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/themeLightButton"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/light_theme" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/themeDarkButton"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/dark_theme" />
|
||||
|
||||
</LinearLayout>
|
||||
47
app/src/main/res/layout/screen_base.xml
Normal file
47
app/src/main/res/layout/screen_base.xml
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/screenBaseContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/colorSurface">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/screenBackButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_arrow_back"
|
||||
android:contentDescription="@string/back" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/screenTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/colorOnSurface" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/colorOutlineVariant" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/screenContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
32
app/src/main/res/layout/screen_clear_history.xml
Normal file
32
app/src/main/res/layout/screen_clear_history.xml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/clear_history_message"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/clearSessionsButton"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Удалить сессии" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/clearAllButton"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Удалить всё (включая профили)"
|
||||
android:textColor="?attr/colorError" />
|
||||
|
||||
</LinearLayout>
|
||||
79
app/src/main/res/layout/screen_profile_edit.xml
Normal file
79
app/src/main/res/layout/screen_profile_edit.xml
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/profile_name"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/profileNameInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPersonName" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/profile_bio"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/profileBioInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="3" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:hint="@string/profile_preferences"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/profilePreferencesInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="2" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/saveProfileButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/save" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/deleteProfileButton"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/delete"
|
||||
android:textColor="?attr/colorError"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
25
app/src/main/res/layout/screen_profiles.xml
Normal file
25
app/src/main/res/layout/screen_profiles.xml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/profilesList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/addProfileButton"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/new_profile"
|
||||
app:icon="@drawable/ic_add" />
|
||||
|
||||
</LinearLayout>
|
||||
23
app/src/main/res/layout/screen_session.xml
Normal file
23
app/src/main/res/layout/screen_session.xml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/sessionLastButton"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/open_last_session" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/sessionNewButton"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/start_new_session" />
|
||||
|
||||
</LinearLayout>
|
||||
35
app/src/main/res/menu/drawer_menu.xml
Normal file
35
app/src/main/res/menu/drawer_menu.xml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_profiles"
|
||||
android:title="@string/manage_profiles"
|
||||
android:icon="@drawable/ic_person" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_appearance"
|
||||
android:title="@string/appearance_settings"
|
||||
android:icon="@drawable/ic_settings" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_session"
|
||||
android:title="@string/session_settings"
|
||||
android:icon="@drawable/ic_settings" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_clear_all"
|
||||
android:title="@string/clear_history"
|
||||
android:icon="@drawable/ic_delete" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_api_key"
|
||||
android:title="@string/api_key"
|
||||
android:icon="@drawable/ic_key" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_about"
|
||||
android:title="@string/about"
|
||||
android:icon="@drawable/ic_info" />
|
||||
|
||||
</menu>
|
||||
|
|
@ -42,11 +42,21 @@
|
|||
<string name="no_sessions">Нет сессий</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="profiles">Профили</string>
|
||||
<string name="manage_profiles">Управление профилями</string>
|
||||
<string name="profiles_uppercase">ПРОФИЛИ</string>
|
||||
<string name="new_profile">Новый профиль</string>
|
||||
<string name="manage_profiles">Управление профилями</string>
|
||||
<string name="edit">Редактировать</string>
|
||||
<string name="selected">Выбрано</string>
|
||||
<string name="clear_all_delete_profiles">Удалить все профили</string>
|
||||
<string name="profile_info">Профиль: %s</string>
|
||||
<string name="appearance_settings">Внешний вид</string>
|
||||
<string name="session_settings">Сессия при запуске</string>
|
||||
<string name="clear_history">Очистить историю</string>
|
||||
<string name="clear_history_message">Удалить все сессии и сообщения?</string>
|
||||
<string name="open_last_session">Открывать последнюю сессию</string>
|
||||
<string name="start_new_session">Начинать новую сессию</string>
|
||||
<string name="light_theme">Светлая</string>
|
||||
<string name="dark_theme">Тёмная</string>
|
||||
<string name="back">Назад</string>
|
||||
<string name="system_theme">Системная</string>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue