diff --git a/app/build.gradle b/app/build.gradle
index 1154c4a..07b107a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -24,10 +24,18 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- implementation 'androidx.appcompat:appcompat:1.0.2'
- implementation 'androidx.core:core-ktx:1.0.2'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'com.squareup.okhttp3:okhttp:4.2.1'
+ implementation 'io.reactivex.rxjava2:rxkotlin:2.2.0'
+ implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
+ implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
+ implementation 'com.squareup.retrofit2:retrofit:2.4.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
+ implementation 'android.arch.lifecycle:extensions:1.1.1'
+ implementation 'com.google.android.material:material:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4bdaf9e..d8b2197 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
+ package="itis.ru.wschat">
+
+
-
+ android:theme="@style/AppTheme">
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/Const.kt b/app/src/main/java/itis/ru/wschat/Const.kt
new file mode 100644
index 0000000..ae9a966
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/Const.kt
@@ -0,0 +1,9 @@
+package itis.ru.wschat
+
+object Const {
+ const val API_CHAT: String = "wss://backend-chat.cloud.technokratos.com/chat"
+ const val API_BASE: String = "https://backend-chat.cloud.technokratos.com/"
+ const val PREFERENCES: String = "SHARED_PREFERENCES"
+ const val DEVICE_ID: String = "device_id"
+ const val USERNAME: String = "username"
+}
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/MainActivity.kt b/app/src/main/java/itis/ru/wschat/MainActivity.kt
deleted file mode 100644
index c2e601c..0000000
--- a/app/src/main/java/itis/ru/wschat/MainActivity.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package itis.ru.wschat
-
-import androidx.appcompat.app.AppCompatActivity
-import android.os.Bundle
-
-class MainActivity : AppCompatActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
-}
diff --git a/app/src/main/java/itis/ru/wschat/Utils.kt b/app/src/main/java/itis/ru/wschat/Utils.kt
new file mode 100644
index 0000000..1f120e3
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/Utils.kt
@@ -0,0 +1,13 @@
+package itis.ru.wschat
+
+import java.util.*
+
+object Utils {
+ fun generateRandomString(length: Int): String? {
+ val AB = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
+ val rnd = Random()
+ val sb = StringBuilder(length)
+ for (i in 0 until length) sb.append(AB[rnd.nextInt(AB.length)])
+ return sb.toString()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/adapters/MessageAdapter.kt b/app/src/main/java/itis/ru/wschat/adapters/MessageAdapter.kt
new file mode 100644
index 0000000..94f7983
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/adapters/MessageAdapter.kt
@@ -0,0 +1,89 @@
+package itis.ru.wschat.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.RecyclerView
+import itis.ru.wschat.R
+import itis.ru.wschat.models.Message
+
+class MessageAdapter internal constructor(
+ private val uidFrom: String, private var data: MutableList
+) : RecyclerView.Adapter() {
+ private var view: View? = null
+
+ override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
+ holder.setMessage(data[position])
+ }
+
+ override fun getItemCount(): Int {
+ return data.size
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
+ return if (viewType == R.layout.item_message_to) {
+ view =
+ LayoutInflater.from(parent.context).inflate(R.layout.item_message_to, parent, false)
+ MessageViewHolder()
+ } else {
+ view = LayoutInflater.from(parent.context)
+ .inflate(R.layout.item_message_from, parent, false)
+ MessageViewHolder()
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return if (uidFrom != data[position].user) {
+ R.layout.item_message_to
+ } else {
+ R.layout.item_message_from
+ }
+ }
+
+ override fun getItemId(position: Int): Long {
+ return data[position].id
+ }
+
+ fun updateData(list: MutableList) {
+ val diffResult = DiffUtil.calculateDiff(RecentDiffUtilCallback(this.data, list))
+ diffResult.dispatchUpdatesTo(this)
+ this.data = list
+ }
+
+ inner class MessageViewHolder : RecyclerView.ViewHolder(view!!) {
+ internal fun setMessage(message: Message) {
+ val textView = view?.findViewById(R.id.text_view)
+ textView?.text = message.message
+ }
+ }
+
+ class RecentDiffUtilCallback internal constructor(
+ private val oldList: List,
+ private val newList: List
+ ) : DiffUtil.Callback() {
+
+ override fun getOldListSize(): Int {
+ return oldList.size
+ }
+
+ override fun getNewListSize(): Int {
+ return newList.size
+ }
+
+ override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val old = oldList[oldItemPosition]
+ val new = newList[newItemPosition]
+ return old.id == new.id
+ }
+
+ override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
+ val old = oldList[oldItemPosition]
+ val new = newList[newItemPosition]
+ return old == new
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/itis/ru/wschat/api/LoginApiService.kt b/app/src/main/java/itis/ru/wschat/api/LoginApiService.kt
new file mode 100644
index 0000000..d8e99cb
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/api/LoginApiService.kt
@@ -0,0 +1,13 @@
+package itis.ru.wschat.api
+
+import io.reactivex.Single
+import itis.ru.wschat.Const
+import itis.ru.wschat.models.LoginResponse
+import itis.ru.wschat.models.User
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+interface LoginApiService{
+ @POST("login")
+ fun login(@Body user: User): Single
+}
diff --git a/app/src/main/java/itis/ru/wschat/api/SocketManager.kt b/app/src/main/java/itis/ru/wschat/api/SocketManager.kt
new file mode 100644
index 0000000..7184ded
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/api/SocketManager.kt
@@ -0,0 +1,71 @@
+package itis.ru.wschat.api
+
+import android.content.Context
+import android.util.Log
+import itis.ru.wschat.Const
+import okhttp3.*
+import java.util.concurrent.TimeUnit
+
+private const val NORMAL_CLOSURE_STATUS = 1000
+
+class SocketManager(
+ private val context: Context,
+ private var messageCallback: (String?, Throwable?) -> Unit,
+ private var getMessagesCallback: (String?, Throwable?) -> Unit
+) {
+ private val client: OkHttpClient = OkHttpClient().newBuilder().build()
+ private lateinit var socket: WebSocket
+ private var deviceIdSent = false
+
+ fun initSocketManager() {
+ val request: Request = Request.Builder().url(Const.API_CHAT).build()
+ val listener = object : WebSocketListener() {
+ override fun onOpen(webSocket: WebSocket, response: Response) {
+ super.onOpen(webSocket, response)
+ Log.d("Socket", "connect")
+ if (!deviceIdSent) {
+ }
+ val deviceId =
+ context.getSharedPreferences(Const.PREFERENCES, Context.MODE_PRIVATE)
+ .getString(Const.DEVICE_ID, "")
+ val json = "{ \"device_id\":\"$deviceId\" }"
+ webSocket.send(json)
+ deviceIdSent = true
+ }
+
+ override fun onMessage(webSocket: WebSocket, text: String) {
+ super.onMessage(webSocket, text)
+ if (text == "{\"status\": \"ok\"}"){
+ messageCallback(text, null)
+ }else if (text.contains("items")){
+ getMessagesCallback(text, null)
+ }
+ Log.d("Socket", "onMessage $text")
+ }
+
+ override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
+ Log.d("Socket", "onClosing $reason")
+ webSocket.close(NORMAL_CLOSURE_STATUS, null)
+ }
+
+ override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
+ super.onFailure(webSocket, t, response)
+ socket = client.newWebSocket(request, this)
+ messageCallback(null, t)
+ Log.d("Socket", "error $t response $response")
+ }
+
+ }
+ socket = client.newWebSocket(request, listener)
+ }
+
+ fun getMessages(count: Int) {
+ val json = "{ \"history\": { \"limit\": $count} }"
+ socket.send(json)
+ }
+
+ fun sendMessage(message: String) {
+ val json = "{ \"message\":\"$message\" }"
+ socket.send(json)
+ }
+}
diff --git a/app/src/main/java/itis/ru/wschat/models/GetMessagesResponse.java b/app/src/main/java/itis/ru/wschat/models/GetMessagesResponse.java
new file mode 100644
index 0000000..004d279
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/models/GetMessagesResponse.java
@@ -0,0 +1,70 @@
+package itis.ru.wschat.models;
+
+import java.util.List;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class GetMessagesResponse {
+
+ @SerializedName("items")
+ @Expose
+ private List items = null;
+ @SerializedName("first")
+ @Expose
+ private Integer first;
+
+ public List getItems() {
+ return items;
+ }
+
+ public void setItems(List items) {
+ this.items = items;
+ }
+
+ public Integer getFirst() {
+ return first;
+ }
+
+ public void setFirst(Integer first) {
+ this.first = first;
+ }
+
+}
+
+class Item {
+
+ @SerializedName("id")
+ @Expose
+ private Integer id;
+ @SerializedName("user")
+ @Expose
+ private String user;
+ @SerializedName("message")
+ @Expose
+ private String message;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+}
diff --git a/app/src/main/java/itis/ru/wschat/models/LoginError.kt b/app/src/main/java/itis/ru/wschat/models/LoginError.kt
new file mode 100644
index 0000000..a5b4284
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/models/LoginError.kt
@@ -0,0 +1,3 @@
+package itis.ru.wschat.models
+
+data class LoginError(val errors: String)
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/models/LoginResponse.kt b/app/src/main/java/itis/ru/wschat/models/LoginResponse.kt
new file mode 100644
index 0000000..d65b09a
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/models/LoginResponse.kt
@@ -0,0 +1,3 @@
+package itis.ru.wschat.models
+
+data class LoginResponse(val status: String)
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/models/Message.kt b/app/src/main/java/itis/ru/wschat/models/Message.kt
new file mode 100644
index 0000000..2ecc002
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/models/Message.kt
@@ -0,0 +1,7 @@
+package itis.ru.wschat.models
+
+data class Message(
+ val id: Long,
+ val message: String = "",
+ val user: String = ""
+)
diff --git a/app/src/main/java/itis/ru/wschat/models/Response.kt b/app/src/main/java/itis/ru/wschat/models/Response.kt
new file mode 100644
index 0000000..4044d3d
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/models/Response.kt
@@ -0,0 +1,11 @@
+package itis.ru.wschat.models
+
+
+class Response(val data: T?, val error: Throwable?) {
+
+ companion object {
+ fun success(data: T): Response = Response(data, null)
+
+ fun error(error: Throwable): Response? = Response(null, error)
+ }
+}
diff --git a/app/src/main/java/itis/ru/wschat/models/User.kt b/app/src/main/java/itis/ru/wschat/models/User.kt
new file mode 100644
index 0000000..f7547b0
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/models/User.kt
@@ -0,0 +1,7 @@
+package itis.ru.wschat.models
+
+import com.google.gson.annotations.SerializedName
+
+data class User(val username: String,
+ @SerializedName("device_id")
+ val deviceId: String)
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/ui/chat/ChatActivity.kt b/app/src/main/java/itis/ru/wschat/ui/chat/ChatActivity.kt
new file mode 100644
index 0000000..cbd2e90
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/ui/chat/ChatActivity.kt
@@ -0,0 +1,47 @@
+package itis.ru.wschat.ui.chat
+
+import android.content.Context
+import android.os.Bundle
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.Observer
+import itis.ru.wschat.Const
+import itis.ru.wschat.R
+import itis.ru.wschat.adapters.MessageAdapter
+import kotlinx.android.synthetic.main.activity_chat.*
+
+class ChatActivity : AppCompatActivity() {
+ private var viewModel: ChatViewModel = ChatViewModel(this)
+ private var adapter: MessageAdapter? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_chat)
+ initRecycler()
+ btn_send_message.setOnClickListener {
+ viewModel.sendMessage(et_message.text.toString())
+ et_message.setText("")
+ }
+ viewModel.getMessagesLiveData.observe(this, Observer {
+ if (it.data != null){
+ adapter?.updateData(it.data.toMutableList())
+ }
+ })
+ viewModel.messageSendLiveData.observe(this, Observer {
+ if (it.data != null) {
+ Toast.makeText(this, "Message sent", Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(this, "Error ${it.error?.message}", Toast.LENGTH_SHORT).show()
+ }
+ })
+ }
+
+ private fun initRecycler() {
+ val username: String = getSharedPreferences(Const.PREFERENCES, Context.MODE_PRIVATE)
+ .getString(Const.USERNAME, "").toString()
+
+ adapter = MessageAdapter(username, arrayListOf())
+ adapter?.setHasStableIds(true)
+ rv_messages.adapter = adapter
+ }
+}
diff --git a/app/src/main/java/itis/ru/wschat/ui/chat/ChatViewModel.kt b/app/src/main/java/itis/ru/wschat/ui/chat/ChatViewModel.kt
new file mode 100644
index 0000000..24d6710
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/ui/chat/ChatViewModel.kt
@@ -0,0 +1,47 @@
+package itis.ru.wschat.ui.chat
+
+import android.app.Activity
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.google.gson.Gson
+import itis.ru.wschat.api.SocketManager
+import itis.ru.wschat.models.GetMessagesResponse
+import itis.ru.wschat.models.Message
+import itis.ru.wschat.models.Response
+
+
+class ChatViewModel(context: Activity) : ViewModel() {
+ private val socketManager: SocketManager = SocketManager(context, { message, error ->
+ context.runOnUiThread {
+ if (message != null) {
+ messageSendLiveData.value = Response.success(message)
+ getMessages(1000)
+ } else if (error != null) {
+ messageSendLiveData.value = Response.error(error)
+ }
+ }
+ }, { messages, error ->
+ context.runOnUiThread {
+ if (messages != null) {
+ val response: GetMessagesResponse =
+ Gson().fromJson(messages, GetMessagesResponse::class.java)
+ getMessagesLiveData.value = Response.success(response.items)
+ }
+ }
+ })
+
+ val messageSendLiveData = MutableLiveData>()
+ val getMessagesLiveData = MutableLiveData>>()
+
+ init {
+ socketManager.initSocketManager()
+ }
+
+ fun getMessages(count: Int) {
+ socketManager.getMessages(count)
+ }
+
+ fun sendMessage(message: String) {
+ socketManager.sendMessage(message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/itis/ru/wschat/ui/login/LoginActivity.kt b/app/src/main/java/itis/ru/wschat/ui/login/LoginActivity.kt
new file mode 100644
index 0000000..9d86217
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/ui/login/LoginActivity.kt
@@ -0,0 +1,30 @@
+package itis.ru.wschat.ui.login
+
+import android.content.Intent
+import android.os.Bundle
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.Observer
+import itis.ru.wschat.R
+import itis.ru.wschat.models.User
+import itis.ru.wschat.ui.chat.ChatActivity
+import kotlinx.android.synthetic.main.activity_login.*
+
+class LoginActivity : AppCompatActivity() {
+ private val viewModel: LoginViewModel = LoginViewModel(this)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_login)
+ btn_login.setOnClickListener {
+ viewModel.login(User(et_name.text.toString(), et_device_id.text.toString()))
+ }
+ viewModel.loginLiveData.observe(this, Observer { response ->
+ if (response.error == null) {
+ startActivity(Intent(this, ChatActivity::class.java))
+ } else {
+ Toast.makeText(this, "Error ${response.error.message}", Toast.LENGTH_SHORT).show()
+ }
+ })
+ }
+}
diff --git a/app/src/main/java/itis/ru/wschat/ui/login/LoginViewModel.kt b/app/src/main/java/itis/ru/wschat/ui/login/LoginViewModel.kt
new file mode 100644
index 0000000..6fd2de9
--- /dev/null
+++ b/app/src/main/java/itis/ru/wschat/ui/login/LoginViewModel.kt
@@ -0,0 +1,51 @@
+package itis.ru.wschat.ui.login
+
+import android.content.Context
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.google.gson.GsonBuilder
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.schedulers.Schedulers
+import itis.ru.wschat.Const
+import itis.ru.wschat.Const.DEVICE_ID
+import itis.ru.wschat.Const.PREFERENCES
+import itis.ru.wschat.Const.USERNAME
+import itis.ru.wschat.api.LoginApiService
+import itis.ru.wschat.models.Response
+import itis.ru.wschat.models.User
+import retrofit2.Retrofit
+import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
+import retrofit2.converter.gson.GsonConverterFactory
+
+class LoginViewModel(private val context: Context) : ViewModel() {
+ val loginLiveData = MutableLiveData>()
+ private val disposables = CompositeDisposable()
+ private val api = Retrofit.Builder()
+ .baseUrl(Const.API_BASE)
+ .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
+ .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()
+ .create(LoginApiService::class.java)
+
+ fun login(user: User) {
+ disposables.add(
+ api.login(user)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({ response ->
+ if (response.status == "ok") {
+ val sharedPref =
+ context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE)
+ sharedPref.edit()
+ .putString(DEVICE_ID, user.deviceId)
+ .putString(USERNAME, user.username).apply()
+ loginLiveData.value = Response.success(response.status)
+ }
+ }, {
+ loginLiveData.value = Response.error(it)
+ it.printStackTrace()
+ })
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
index c7bd21d..1f6bb29 100644
--- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -2,13 +2,13 @@
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
- android:viewportHeight="108"
- android:viewportWidth="108">
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ android:strokeWidth="1"
+ android:strokeColor="#00000000">
+ android:strokeWidth="1"
+ android:strokeColor="#00000000" />
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index 2408e30..0d025f9 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,74 +1,170 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:viewportHeight="108">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/message_from.xml b/app/src/main/res/drawable/message_from.xml
new file mode 100644
index 0000000..b71efff
--- /dev/null
+++ b/app/src/main/res/drawable/message_from.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/message_to.xml b/app/src/main/res/drawable/message_to.xml
new file mode 100644
index 0000000..883f1d0
--- /dev/null
+++ b/app/src/main/res/drawable/message_to.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml
new file mode 100644
index 0000000..7143601
--- /dev/null
+++ b/app/src/main/res/layout/activity_chat.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..ee49440
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
\ 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
deleted file mode 100644
index cad1963..0000000
--- a/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_message_from.xml b/app/src/main/res/layout/item_message_from.xml
new file mode 100644
index 0000000..1dfc43d
--- /dev/null
+++ b/app/src/main/res/layout/item_message_from.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_message_to.xml b/app/src/main/res/layout/item_message_to.xml
new file mode 100644
index 0000000..360a15e
--- /dev/null
+++ b/app/src/main/res/layout/item_message_to.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index bbd3e02..eca70cf 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index bbd3e02..eca70cf 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -1,5 +1,5 @@
-
-
+
+
\ 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 77d0241..ca2609c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,4 @@
WSChat
+ LoginActivity
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5885930..545b9c6 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -8,4 +8,13 @@
- @color/colorAccent
+
+
+
+
+
+