more changes

This commit is contained in:
Tucan444 2021-04-21 11:34:03 +02:00
parent d14dd7c1fd
commit 8737a5a471
31 changed files with 1647 additions and 126 deletions

@ -1,6 +1,6 @@
<resources>
<!--
TODO: Before you run your application, you need a Google Maps API key.
Before you run your application, you need a Google Maps API key.
To get one, follow this link, follow the directions and press "Create" at the end:

@ -7,11 +7,11 @@ import android.os.Environment
import android.view.View
import android.widget.Toast
import com.google.android.material.snackbar.Snackbar
import okhttp3.*
import org.json.JSONArray
import java.io.*
import java.io.File
import java.io.FileInputStream
import java.nio.channels.FileChannel
import java.nio.charset.Charset
import java.util.*
// for showing messages
@ -85,6 +85,18 @@ fun Context.getStringFromSharedPreferences(accessKey: String, preferencesFilenam
return ""
}
// Other
fun Context.getRandomGenerator(seedString: String): Random {
var n: Long = 0
for (element in seedString) {
n += element.toInt()
}
println(n)
return Random(n)
}
// Activity extensions
fun Activity.askToQuit() {

@ -48,7 +48,6 @@ class MainActivity : AppCompatActivity() {
askToQuit()
}
is infoFragment -> {
println(CustomBackstackVariables.infoFragmentBackDestination)
when (CustomBackstackVariables.infoFragmentBackDestination) {
"exploreFragment" -> { currentlyShownFragment.goExploreFragment() }
"mapFragment" -> {currentlyShownFragment.goMapFragment()}
@ -78,6 +77,11 @@ class MainActivity : AppCompatActivity() {
windowManager.defaultDisplay.getMetrics(displayMetrics)
ScreenParameters.height = displayMetrics.heightPixels
ScreenParameters.width = displayMetrics.widthPixels
val savedBaseUrl = this.getStringFromSharedPreferences("baseUrlSave")
if (savedBaseUrl != "") {
ServerManagement.baseUrl = savedBaseUrl
}
}
override fun onResume() {
@ -90,11 +94,12 @@ class MainActivity : AppCompatActivity() {
val names = json.currentJsonObject!!.names()
try {
names?.let {
mainFragmentHost.childFragmentManager.fragments[0]?.let {
if (it is homeFragment) {
LabeledValuesSupplier.wipeData()
for (n in 0 until names!!.length()) {
for (n in 0 until names.length()) {
val labeledValue = LabeledValue(names[n].toString(), json.getAttributeContent(names[n].toString()))
if (!LabeledValuesSupplier.checkIfContains(labeledValue)) {
LabeledValuesSupplier.appendLabeledValue(labeledValue)
@ -111,6 +116,7 @@ class MainActivity : AppCompatActivity() {
}
}
}
}
} catch (e: Throwable) { println("[debug] Exception in main activity, sensors connection : $e") }
}
@ -122,7 +128,7 @@ class MainActivity : AppCompatActivity() {
// getting other needed information
val dataReceiver2: (String) -> Unit = {data1: String ->
var json = JsonManager(this, data1)
json = JsonManager(this, json.findJsonObjectByAttribute("ID", data0.toInt()), "JSONObject")
json = JsonManager(this, json.findJsonObjectByAttribute("ID", data0.toInt()), "JSONObject") // todo doesnt return correct result
val positionsList = json.getAttributeContent("location").split(",")
MapManagement.connectedServerPosition = LatLng(positionsList[0].toDouble(), positionsList[1].toDouble())
}

@ -5,6 +5,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.wikispot.ChatManagement
import com.example.wikispot.GeneralVariables
import com.example.wikispot.R
import com.example.wikispot.modelsForAdapters.Message
import kotlinx.android.synthetic.main.message.view.*
@ -19,8 +21,20 @@ class ChatMessagesAdapter(private val context: Context, private val messages: Ar
fun setData(message: Message?, pos: Int) {
message?.let {
itemView.message_author_text.text = message.author
itemView.message_author_text.text = message.senderName
itemView.message_content_text.text = message.content
if (GeneralVariables.id == message.senderId) {
itemView.message_author_text.textAlignment = View.TEXT_ALIGNMENT_TEXT_END
itemView.message_content_text.textAlignment = View.TEXT_ALIGNMENT_TEXT_END
}
for (n in 0 until ChatManagement.lastNames.length()) {
if (ChatManagement.lastNames[n] == message.senderId) {
itemView.message_author_text.textAlignment = View.TEXT_ALIGNMENT_TEXT_END
itemView.message_content_text.textAlignment = View.TEXT_ALIGNMENT_TEXT_END
itemView.message_author_text.text = GeneralVariables.name
}
}
}
this.message = message

File diff suppressed because it is too large Load Diff

@ -1,16 +1,20 @@
package com.example.wikispot.fragments
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.View
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.wikispot.R
import com.example.wikispot.ServerManagement
import com.example.wikispot.*
import com.example.wikispot.adapters.ChatMessagesAdapter
import com.example.wikispot.adapters.FileViewsAdapter
import com.example.wikispot.databases.NamesDatabase
import com.example.wikispot.modelClasses.JsonManager
import com.example.wikispot.modelsForAdapters.Message
import com.example.wikispot.modelsForAdapters.MessagesSupplier
import kotlinx.android.synthetic.main.fragment_chat.*
import kotlinx.android.synthetic.main.fragment_info.*
import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.json.JSONArray
import java.io.IOException
class chatFragment : Fragment(R.layout.fragment_chat) {
@ -19,20 +23,93 @@ class chatFragment : Fragment(R.layout.fragment_chat) {
super.onViewCreated(view, savedInstanceState)
updateRecyclerView()
sendMessageBtn.setOnClickListener {
GeneralVariables.id?.let {
if (userMessageText.text.toString() != "" ) {
val message = Message(GeneralVariables.id!!, userMessageText.text.toString(), "waiting")
MessagesSupplier.appendMessage(message)
userMessageText.setText("")
val messagePostThread = Thread(MessagePost(message))
messagePostThread.start()
updateRecyclerView()
} else {
requireContext().showToast("sending empty messages is not permitted")
}
}
}
}
override fun onResume() {
super.onResume()
loadNamesCache()
val dataReceiver: (String) -> Unit = { data: String ->
println("[debug][chat connection] data: $data")
val json = JsonManager(requireContext(), data, "JSONObject")
try {
when (json.getAttributeContent("source")) {
"messages/register" -> {
GeneralVariables.id = json.getAttributeContentByPath("data/0")
val r = requireContext().getRandomGenerator(GeneralVariables.id!!)
GeneralVariables.name = "${NamesDatabase.names[r.nextInt(NamesDatabase.names.size)]} - ${r.nextInt(9999).toString()}"
json.getAttributeContent("data")
json.getAttributeContent("1")
val length = json.currentJsonAttribute1!!.length()
json.clearSelectedAttribute()
for (i in 0 until length) {
val jsonOfMessage = JsonManager(requireContext(), json.getAttributeContentByPath("data/1/$i"), "JSONObject")
val message = Message(jsonOfMessage.getAttributeContent("sender"),
jsonOfMessage.getAttributeContent("message"),
jsonOfMessage.getAttributeContent("timestamp"))
if (!MessagesSupplier.checkIfContains(message)) {
MessagesSupplier.appendMessage(message)
updateRecyclerView()
}
}
}
"messages/get" -> {
json.getAttributeContent("data")
val length = json.currentJsonAttribute1!!.length()
json.clearSelectedAttribute()
for (i in 0 until length) {
println("message at index n: ${json.getAttributeContentByPath("data/$i")}")
val jsonOfMessage = JsonManager(requireContext(), json.getAttributeContentByPath("data/$i"), "JSONObject")
val message = Message(jsonOfMessage.getAttributeContent("sender"),
jsonOfMessage.getAttributeContent("message"),
jsonOfMessage.getAttributeContent("timestamp"))
val lastMessageSentIndex = MessagesSupplier.getIndexOfLastMessageFromSelf()
if (message.senderId != GeneralVariables.id) {
if (!MessagesSupplier.checkIfContains(message)) {
MessagesSupplier.appendMessage(message)
updateRecyclerView()
}
} else {
lastMessageSentIndex?.let {
MessagesSupplier.messages[lastMessageSentIndex]!!.timestamp = jsonOfMessage.getAttributeContent("timestamp")
}
}
}
}
}
} catch (e: Throwable) { println("[debug][chat fragment] Exception: $e") }
}
ServerManagement.serverManager.addReceiverConnection(dataReceiver, requireContext(), "chatConnection", 0, ServerManagement.chat_keyword)
ServerManagement.serverManager.addChatConnection(dataReceiver, requireContext(), "chatConnection")
}
override fun onPause() {
super.onPause()
saveNamesCache()
ServerManagement.serverManager.deleteConnection("chatConnection")
}
@ -46,9 +123,74 @@ class chatFragment : Fragment(R.layout.fragment_chat) {
val adapter = context?.let { ChatMessagesAdapter(it, MessagesSupplier.messages) }
chat_messages_recycler_view.adapter = adapter
chat_messages_recycler_view.scrollToPosition(MessagesSupplier.messages.size - 1)
}
} catch (e: Throwable) { println("[debug] e5 Exception: $e") }
}
inner class MessagePost(private val message: Message): Runnable {
override fun run() {
val urlBuilder: HttpUrl.Builder = "${ServerManagement.baseUrl}messages/post".toHttpUrlOrNull()!!.newBuilder()
.addQueryParameter("m_sender", message.senderId)
.addQueryParameter("message", message.content)
val url: String = urlBuilder.build().toString()
val formBody: FormBody = FormBody.Builder().build()
val request: Request = Request.Builder()
.url(url)
.post(formBody)
.build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
response.body?.let {
val receivedString = response.body!!.string()
println("[debug][message post] received string from post request: $receivedString")
}
}
override fun onFailure(call: Call, e: IOException) {
println("Request Failed")
println(e)
}
})
}
}
// loading and saving last names
private fun loadNamesCache() {
val namesCache = requireContext().getStringFromSharedPreferences("namesCache", "chatPreferences")
if (namesCache != "") {
ChatManagement.lastNames = JSONArray(namesCache)
}
}
private fun saveNamesCache() {
GeneralVariables.id?.let {
ChatManagement.lastNames.let {
val namesCache = JSONArray()
var subtractAmount = it.length()
if (it.length() > (ChatManagement.numberOfNamesToCache - 1)) {
subtractAmount = ChatManagement.numberOfNamesToCache - 1
}
for (i in it.length() - subtractAmount until it.length()) {
namesCache.put(it[i])
}
namesCache.put(GeneralVariables.id)
requireContext().saveString("namesCache", namesCache.toString(), "chatPreferences")
}
}
}
}

@ -6,11 +6,9 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import com.example.wikispot.IntentsKeys
import com.example.wikispot.R
import com.example.wikispot.ServerManagement
import com.example.wikispot.*
import com.example.wikispot.activities.MainActivity
import com.example.wikispot.modelClasses.JsonManager
import com.example.wikispot.modelsForAdapters.MessagesSupplier
import kotlinx.android.synthetic.main.fragment_debug.*
@ -34,8 +32,9 @@ class debugFragment : Fragment(R.layout.fragment_debug) {
editTextIp.setText(ServerManagement.baseUrl)
changeIpBtn.setOnClickListener {
changeUrlBtn.setOnClickListener {
ServerManagement.baseUrl = editTextIp.text.toString()
requireContext().saveString("baseUrlSave", editTextIp.text.toString())
restartAppPartially()
}
@ -43,6 +42,10 @@ class debugFragment : Fragment(R.layout.fragment_debug) {
restartAppPartially()
}
closeAppBtn.setOnClickListener {
activity?.finish()
}
}
private fun restartAppPartially() {
@ -51,6 +54,8 @@ class debugFragment : Fragment(R.layout.fragment_debug) {
intent.putExtra(IntentsKeys.startFragment, "debugFragment")
ServerManagement.serverManager.clearConnections()
MessagesSupplier.wipeData()
GeneralVariables.id = null
startActivity(intent)
activity?.finish()

@ -4,6 +4,7 @@ import android.graphics.Bitmap
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import com.example.wikispot.R
import com.example.wikispot.ServerManagement
import com.example.wikispot.modelClasses.JsonManager
@ -18,6 +19,10 @@ class homeFragment : Fragment(R.layout.fragment_home) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
loadCache()
chatBtn.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.homeFragment_to_chatFragment)
}
}
override fun onResume() {

@ -1,6 +1,7 @@
package com.example.wikispot.modelClasses
import android.content.Context
import com.example.wikispot.GeneralVariables
import com.example.wikispot.getStringFromSharedPreferences
import com.example.wikispot.saveString
import com.example.wikispot.showToast
@ -72,7 +73,8 @@ data class JsonManager(private val context: Context, val data: String, val input
}
}
}
} else if (currentJsonAttribute1 != null) {
}
if (currentJsonAttribute1 != null) {
try {
currentJsonAttribute0 = currentJsonAttribute1!!.getJSONObject(name.toInt())
return currentJsonAttribute0.toString()
@ -117,7 +119,7 @@ data class JsonManager(private val context: Context, val data: String, val input
}
}
return ""
return GeneralVariables.variableMissingKeyword
}
fun getAttributeContentByPath(path: String): String {
@ -136,7 +138,7 @@ data class JsonManager(private val context: Context, val data: String, val input
// loading back saved json attributes
currentJsonAttribute0 = currentJsonAttributesBackup[0] as JSONObject?
currentJsonAttribute1 = currentJsonAttributesBackup[1] as JSONArray?
return ""
return GeneralVariables.variableMissingKeyword
}
}
@ -183,7 +185,7 @@ data class JsonManager(private val context: Context, val data: String, val input
val attributeContent = getAttributeContentByPath(attributePath)
if (attributeContent != "null") {
if (attributeContent != GeneralVariables.variableMissingKeyword) {
if (attributeContent == value.toString()) {
return currentJsonObject.toString()

@ -4,19 +4,23 @@ import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.widget.TextView
import com.example.wikispot.GeneralVariables
import com.example.wikispot.ScreenParameters
import com.example.wikispot.ServerManagement
import com.example.wikispot.modelsForAdapters.MessagesSupplier
import com.github.barteksc.pdfviewer.PDFView
import kotlinx.android.synthetic.main.file_view.view.*
import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.json.JSONArray
import org.json.JSONObject
import java.io.IOException
import java.io.InputStream
class ServerManager {
private var receiverConnections = mutableListOf<ReceiverConnection>()
private var viewConnections = mutableListOf<ViewConnection>()
private var chatConnections = mutableListOf<ChatConnection>()
// single time requests
@ -115,7 +119,12 @@ class ServerManager {
try {
val inputStream = java.net.URL(url).openStream()
val bitmap = BitmapFactory.decodeStream(inputStream)
var bitmap = BitmapFactory.decodeStream(inputStream)
if (bitmap.width > ScreenParameters.width) {
val ratio = bitmap.height.toFloat() / bitmap.width.toFloat()
bitmap = Bitmap.createScaledBitmap(bitmap, ScreenParameters.width, (ScreenParameters.width * ratio).toInt(), false)
}
imageReceiver(bitmap)
break
@ -153,12 +162,20 @@ class ServerManager {
} catch (e: Throwable) { println("In clearConnections: $e") }
}
receiverConnections = mutableListOf()
for (i in 0 until viewConnections.size) {
try {
viewConnections[i].running = false
} catch (e: Throwable) { println("In clearConnections: $e") }
}
viewConnections = mutableListOf()
for (i in 0 until chatConnections.size) {
try {
chatConnections[i].running = false
} catch (e: Throwable) { println("In clearConnections: $e") }
}
chatConnections = mutableListOf()
}
fun checkIfConnectionAlreadyExists(connectionName: String, connectionType: String = "any"): Boolean{
@ -176,6 +193,13 @@ class ServerManager {
}
}
}
if ((connectionType == "any") or (connectionType == "chat")) {
for (n in 0 until chatConnections.size) {
if (chatConnections[n].connectionName == connectionName) {
return true
}
}
}
return false
}
@ -202,6 +226,17 @@ class ServerManager {
} catch (e: Throwable) { println("In deleteConnection: $e") }
}
}
if ((connectionType == "any") or (connectionType == "chat")) {
for (i in 0 until chatConnections.size) { // checking in connections
try {
if (chatConnections[i].connectionName == connectionName) {
chatConnections[i].running = false
chatConnections.removeAt(i)
}
} catch (e: Throwable) { println("In deleteConnection: $e") }
}
}
}
fun addReceiverConnection(dataReceiver: (String) -> Unit, context: Context, connectionName: String, serverId: Int, path: String = "", attributePath: String = "", waitTime: Long = ServerManagement.receiverConnectionOnCheckWait) {
@ -401,4 +436,102 @@ class ServerManager {
}
fun addChatConnection(dataReceiver: (String) -> Unit, context: Context, connectionName: String) {
chatConnections.add(ChatConnection(dataReceiver, context, connectionName))
}
inner class ChatConnection(val dataReceiver: (String) -> Unit, val context: Context, val connectionName: String) {
var running = true
init {
val checkingServerDataThread = Thread(CheckingServerData())
checkingServerDataThread.start()
}
inner class CheckingServerData : Runnable {
override fun run() {
while (running) {
if (GeneralVariables.id == null) {
val url = "${ServerManagement.baseUrl}messages/register"
println(url)
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
response.body?.let {
val receivedString = response.body!!.string()
if (receivedString == "Internal Server Error") {
return
}
val returnJsonObject = JSONObject()
returnJsonObject.put("source", "messages/register")
returnJsonObject.put("data", JSONArray(receivedString))
dataReceiver(returnJsonObject.toString())
}
}
override fun onFailure(call: Call, e: IOException) {
println("Request Failed")
println(e)
}
})
} else {
var timestamp = "0"
if (MessagesSupplier.messages.isNotEmpty()) {
val messagesReversed = MessagesSupplier.messages.reversed()
for (i in messagesReversed.indices) {
if (messagesReversed[i]!!.timestamp != "waiting") {
timestamp = messagesReversed[i]!!.timestamp
break
}
}
}
val urlBuilder: HttpUrl.Builder = "${ServerManagement.baseUrl}messages/get".toHttpUrlOrNull()!!.newBuilder()
urlBuilder.addQueryParameter("timestamp", timestamp)
val url: String = urlBuilder.build().toString()
val request: Request = Request.Builder()
.url(url)
.build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
response.body?.let {
val receivedString = response.body!!.string()
if (receivedString == "Internal Server Error") {
return
}
val returnJsonObject = JSONObject()
returnJsonObject.put("source", "messages/get")
returnJsonObject.put("data", JSONArray(receivedString))
dataReceiver(returnJsonObject.toString())
}
}
override fun onFailure(call: Call, e: IOException) {
println("Request Failed")
println(e)
}
})
}
Thread.sleep(ServerManagement.chatConnectionOnCheckWait)
}
}
}
}
}

