diff --git a/app/build.gradle b/app/build.gradle
index 54e4eac..09efae7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -26,10 +26,16 @@ android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
+
+
}
kotlinOptions {
jvmTarget = '1.8'
}
+
+ viewBinding {
+ enabled = true
+ }
}
dependencies {
@@ -38,7 +44,11 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- testImplementation 'junit:junit:4.13.2'
+ //implementation 'com.github.telegram:telegram-design-system:7.8.1'
+ implementation 'com.github.bumptech.glide:glide:4.15.1'
+ //kapt 'com.github.bumptech.glide:compiler:4.15.1' // For annotation processing if required testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
-}
\ No newline at end of file
+}
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ef75335..04f2779 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,10 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/otus/gpb/recyclerview/Chat.kt b/app/src/main/java/otus/gpb/recyclerview/Chat.kt
new file mode 100644
index 0000000..1c3fa89
--- /dev/null
+++ b/app/src/main/java/otus/gpb/recyclerview/Chat.kt
@@ -0,0 +1,138 @@
+package otus.gpb.recyclerview
+
+interface Chat {
+ override fun equals(other: Any?): Boolean
+}
+
+// Parent interface
+interface DataChat: Chat {
+ val id: Int
+ val lastUserName: String
+ val lastMessage: String
+ val time: String
+ val isVerified: Boolean
+ val isScam: Boolean
+ val unreadMessageCount: Int
+ val avatarUrl: String?
+ val lastAnswererUrl: String?
+ val isPinned: Boolean
+ var isMute: Boolean
+ var isSpeeching: Boolean
+ var isTyping: Boolean
+ var isUnreadedAnswerToYou: Boolean
+ var isAnswered: Boolean
+ var isOpponnentReaded: Boolean
+ var isLock: Boolean
+
+}
+
+// Child class for group chat
+data class GroupChat(
+ override val id: Int,
+ val title: String,
+ override val lastUserName: String,
+ override val lastMessage: String,
+ override val time: String,
+ override val isVerified: Boolean = true,
+ override val isScam: Boolean = false,
+ override val unreadMessageCount: Int = 0,
+ override val avatarUrl: String? = null,
+ override val lastAnswererUrl: String? = null,
+ override val isPinned: Boolean = false,
+ override var isMute: Boolean = false,
+ override var isSpeeching: Boolean = false,
+ override var isTyping: Boolean = false,
+ override var isUnreadedAnswerToYou: Boolean = false,
+ override var isAnswered: Boolean = false,
+ override var isOpponnentReaded: Boolean = false,
+ override var isLock: Boolean = false
+
+
+) : DataChat {
+
+ // Custom equals implementation for GroupChat
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other !is GroupChat) return false
+ return id == other.id &&
+ lastUserName == other.lastUserName &&
+ lastMessage == other.lastMessage &&
+ time == other.time &&
+ isVerified == other.isVerified &&
+ isScam == other.isScam &&
+ unreadMessageCount == other.unreadMessageCount &&
+ avatarUrl == other.avatarUrl &&
+ lastAnswererUrl == other.lastAnswererUrl &&
+ isPinned == other.isPinned &&
+ isMute == other.isMute &&
+ isSpeeching == other.isSpeeching &&
+ isTyping == other.isTyping &&
+ isUnreadedAnswerToYou == other.isUnreadedAnswerToYou &&
+ isAnswered == other.isAnswered &&
+ isOpponnentReaded == other.isOpponnentReaded &&
+ isLock == other.isLock
+ }
+
+ override fun hashCode(): Int {
+ return id.hashCode()
+ }
+}
+
+// Child class for user chat
+data class UserChat(
+ override val id: Int,
+ override val lastUserName: String,
+ override val lastMessage: String,
+ override val time: String,
+ override val isVerified: Boolean = true,
+ override val isScam: Boolean = false,
+ override val unreadMessageCount: Int = 0,
+ override val avatarUrl: String? = null,
+ override val lastAnswererUrl: String? = null,
+ override val isPinned: Boolean = false,
+ override var isMute: Boolean = false,
+ override var isSpeeching: Boolean = false,
+ override var isTyping: Boolean = false,
+ override var isUnreadedAnswerToYou: Boolean = false,
+ override var isAnswered: Boolean = false,
+ override var isOpponnentReaded: Boolean = false,
+ override var isLock: Boolean = false
+) : DataChat {
+
+ // Custom equals implementation for UserChat
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other !is UserChat) return false
+ return id == other.id &&
+ lastUserName == other.lastUserName &&
+ lastMessage == other.lastMessage &&
+ time == other.time &&
+ isVerified == other.isVerified &&
+ isScam == other.isScam &&
+ unreadMessageCount == other.unreadMessageCount &&
+ avatarUrl == other.avatarUrl &&
+ lastAnswererUrl == other.lastAnswererUrl &&
+ isPinned == other.isPinned &&
+ isMute == other.isMute &&
+ isSpeeching == other.isSpeeching &&
+ isTyping == other.isTyping &&
+ isUnreadedAnswerToYou == other.isUnreadedAnswerToYou &&
+ isAnswered == other.isAnswered &&
+ isOpponnentReaded == other.isOpponnentReaded &&
+ isLock == other.isLock
+ }
+
+ override fun hashCode(): Int {
+ return id.hashCode()
+ }
+}
+
+object ChatLoading : Chat {
+ override fun equals(other: Any?): Boolean {
+ return this === other
+ }
+
+ override fun hashCode(): Int {
+ return javaClass.hashCode()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/otus/gpb/recyclerview/ChatAdapter.kt b/app/src/main/java/otus/gpb/recyclerview/ChatAdapter.kt
new file mode 100644
index 0000000..a63266f
--- /dev/null
+++ b/app/src/main/java/otus/gpb/recyclerview/ChatAdapter.kt
@@ -0,0 +1,186 @@
+package otus.gpb.recyclerview
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.resource.bitmap.CircleCrop
+import otus.gpb.recyclerview.databinding.ItemChatBinding
+
+
+class ChatAdapter(
+ private val context: Context,
+ private val onArchiveChat: (Chat) -> Unit // Новый callback для архивирования
+) : ListAdapter(ChatDiffCallback()) {
+
+ companion object {
+ private const val VIEW_TYPE_DATA = 0
+ private const val VIEW_TYPE_LOADING = 1
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return when (getItem(position)) {
+ is DataChat -> VIEW_TYPE_DATA
+ is ChatLoading -> VIEW_TYPE_LOADING
+ else -> throw IllegalArgumentException(context.getString(R.string.invalid_view_type))
+ }
+ }
+
+ inner class ChatViewHolder(private val binding: ItemChatBinding) :
+ ViewHolder(binding.root) {
+
+ fun bind(chat: Chat) {
+ if (chat is DataChat) {
+ // Установка данных в зависимости от типа чата
+ when (chat) {
+ is GroupChat -> {
+ binding.chatTopic.text = chat.title
+ binding.chatLastUser.text = chat.lastUserName
+ binding.chatLastUser.visibility = View.VISIBLE
+ }
+
+ is UserChat -> {
+ binding.chatTopic.text = chat.lastUserName
+ binding.chatLastUser.visibility = View.GONE
+ }
+ }
+
+ binding.chatLastMessage.text = chat.lastMessage
+ binding.chatTime.text = chat.time
+
+ // Отображение иконок статусов
+ binding.speechingStatusIcon.visibility =
+ if (chat.isSpeeching) View.VISIBLE else View.GONE
+ binding.muteChannelIcon.visibility = if (chat.isMute) View.VISIBLE else View.GONE
+
+ binding.lockIcon.visibility = if (chat.isLock) View.VISIBLE else View.GONE
+ binding.scamIcon.visibility = if (chat.isScam) View.VISIBLE else View.GONE
+
+ binding.verifiedIcon.visibility = if (chat.isVerified) View.VISIBLE else View.GONE
+
+ binding.unreadCount.visibility =
+ if (chat.unreadMessageCount > 0) View.VISIBLE else View.GONE
+ chat.unreadMessageCount.toString().also { binding.unreadCount.text = it }
+
+ binding.typingIcon.visibility = if (chat.isTyping) View.VISIBLE else View.GONE
+ binding.typing.visibility = if (chat.isTyping) View.VISIBLE else View.GONE
+ binding.chatLastMessage.visibility = if (chat.isTyping) View.GONE else View.VISIBLE
+
+ binding.answeredToYouStatus.visibility =
+ if (chat.isUnreadedAnswerToYou) View.VISIBLE else View.GONE
+
+ binding.answeredIcon.visibility =
+ if (chat.isAnswered && !chat.isOpponnentReaded) View.VISIBLE else View.GONE
+ binding.answeredAndReadedIcon.visibility =
+ if (chat.isAnswered && chat.isOpponnentReaded) View.VISIBLE else View.GONE
+ binding.pinnedStatus.visibility = if (chat.isPinned) View.VISIBLE else View.GONE
+
+ val targetSize = 500 // Размер в пикселях, до которого нужно увеличить изображение
+ // Загрузка аватара
+ if (chat.avatarUrl != null) {
+ Glide.with(binding.chatAvatar.context)
+ .load(chat.avatarUrl)
+ .transform(
+ ResizeAndCropTransformation(targetSize),
+ CircleCrop()
+ ) // Обрезаем и применяем круг
+ .into(binding.chatAvatar)
+ } else {
+ binding.chatAvatar.setImageResource(R.drawable.ic_placeholder_avatar)
+ }
+
+ // Загрузка аватара ответившего
+ if (chat.lastAnswererUrl != null) {
+ Glide.with(binding.answererIcon.context)
+ .load(chat.lastAnswererUrl)
+ //.circleCrop()
+ .into(binding.answererIcon)
+ binding.answererIcon.visibility = View.VISIBLE
+ } else {
+ binding.answererIcon.setImageResource(android.R.color.transparent)
+ binding.answererIcon.visibility = View.GONE
+ }
+
+ // Обработчик нажатия на кнопку архивирования
+ binding.archiveButton.setOnClickListener {
+ val position = adapterPosition
+ if (position != RecyclerView.NO_POSITION) {
+ val chatObj = currentList[position]
+ // Обработка архивации
+ onArchiveChat(chatObj)
+ // Скрыть шторку
+ val archiveLayout =
+ binding.root.findViewById(R.id.archiveButtonLayout)
+ archiveLayout.visibility = View.GONE
+ notifyItemChanged(position)
+ }
+ }
+
+
+ binding.root.setOnClickListener {
+ val archiveLayout =
+ binding.root.findViewById(R.id.archiveButtonLayout)
+ val itemLayout = binding.root.findViewById(R.id.chatItemLayout)
+ if (archiveLayout.visibility == View.VISIBLE) {
+ // Анимация возврата в исходное положение
+ itemLayout.animate()
+ .translationX(0f)
+ .setDuration(500)
+ .withEndAction {
+ // После завершения анимации скрываем шторку
+ archiveLayout.visibility = View.GONE
+ // Обновляем элемент только после завершения анимации
+ val position = adapterPosition
+ if (position != RecyclerView.NO_POSITION) {
+ notifyItemChanged(position)
+ }
+ }
+ .start()
+
+ }
+ }
+ }
+ }
+ }
+
+ inner class LoadingViewHolder(view: View) : ViewHolder(view)
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return when (viewType) {
+ VIEW_TYPE_DATA -> {
+ val binding = ItemChatBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ ChatViewHolder(binding)
+ }
+ VIEW_TYPE_LOADING -> {
+ val view = LayoutInflater.from(parent.context)
+ .inflate(R.layout.item_loading, parent, false)
+ LoadingViewHolder(view)
+ }
+ else -> throw IllegalArgumentException(context.getString(R.string.invalid_view_type))
+ }
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ when (holder) {
+ is ChatViewHolder -> holder.bind(getItem(position) as DataChat)
+ is LoadingViewHolder -> {
+ // Здесь ничего не нужно делать, если загрузка не требует биндинга
+ }
+ else -> throw IllegalArgumentException(context.getString(R.string.invalid_view_type))
+ }
+ }
+
+}
+
+class ChatDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Chat, newItem: Chat): Boolean
+ = (oldItem as? DataChat)?.id == (newItem as? DataChat)?.id
+ override fun areContentsTheSame(oldItem: Chat, newItem: Chat): Boolean
+ = oldItem == newItem
+}
diff --git a/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt b/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt
index e2cdca7..2067e67 100644
--- a/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt
+++ b/app/src/main/java/otus/gpb/recyclerview/MainActivity.kt
@@ -1,12 +1,482 @@
package otus.gpb.recyclerview
-import androidx.appcompat.app.AppCompatActivity
+import android.graphics.Canvas
import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.Toast
+import androidx.appcompat.app.ActionBarDrawerToggle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.view.GravityCompat
+import androidx.drawerlayout.widget.DrawerLayout
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.appbar.MaterialToolbar
+import com.google.android.material.floatingactionbutton.FloatingActionButton
+import com.google.android.material.navigation.NavigationView
+import kotlin.math.abs
+import kotlin.random.Random
+
class MainActivity : AppCompatActivity() {
+ private lateinit var chatAdapter: ChatAdapter
+ private var itemTouchHelper: ItemTouchHelper? = null
+
+ private lateinit var drawerLayout: DrawerLayout
+ private lateinit var navigationView: NavigationView
+ private lateinit var toolbar: MaterialToolbar
+
+ private var isLoading = false
+ private var lastChatId: Int = 1;
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+
+
+ this.title = getString(R.string.app_title)
+
+ // Initialize views
+ drawerLayout = findViewById(R.id.drawer_layout)
+ navigationView = findViewById(R.id.navigation_view)
+ toolbar = findViewById(R.id.toolbar)
+
+ // Set up toolbar
+ setSupportActionBar(toolbar)
+
+ // Add navigation drawer toggle
+ val toggle = ActionBarDrawerToggle(
+ this, drawerLayout, toolbar,
+ R.string.navigation_drawer_open,
+ R.string.navigation_drawer_close
+ )
+ toggle.drawerArrowDrawable.color = ContextCompat.getColor(this, R.color.colorOnPrimary)
+ drawerLayout.addDrawerListener(toggle)
+ toggle.syncState()
+
+ // Handle navigation menu item clicks
+ navigationView.setNavigationItemSelectedListener { menuItem ->
+ when (menuItem.itemId) {
+ R.id.nav_home -> {
+ Toast.makeText(this, getString(R.string.home_selected), Toast.LENGTH_SHORT).show()
+ }
+ R.id.nav_settings -> {
+ Toast.makeText(this, getString(R.string.settings_selected), Toast.LENGTH_SHORT).show()
+ }
+ R.id.nav_about -> {
+ Toast.makeText(this,getString(R.string.about_selected), Toast.LENGTH_SHORT).show()
+ }
+ }
+ drawerLayout.closeDrawer(GravityCompat.START)
+ true
+ }
+
+ val fab = findViewById(R.id.fab)
+ fab.setOnClickListener {
+ // Обработка нажатия на кнопку
+ Toast.makeText(
+ this,
+ getString(R.string.write_new_message),
+ Toast.LENGTH_SHORT
+ ).show()
+ // Здесь вы можете добавить логику для открытия нового экрана или действия
+ }
+
+
+ val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
+
+ val divider = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
+ divider.setDrawable(ContextCompat.getDrawable(this, R.drawable.recycler_view_devider)!!)
+ recyclerView.addItemDecoration(divider)
+
+ chatAdapter = ChatAdapter(
+ context = this,
+ onArchiveChat = { chat ->
+ // Обработка архивирования
+ val updatedList = chatAdapter.currentList.toMutableList()
+ updatedList.remove(chat)
+ chatAdapter.submitList(updatedList)
+ Toast.makeText(this, "$chat archived", Toast.LENGTH_SHORT).show()
+ }
+ )
+
+ recyclerView.layoutManager = LinearLayoutManager(this)
+ recyclerView.adapter = chatAdapter
+
+ val itemTouchHelperCallback = object : ItemTouchHelper.Callback() {
+
+ override fun getMovementFlags(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder
+ ): Int {
+ // Позволяем свайпы влево
+ return makeMovementFlags(0, ItemTouchHelper.LEFT)
+ }
+
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean {
+ // Перемещение элементов отключено
+ return false
+ }
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ val position = viewHolder.adapterPosition
+ if (position == RecyclerView.NO_POSITION) return
+
+ if (direction == ItemTouchHelper.LEFT) {
+ // Длинный свайп (удаление)
+ val updatedList = chatAdapter.currentList.toMutableList()
+ updatedList.removeAt(position)
+ chatAdapter.submitList(updatedList)
+ Toast.makeText(this@MainActivity, "Deleted item at position $position", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ override fun onChildDraw(
+ c: Canvas,
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ dX: Float,
+ dY: Float,
+ actionState: Int,
+ isCurrentlyActive: Boolean
+ ) {
+ val itemView = viewHolder.itemView
+
+ // Получаем смещение dX (оно будет отрицательным для свайпа влево)
+ val translationX = abs(dX)
+
+ // Устанавливаем шторку в видимое состояние, если свайп достаточно длинный
+ val archiveLayout = itemView.findViewById(R.id.archiveButtonLayout)
+ if (translationX >= itemView.width * 0.8f) {
+ // Длинный свайп (удаление)
+ archiveLayout.visibility = View.GONE
+ } else {
+ // Полусвайп (показ шторки)
+ archiveLayout.visibility = View.VISIBLE
+
+ }
+
+ // Выполняем стандартный рендеринг
+ super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
+ }
+
+ override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
+ super.clearView(recyclerView, viewHolder)
+
+ val archiveLayout = viewHolder.itemView.findViewById(R.id.archiveButtonLayout)
+ val itemLayout = viewHolder.itemView.findViewById(R.id.chatItemLayout)
+
+ // Проверяем, видима ли шторка
+ if (archiveLayout.visibility != View.GONE) {
+ // Анимация возврата в исходное положение
+ // Сброс состояния
+ itemLayout.postDelayed({
+ itemLayout.animate()
+ .translationX(0f)
+ .setDuration(500)
+ .withEndAction {
+ // После завершения анимации скрываем шторку
+ archiveLayout.visibility = View.GONE
+
+ // Обновляем элемент только после завершения анимации
+ val position = viewHolder.adapterPosition
+ if (position != RecyclerView.NO_POSITION) {
+ chatAdapter.notifyItemChanged(position)
+ }
+ }
+ .start()
+ }, 3000)
+
+ }
+ }
+
+ override fun isItemViewSwipeEnabled(): Boolean = true
+ }
+
+ itemTouchHelper = ItemTouchHelper(itemTouchHelperCallback)
+ itemTouchHelper?.attachToRecyclerView(recyclerView)
+
+
+ // Слушатель для пагинации
+ recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
+ super.onScrolled(recyclerView, dx, dy)
+
+ val layoutManager = recyclerView.layoutManager as LinearLayoutManager
+ val visibleItemCount = layoutManager.childCount
+ val totalItemCount = layoutManager.itemCount
+ val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
+
+ if (!isLoading && (visibleItemCount + firstVisibleItemPosition) >= totalItemCount
+ && firstVisibleItemPosition >= 0
+ ) {
+ loadMoreItems()
+ }
+ }
+ })
+
+ // Загрузить данные
+ loadMoreItems()
+
+ }
+
+
+ private fun loadMoreItems() {
+ // Проверяем, не загружаются ли уже данные
+ if (isLoading) return
+ isLoading = true
+ val list = chatAdapter.currentList.toMutableList()
+ // Добавляем элемент загрузки в список
+ if (!list.contains(ChatLoading)) {
+ list.add(ChatLoading)
+ chatAdapter.submitList(list.toList()) // Обновляем адаптер
+ }
+ // Эмуляция загрузки данных
+ Handler(Looper.getMainLooper()).postDelayed({
+ // Убираем индикатор загрузки
+ list.remove(ChatLoading)
+
+ list.addAll(loadChats())
+ // Используем submitList для обновления адаптера
+ chatAdapter.submitList(list.toList())
+ isLoading = false
+ }, 1500) // Задержка для эмуляции сети
+ }
+
+
+ private fun loadChats(): List {
+ return listOf(
+ UserChat(
+ id = lastChatId++,
+ lastUserName = "Alice",
+ lastMessage = "Hi there!",
+ time = "12:30",
+ isVerified = true,
+ avatarUrl = "https://gravatar.com/avatar/478f6b94ddcde12416b90f22d7588cab?s=400&d=robohash&r=x",
+ isScam = false,
+ unreadMessageCount = 0,
+ isMute = false,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isPinned = true,
+ isOpponnentReaded = false,
+ isAnswered = true
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "Mentors",
+ lastUserName = "Bob",
+ lastMessage = "How are you?",
+ time = "11:15",
+ isVerified = false,
+ avatarUrl = "https://gravatar.com/avatar/1ae9a8dbb50baebe44d7b96d012a73d5?s=400&d=robohash&r=x",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(30),
+ isMute = false,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = true,
+ isAnswered = true,
+ isLock = false,
+ isPinned = true,
+ lastAnswererUrl = "https://i.pinimg.com/736x/c9/fe/fb/c9fefb489d5fdc792ae324103255edd2.jpg"
+
+ ),
+ UserChat(
+ id = lastChatId++,
+ lastUserName = "Charlie",
+ lastMessage = "Meeting at 3?",
+ time = "Yesterday",
+ isVerified = true,
+ avatarUrl = "https://gravatar.com/avatar/f07d785a9ee32506a7a077f25466f98b?s=400&d=robohash&r=x",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(15),
+ isMute = true,
+ isSpeeching = true,
+ isTyping = false,
+ isUnreadedAnswerToYou = true
+ ),
+ UserChat(
+ id = lastChatId++,
+ lastUserName = "Marilyn",
+ lastMessage = "Tomorow?",
+ time = "Yesterday",
+ isVerified = false,
+ avatarUrl = "https://i.pinimg.com/736x/75/26/5b/75265b439fb335a418e79b13b447b1a6.jpg",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(50),
+ isMute = false,
+ isSpeeching = false,
+ isTyping = true,
+ isUnreadedAnswerToYou = false,
+ isAnswered = false,
+ isOpponnentReaded = false
+ ),
+ UserChat(
+ id = lastChatId++,
+ lastUserName = "Elvis",
+ lastMessage = "Dear! Not today.",
+ time = "Yesterday",
+ isVerified = true,
+ avatarUrl = "https://www.kino-teatr.ru/news/20390/183753.jpg",
+ isScam = false,
+ unreadMessageCount = 0,
+ isMute = false,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isOpponnentReaded = true
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "Cat's and mouse",
+ lastUserName = "Catzilla",
+ lastMessage = "Good morning!",
+ time = "06:07",
+ isVerified = false,
+ avatarUrl = "https://s9.travelask.ru/uploads/post/000/031/157/main_image/facebook-bf918145c8d2cee688d53ee7112500d3.jpg",
+ isScam = true,
+ unreadMessageCount = 0,
+ isMute = false,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = true,
+ isAnswered = true,
+ isLock = true,
+ lastAnswererUrl = "https://i.pinimg.com/originals/52/c6/65/52c665df0515dd447eb92544374cf543.jpg"
+
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "StarLine Tours",
+ lastUserName = "Bear Grils",
+ lastMessage = "Let's go!",
+ time = "10:09",
+ isVerified = false,
+ avatarUrl = "https://avatars.mds.yandex.net/i?id=c7269ba0c5fc64e968daedd67f497d1d82453fcf-7760894-images-thumbs&n=13",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(150),
+ isMute = false,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isLock = false,
+ lastAnswererUrl = "https://avatars.mds.yandex.net/get-kinopoisk-image/1898899/78473e64-0a54-46ba-87ad-94b2822e9aaf/1920x"
+
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "News & Facts",
+ lastUserName = "Truth Reporter",
+ lastMessage = "Aliens already here!",
+ time = "23:20",
+ isVerified = false,
+ avatarUrl = "https://avatars.mds.yandex.net/i?id=a81133d9a76c76f1504ca65334107711af3e3b92-10465625-images-thumbs&n=13",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(301),
+ isMute = true,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isLock = false,
+ lastAnswererUrl = "https://www.kino-teatr.ru/news/20390/183753.jpg"
+
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "Food",
+ lastUserName = "Supplier",
+ lastMessage = "Food for wealth.",
+ time = "21:41",
+ isVerified = false,
+ avatarUrl = "https://avatars.mds.yandex.net/i?id=e1258c5d321183ada452bdb6f7283115a439ce89-10246451-images-thumbs&n=13",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(350),
+ isMute = true,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isLock = false,
+ lastAnswererUrl = "https://www.axial.net/wp-content/uploads/2016/07/naturalfood.jpg"
+
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "Fitness",
+ lastUserName = "Trainer",
+ lastMessage = "Let's go to training!",
+ time = "22:15",
+ isVerified = false,
+ avatarUrl = "https://cdn.culture.ru/images/cf6e22be-dddf-55cf-bef4-4dde1e64fa63",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(360),
+ isMute = true,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isLock = false,
+ lastAnswererUrl = "https://avatars.mds.yandex.net/i?id=6ce40ad4578dddf9bf81d1a52f44b5f027ee78a7-4078102-images-thumbs&n=13"
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "Technology News",
+ lastUserName = "Bober",
+ lastMessage = "Ready for new apple!",
+ time = "Fri",
+ isVerified = true,
+ avatarUrl = "https://avatars.mds.yandex.net/i?id=fc179096458914d6908cd807b942bf73cf8b74cc-3663718-images-thumbs&n=13",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(3000),
+ isMute = true,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isLock = false,
+ lastAnswererUrl = "https://avatars.mds.yandex.net/i?id=67e2837139254b993171edce157f551949602e2b-12714815-images-thumbs&n=13"
+ ),
+ GroupChat(
+ id = lastChatId++,
+ title = "Fashion News",
+ lastUserName = "Pavlin",
+ lastMessage = "Exclusive for you!",
+ time = "Fri",
+ isVerified = true,
+ avatarUrl = "https://avatars.mds.yandex.net/i?id=cc4788280c0d75f6882102161b08737ac79c7973-4262069-images-thumbs&n=13",
+ isScam = false,
+ unreadMessageCount = Random.nextInt(40),
+ isMute = true,
+ isSpeeching = false,
+ isTyping = false,
+ isUnreadedAnswerToYou = false,
+ isAnswered = true,
+ isLock = false,
+ lastAnswererUrl = "https://avatars.mds.yandex.net/i?id=3e4a09ab3c6b398ac222fe28ef03953e043d48b7b0a55b2b-12999039-images-thumbs&n=13"
+
+ )
+
+
+ )
}
-}
\ No newline at end of file
+
+}
+
+
+
+
diff --git a/app/src/main/java/otus/gpb/recyclerview/ResizeToMinSideTransformation.kt b/app/src/main/java/otus/gpb/recyclerview/ResizeToMinSideTransformation.kt
new file mode 100644
index 0000000..65a12f1
--- /dev/null
+++ b/app/src/main/java/otus/gpb/recyclerview/ResizeToMinSideTransformation.kt
@@ -0,0 +1,36 @@
+package otus.gpb.recyclerview
+
+import android.graphics.Bitmap
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
+import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
+import java.security.MessageDigest
+
+class ResizeAndCropTransformation(private val targetSize: Int) : BitmapTransformation() {
+
+ override fun transform(
+ pool: BitmapPool,
+ toTransform: Bitmap,
+ outWidth: Int,
+ outHeight: Int
+ ): Bitmap {
+ // Определяем масштаб для увеличения изображения до нужного размера
+ val scale = targetSize.toFloat() / minOf(toTransform.width, toTransform.height)
+
+ val resizedWidth = (toTransform.width * scale).toInt()
+ val resizedHeight = (toTransform.height * scale).toInt()
+
+ // Масштабируем изображение
+ val resizedBitmap = Bitmap.createScaledBitmap(toTransform, resizedWidth, resizedHeight, true)
+
+ // Обрезаем до квадрата
+ val minSide = minOf(resizedWidth, resizedHeight)
+ val left = (resizedWidth - minSide) / 2
+ val top = (resizedHeight - minSide) / 2
+
+ return Bitmap.createBitmap(resizedBitmap, left, top, minSide, minSide)
+ }
+
+ override fun updateDiskCacheKey(messageDigest: MessageDigest) {
+ messageDigest.update(("ResizeAndCropTransformation:$targetSize").toByteArray())
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/circle_border.xml b/app/src/main/res/drawable/circle_border.xml
new file mode 100644
index 0000000..b4b96d0
--- /dev/null
+++ b/app/src/main/res/drawable/circle_border.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/circle_border_blue_20.xml b/app/src/main/res/drawable/circle_border_blue_20.xml
new file mode 100644
index 0000000..ef218a2
--- /dev/null
+++ b/app/src/main/res/drawable/circle_border_blue_20.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/circle_border_silver_10.xml b/app/src/main/res/drawable/circle_border_silver_10.xml
new file mode 100644
index 0000000..ebdb013
--- /dev/null
+++ b/app/src/main/res/drawable/circle_border_silver_10.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml
new file mode 100644
index 0000000..43eb47e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_archive.xml b/app/src/main/res/drawable/ic_archive.xml
new file mode 100644
index 0000000..bee2e39
--- /dev/null
+++ b/app/src/main/res/drawable/ic_archive.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_at.xml b/app/src/main/res/drawable/ic_at.xml
new file mode 100644
index 0000000..690f919
--- /dev/null
+++ b/app/src/main/res/drawable/ic_at.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_blue_verified.xml b/app/src/main/res/drawable/ic_blue_verified.xml
new file mode 100644
index 0000000..552bd9e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_blue_verified.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_bubles.xml b/app/src/main/res/drawable/ic_bubles.xml
new file mode 100644
index 0000000..e36ba82
--- /dev/null
+++ b/app/src/main/res/drawable/ic_bubles.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_green_check.xml b/app/src/main/res/drawable/ic_green_check.xml
new file mode 100644
index 0000000..0950241
--- /dev/null
+++ b/app/src/main/res/drawable/ic_green_check.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_green_double_check.xml b/app/src/main/res/drawable/ic_green_double_check.xml
new file mode 100644
index 0000000..320454b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_green_double_check.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml
new file mode 100644
index 0000000..f8acc37
--- /dev/null
+++ b/app/src/main/res/drawable/ic_home.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml
new file mode 100644
index 0000000..475684d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_info.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml
new file mode 100644
index 0000000..ab2a883
--- /dev/null
+++ b/app/src/main/res/drawable/ic_lock.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_main_menu.xml b/app/src/main/res/drawable/ic_main_menu.xml
new file mode 100644
index 0000000..32b6ead
--- /dev/null
+++ b/app/src/main/res/drawable/ic_main_menu.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_mute.xml b/app/src/main/res/drawable/ic_mute.xml
new file mode 100644
index 0000000..7d09270
--- /dev/null
+++ b/app/src/main/res/drawable/ic_mute.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_nav_header_avatar.xml b/app/src/main/res/drawable/ic_nav_header_avatar.xml
new file mode 100644
index 0000000..9d783a5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_nav_header_avatar.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_pinned.xml b/app/src/main/res/drawable/ic_pinned.xml
new file mode 100644
index 0000000..bc08f6f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_pinned.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_placeholder_avatar.xml b/app/src/main/res/drawable/ic_placeholder_avatar.xml
new file mode 100644
index 0000000..03d0044
--- /dev/null
+++ b/app/src/main/res/drawable/ic_placeholder_avatar.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_scam.xml b/app/src/main/res/drawable/ic_scam.xml
new file mode 100644
index 0000000..b739235
--- /dev/null
+++ b/app/src/main/res/drawable/ic_scam.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..b305691
--- /dev/null
+++ b/app/src/main/res/drawable/ic_settings.xml
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_status_speech.xml b/app/src/main/res/drawable/ic_status_speech.xml
new file mode 100644
index 0000000..4f367f0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_status_speech.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/recycler_view_devider.xml b/app/src/main/res/drawable/recycler_view_devider.xml
new file mode 100644
index 0000000..8972b1a
--- /dev/null
+++ b/app/src/main/res/drawable/recycler_view_devider.xml
@@ -0,0 +1,10 @@
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_background.xml b/app/src/main/res/drawable/rounded_background.xml
new file mode 100644
index 0000000..d320df6
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 2d026df..82ab7a4 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,13 +1,73 @@
-
-
+
+ android:layout_height="match_parent">
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_chat.xml b/app/src/main/res/layout/item_chat.xml
new file mode 100644
index 0000000..4529823
--- /dev/null
+++ b/app/src/main/res/layout/item_chat.xml
@@ -0,0 +1,373 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_loading.xml b/app/src/main/res/layout/item_loading.xml
new file mode 100644
index 0000000..80c40b0
--- /dev/null
+++ b/app/src/main/res/layout/item_loading.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/nav_header.xml b/app/src/main/res/layout/nav_header.xml
new file mode 100644
index 0000000..6159d78
--- /dev/null
+++ b/app/src/main/res/layout/nav_header.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/navigation_menu.xml b/app/src/main/res/menu/navigation_menu.xml
new file mode 100644
index 0000000..46b7a58
--- /dev/null
+++ b/app/src/main/res/menu/navigation_menu.xml
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 114f376..1849f80 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -1,16 +1,18 @@
-
+
-
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..08d9831
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f8c6127..873f527 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -7,4 +7,48 @@
#FF018786
#FF000000
#FFFFFFFF
+
+ #2196F3
+ #1976D2
+ #81C784
+ #388E3C
+ #64B5F6
+ #A5D6A7
+ #4CAF50
+
+
+ #2c75b0
+ #1a5b8e
+ #ffffff
+
+ #F5F5F5
+ #66A9E0
+ #F5F5F5
+
+ #f5f5f5
+ #000000
+ #757575
+
+ #d3d3d3
+
+ #9e9e9e
+ #FFFFFF
+
+
+ #1f2a36
+ #0c1520
+ #ffffff
+
+ #1a1a1a
+ #a0a0a0
+ #ffffff
+
+ #1a1a1a
+ #e0e0e0
+ #a0a0a0
+
+ #212121
+ #9e9e9e
+ #121212
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3d78b1f..791ec94 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,42 @@
RecyclerView
+ description
+ User Name
+ 12:34
+ Last message in chat
+ Speech status
+ Mute channel
+ Last user
+ Archive
+ End of shadow
+ Answered
+ Pinned
+ Verified
+ Answered
+ Answered and opponent readed
+ Scam
+ Lock channel
+ Topic
+ Margin topic
+ Typing
+ typing
+ Answerer
+ 101011
+ Main menu
+ Telegram
+ Home
+ Exit
+ Username
+ Avatar
+ Navigation drawer open
+ Navigation drawer close
+ Settings
+ About
+ Telegram
+ Home selected
+ Settings selected
+ About selected
+ Invalid view type
+ New message
+ Write new message
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..0d2c4cc
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 2187cf1..d35017b 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,16 +1,18 @@
-
+
-
\ No newline at end of file
diff --git a/app/src/test/java/otus/gpb/recyclerview/ExampleUnitTest.kt b/app/src/test/java/otus/gpb/recyclerview/ExampleUnitTest.kt
index 5ce306c..9d2c85f 100644
--- a/app/src/test/java/otus/gpb/recyclerview/ExampleUnitTest.kt
+++ b/app/src/test/java/otus/gpb/recyclerview/ExampleUnitTest.kt
@@ -1,17 +1,14 @@
package otus.gpb.recyclerview
-import org.junit.Test
-
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
+ *
+ * class ExampleUnitTest {
+ * @Test
+ * fun addition_isCorrect() {
+ * assertEquals(4, 2 + 2)
+ * }
+ * }
*/
-class ExampleUnitTest {
- @Test
- fun addition_isCorrect() {
- assertEquals(4, 2 + 2)
- }
-}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index bd20018..c1baa7e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,10 +1,10 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id 'com.android.application' version '8.7.2' apply false
- id 'com.android.library' version '8.7.2' apply false
+ id 'com.android.application' version '8.7.3' apply false
+ id 'com.android.library' version '8.7.3' apply false
id 'org.jetbrains.kotlin.android' version '2.0.21' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
-}
\ No newline at end of file
+}
diff --git a/gradle.properties b/gradle.properties
index cd0519b..b793761 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,4 +20,7 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
+android.nonTransitiveRClass=true
+
+
+android.suppressUnsupportedCompileSdk=1
\ No newline at end of file