@ -11,7 +11,7 @@ import org.json.JSONArray
data class PlacePreview(var title: String, var description: String, var location: String? = null, var img: Bitmap? = null, val id: Int?=null) {
init {
val words = description.split(" ")
val words = description.split(" ", "\n")
description = ""
var lastLine = ""
@ -35,11 +35,7 @@ object PlaceSupplier {
var controlJson: JsonManagerLite? = null
var places = arrayOf<PlacePreview?>(
PlacePreview("River", "", "39.94071648123733,-85.9346308193051", null, 12),
PlacePreview("Velky Manin", "", "49.12590793522579,18.49571849264312", null, 16),
PlacePreview("Klapy", "", "49.161527643132175,18.41231657316252", null, 18)
)
var places = arrayOf<PlacePreview?>()
fun appendPlace(place: PlacePreview) {
val array = places.copyOf(places.size + 1)
@ -83,7 +79,6 @@ object PlaceSupplier {
val jsonManager = JsonManager(context, save)
for (n in 0 until jsonManager.getLengthOfJsonArray()) {
val savedData = jsonManager.jsonArray?.get(n).toString().split("|||||")
println("[debug] saved data is $savedData")
val place = PlacePreview(savedData[0], savedData[1], savedData[2], null, savedData[3].toInt())
if (!checkIfContains(place)) {
appendPlace(place)

@ -1,6 +1,29 @@
package com.example.wikispot.modelsForAdapters
data class Message(val author: String, val content: String)
import com.example.wikispot.GeneralVariables
import com.example.wikispot.databases.NamesDatabase
import java.util.*
data class Message(var senderId: String, val content: String, var timestamp: String="0") {
var senderName: String
init {
val r = getRandomGenerator(senderId)
senderName = "${NamesDatabase.names[r.nextInt(NamesDatabase.names.size)]} - ${r.nextInt(9999).toString()}"
}
private fun getRandomGenerator(seedString: String): Random {
var n: Long = 0
for (element in seedString) {
n += element.toInt()
}
return Random(n)
}
}
object MessagesSupplier {
@ -13,8 +36,29 @@ object MessagesSupplier {
messages = array
}
fun checkIfContains(message: Message) {
fun checkIfContains(message: Message): Boolean {
for (i in messages.indices) {
messages[i]?.let {
if (message.senderId == it.senderId) {
if (message.content == it.content) {
if (message.timestamp == it.timestamp) {
return true
}
}
}
}
}
return false
}
fun getIndexOfLastMessageFromSelf(): Int? {
var i: Int? = null
for (n in messages.indices) {
if (messages[n]!!.senderId == GeneralVariables.id) {
i = n
}
}
return i
}
fun wipeData() {

@ -1,14 +1,19 @@
package com.example.wikispot
import android.util.DisplayMetrics
import com.example.wikispot.modelClasses.ServerManager
import com.google.android.gms.maps.model.LatLng
import org.json.JSONArray
object GeneralVariables {
var appRunningFirstTime = true
var id: String? = null
var name: String? = null
const val variableMissingKeyword = "_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_"
}
object IntentsKeys {
@ -22,17 +27,22 @@ object ServerManagement {
var serverManager = ServerManager()
const val receiverConnectionOnCheckWait: Long = 4000
const val viewConnectionOnCheckWait: Long = 5000
const val chatConnectionOnCheckWait: Long = 1000
const val dataRequestOnAttemptWait: Long = 2000
const val imageRequestOnAttemptWait: Long = 2000
var baseUrl = "http://192.168.1.156:8000/"
var selectedServerId = 0
const val sensors_keyword = "_[{(S,e,n,s,o,r,s)}]_"
const val chat_keyword = "_[{(C,h,a,t)}]_"
var totalNumberOfRequestsSent = 0
}
object ChatManagement {
var lastNames = JSONArray()
const val numberOfNamesToCache = 4
}
object MapManagement {
var connectedServerPosition: LatLng? = LatLng(0.toDouble(), 0.toDouble())
var lastCoordinates = LatLng(0.toDouble(), 0.toDouble())

@ -9,7 +9,7 @@
/>
<stroke
android:color="#7FFFFFFF"
android:color="?attr/chatFragmentBgStrokeColor"
android:width="10dp"/>
</shape>

@ -0,0 +1,11 @@
<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/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

@ -5,6 +5,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="?attr/exploreFragmentListItemBackgroundColor"
android:layout_margin="5dp"
card_view:cardCornerRadius="10dp">

@ -1,10 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginTop="2dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="2dp"
android:backgroundTint="#22FFFFFF"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
@ -17,11 +23,11 @@
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="36dp"
tools:text="Filename"
android:textSize="24sp"
android:textStyle="bold"
card_view:layout_constraintStart_toStartOf="parent"
card_view:layout_constraintTop_toTopOf="parent" />
card_view:layout_constraintTop_toTopOf="parent"
tools:text="Filename" />
<ImageView
android:id="@+id/showFileBtn"

@ -11,12 +11,47 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chat_messages_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="12dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="0dp"
android:layout_margin="16dp"
app:layout_constraintBottom_toTopOf="@+id/constraintLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="?attr/chatFragmentWriteBarBgColor"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:id="@+id/userMessageText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/sendMessageBtn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/sendMessageBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_baseline_send_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -4,30 +4,29 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E35050"
android:background="#E34B4B"
tools:context=".fragments.debugFragment">
<Button
android:id="@+id/goSecondDebugFragmentBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:layout_marginEnd="52dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/debugFragmentTitle" />
<Button
android:id="@+id/getNumberOfSentRequestsBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginTop="16dp"
android:text="Get number of sent requests"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintEnd_toStartOf="@+id/goSecondDebugFragmentBtn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/goSecondDebugFragmentBtn" />
app:layout_constraintTop_toBottomOf="@+id/debugFragmentTitle" />
<ScrollView
android:id="@+id/scrollView3"
@ -56,11 +55,11 @@
</ScrollView>
<Button
android:id="@+id/changeIpBtn"
android:id="@+id/changeUrlBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Change IP"
android:text="Change Url"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editTextIp" />
@ -97,6 +96,31 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/changeIpBtn" />
app:layout_constraintTop_toBottomOf="@+id/changeUrlBtn" />
<TextView
android:id="@+id/debugFragmentTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Debug fragment"
android:textColor="#FFFFFF"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/closeAppBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Close app"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/restartAppPartiallyBtn" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -34,18 +34,29 @@
android:name="com.example.wikispot.fragments.infoFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="40dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toTopOf="@+id/chatBtn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/home_title">
app:layout_constraintTop_toBottomOf="@+id/home_title"
app:layout_constraintVertical_bias="0.0">
</androidx.fragment.app.FragmentContainerView>
<ImageView
android:id="@+id/chatBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginBottom="32dp"
android:src="@drawable/ic_baseline_chat_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -21,9 +21,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="64dp"
android:layout_marginLeft="64dp"
android:layout_marginTop="88dp"
android:text="Dark theme"
android:text="@string/dark_theme"
android:background="@drawable/text_background_gradient"
android:padding="5dp"
android:textColor="#FFFFFF"

@ -5,7 +5,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp">
android:backgroundTint="#22FFFFFF"
card_view:cardCornerRadius="6dp"
card_view:cardElevation="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
@ -19,7 +21,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:textSize="20sp"
android:textSize="12sp"
android:textStyle="bold"
card_view:layout_constraintEnd_toEndOf="parent"
card_view:layout_constraintHorizontal_bias="0.5"
@ -33,6 +35,8 @@
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:textAlignment="textStart"
android:textSize="18sp"
android:textStyle="bold"
card_view:layout_constraintBottom_toBottomOf="parent"
card_view:layout_constraintEnd_toEndOf="parent"
card_view:layout_constraintHorizontal_bias="0.5"

@ -28,7 +28,7 @@
android:label="fragment_home"
tools:layout="@layout/fragment_home" >
<action
android:id="@+id/action_homeFragment_to_chatFragment"
android:id="@+id/homeFragment_to_chatFragment"
app:destination="@id/chatFragment" />
<action
android:id="@+id/homeFragment_to_mapFragment"

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WikiSpot</string>
<string name="chat">Plaudern</string>
<string name="explore">Erkunden</string>
<string name="home">Start</string>
<string name="map">Karte</string>
<string name="settings">Einstellungen</string>
<string name="files">Dateien</string>
<string name="dark_theme">Dunkles Thema</string>
</resources>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ウィキすぽっと</string>
<string name="map">地図</string>
<string name="chat">チャット</string>
<string name="explore">見る</string>
<string name="home"></string>
<string name="files">ファイル</string>
<string name="settings">設定</string>
<string name="dark_theme">暗いテーマ</string>
</resources>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WikiSpot</string>
<string name="dark_theme">темная тема</string>
<string name="files">файлы</string>
<string name="settings">настройки</string>
<string name="map">карта</string>
<string name="home">дом</string>
<string name="explore">просматривать</string>
<string name="chat">чат</string>
</resources>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WikiSpot</string>
<string name="chat">Čet</string>
<string name="explore">Prehliadať</string>
<string name="home">Domov</string>
<string name="map">Mapa</string>
<string name="settings">Nastavenia</string>
<string name="files">Súbory</string>
<string name="dark_theme">Tmavá téma</string>
</resources>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- For gradient Backgrounds -->
<!-- For Backgrounds -->
<attr name="textBackgroundGradientStartColor" format="color"/>
<attr name="textBackgroundGradientEndColor" format="color"/>
@ -12,10 +12,13 @@
<attr name="chatFragmentGradientStartColor" format="color"/>
<attr name="chatFragmentGradientCenterColor" format="color"/>
<attr name="chatFragmentGradientEndColor" format="color"/>
<attr name="chatFragmentBgStrokeColor" format="color" />
<attr name="chatFragmentWriteBarBgColor" format="color" />
<attr name="exploreFragmentGradientStartColor" format="color"/>
<attr name="exploreFragmentGradientCenterColor" format="color"/>
<attr name="exploreFragmentGradientEndColor" format="color"/>
<attr name="exploreFragmentListItemBackgroundColor" format="color" />
<attr name="homeFragmentGradientStartColor" format="color"/>
<attr name="homeFragmentGradientCenterColor" format="color"/>

@ -26,10 +26,13 @@
<color name="chatFragmentGradientStartColor" >#FCB0EF</color>
<color name="chatFragmentGradientCenterColor" >#9ECFFF</color>
<color name="chatFragmentGradientEndColor" >#9FE7FF</color>
<color name="chatFragmentBgStrokeColor" >#7FFFFFFF</color>
<color name="chatFragmentWriteBarBgColor">#FFF</color>
<color name="exploreFragmentGradientStartColor" >#A1DEFC</color>
<color name="exploreFragmentGradientCenterColor" >#A5CBFF</color>
<color name="exploreFragmentGradientEndColor" >#F9B6F6</color>
<color name="exploreFragmentListItemBackgroundColor">#fff</color>
<color name="homeFragmentGradientStartColor" >#83E1FF</color>
<color name="homeFragmentGradientCenterColor" >#9EC6FF</color>
@ -55,32 +58,35 @@
<color name="bottomNavBarCheckedItemColorDark">#FFB571</color>
<color name="bottomNavBarItemColorDark">#320747</color>
<color name="bottomNavBarRippleColorDark">#33222222</color>
<color name="statusBarColorDark">#4527A0</color>
<color name="statusBarColorDark">#000000</color>
<color name="textBackgroundGradientStartColorDark" >#80E5BEFF</color>
<color name="textBackgroundGradientEndColorDark" >#80FFB5F0</color>
<color name="textBackgroundGradientStartColorDark" >#80A185B4</color>
<color name="textBackgroundGradientEndColorDark" >#80926789</color>
<color name="bottomNavBarGradientStartColorDark" >#FCDD94</color>
<color name="bottomNavBarGradientEndColorDark" >#C5F8AB</color>
<color name="bottomNavBarGradientStartColorDark" >#9F8B5D</color>
<color name="bottomNavBarGradientEndColorDark" >#749265</color>
<color name="chatFragmentGradientStartColorDark" >#FCB0EF</color>
<color name="chatFragmentGradientCenterColorDark" >#9ECFFF</color>
<color name="chatFragmentGradientEndColorDark" >#9FE7FF</color>
<color name="chatFragmentGradientStartColorDark" >#885E81</color>
<color name="chatFragmentGradientCenterColorDark" >#516B85</color>
<color name="chatFragmentGradientEndColorDark" >#5E8A99</color>
<color name="chatFragmentBgStrokeColorDark" >#D43E3E3E</color>
<color name="chatFragmentWriteBarBgColorDark">#444</color>
<color name="exploreFragmentGradientStartColorDark" >#A1DEFC</color>
<color name="exploreFragmentGradientCenterColorDark" >#A5CBFF</color>
<color name="exploreFragmentGradientEndColorDark" >#F9B6F6</color>
<color name="exploreFragmentGradientStartColorDark" >#587A8B</color>
<color name="exploreFragmentGradientCenterColorDark" >#657C9C</color>
<color name="exploreFragmentGradientEndColorDark" >#896488</color>
<color name="exploreFragmentListItemBackgroundColorDark">#636363</color>
<color name="homeFragmentGradientStartColorDark" >#83E1FF</color>
<color name="homeFragmentGradientCenterColorDark" >#9EC6FF</color>
<color name="homeFragmentGradientEndColorDark" >#FEBBFF</color>
<color name="homeFragmentGradientStartColorDark" >#4F889A</color>
<color name="homeFragmentGradientCenterColorDark" >#647EA3</color>
<color name="homeFragmentGradientEndColorDark" >#977098</color>
<color name="settingsFragmentGradientStartColorDark" >#92EB97FC</color>
<color name="settingsFragmentGradientCenterColorDark" >#A198F9</color>
<color name="settingsFragmentGradientEndColorDark" >#74C7F7</color>
<color name="settingsFragmentGradientStartColorDark" >#92875691</color>
<color name="settingsFragmentGradientCenterColorDark" >#6863A2</color>
<color name="settingsFragmentGradientEndColorDark" >#4B7F9D</color>
<color name="infoFragmentGradientStartColorDark" >#FFB6FB</color>
<color name="infoFragmentGradientCenterColorDark" >#A7D2FF</color>
<color name="infoFragmentGradientEndColorDark" >#96E7FF</color>
<color name="infoFragmentGradientStartColorDark" >#966B94</color>
<color name="infoFragmentGradientCenterColorDark" >#69829D</color>
<color name="infoFragmentGradientEndColorDark" >#54818E</color>
</resources>

@ -6,7 +6,6 @@
<string name="map">Map</string>
<string name="settings">Settings</string>
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="files">Files</string>
<string name="dark_theme">Dark theme</string>
</resources>

@ -12,7 +12,7 @@
<item name="colorSecondaryVariant">@color/secondaryVariant</item>
<item name="colorOnSecondary">@color/onSecondary</item>
<!-- For gradient Backgrounds -->
<!-- For Backgrounds -->
<item name="textBackgroundGradientStartColor" >@color/textBackgroundGradientStartColor</item>
<item name="textBackgroundGradientEndColor" >@color/textBackgroundGradientEndColor</item>
@ -23,10 +23,13 @@
<item name="chatFragmentGradientStartColor" >@color/chatFragmentGradientStartColor</item>
<item name="chatFragmentGradientCenterColor" >@color/chatFragmentGradientCenterColor</item>
<item name="chatFragmentGradientEndColor" >@color/chatFragmentGradientEndColor</item>
<item name="chatFragmentBgStrokeColor">@color/chatFragmentBgStrokeColor</item>
<item name="chatFragmentWriteBarBgColor">@color/chatFragmentWriteBarBgColor</item>
<item name="exploreFragmentGradientStartColor" >@color/exploreFragmentGradientStartColor</item>
<item name="exploreFragmentGradientCenterColor" >@color/exploreFragmentGradientCenterColor</item>
<item name="exploreFragmentGradientEndColor" >@color/exploreFragmentGradientEndColor</item>
<item name="exploreFragmentListItemBackgroundColor">@color/exploreFragmentListItemBackgroundColor</item>
<item name="homeFragmentGradientStartColor" >@color/homeFragmentGradientStartColor</item>
<item name="homeFragmentGradientCenterColor" >@color/homeFragmentGradientCenterColor</item>
@ -70,7 +73,7 @@
<item name="colorSecondaryVariant">@color/secondaryVariantDark</item>
<item name="colorOnSecondary">@color/onSecondaryDark</item>
<!-- For gradient Backgrounds -->
<!-- For Backgrounds -->
<item name="textBackgroundGradientStartColor" >@color/textBackgroundGradientStartColorDark</item>
<item name="textBackgroundGradientEndColor" >@color/textBackgroundGradientEndColorDark</item>
@ -81,10 +84,13 @@
<item name="chatFragmentGradientStartColor" >@color/chatFragmentGradientStartColorDark</item>
<item name="chatFragmentGradientCenterColor" >@color/chatFragmentGradientCenterColorDark</item>
<item name="chatFragmentGradientEndColor" >@color/chatFragmentGradientEndColorDark</item>
<item name="chatFragmentBgStrokeColor">@color/chatFragmentBgStrokeColorDark</item>
<item name="chatFragmentWriteBarBgColor">@color/chatFragmentWriteBarBgColorDark</item>
<item name="exploreFragmentGradientStartColor" >@color/exploreFragmentGradientStartColorDark</item>
<item name="exploreFragmentGradientCenterColor" >@color/exploreFragmentGradientCenterColorDark</item>
<item name="exploreFragmentGradientEndColor" >@color/exploreFragmentGradientEndColorDark</item>
<item name="exploreFragmentListItemBackgroundColor">@color/exploreFragmentListItemBackgroundColorDark</item>
<item name="homeFragmentGradientStartColor" >@color/homeFragmentGradientStartColorDark</item>
<item name="homeFragmentGradientCenterColor" >@color/homeFragmentGradientCenterColorDark</item>