some changes

This commit is contained in:
Tucan444 2021-03-22 09:12:29 +01:00
parent c1733e7773
commit 8603a2aa38
25 changed files with 1103 additions and 102 deletions

@ -1,6 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="ben44">
<words>
<w>filetype</w>
<w>initing</w>
</words>
</dictionary>

@ -1,7 +1,6 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.chaquo.python'
id 'kotlin-android-extensions'
}
@ -11,7 +10,7 @@ android {
defaultConfig {
applicationId "com.example.wikispot"
minSdkVersion 16
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
@ -19,23 +18,6 @@ android {
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
sourceSets {
main {
python {
srcDirs = ["src/main/python"]
}
}
}
python {
pip {
install "requests"
}
}
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
buildFeatures {
@ -67,6 +49,7 @@ dependencies {
implementation 'androidx.navigation:navigation-ui-ktx:2.3.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

@ -1,19 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.wikispot">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.WikiSpotWithActionBar">
<activity android:name=".activities.MainActivity"
android:launchMode="singleTask">
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

@ -1,19 +1,13 @@
package com.example.wikispot.activities
import android.os.Build
import android.os.Bundle
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.setupWithNavController
import com.chaquo.python.Python
import com.chaquo.python.android.AndroidPlatform
import com.example.wikispot.R
import com.example.wikispot.*
import com.example.wikispot.modelClasses.SettingsSaveManager
import kotlinx.android.synthetic.main.activity_main.*
import org.json.JSONArray
import org.json.JSONObject
import java.util.*
class MainActivity : AppCompatActivity() {
@ -27,12 +21,39 @@ class MainActivity : AppCompatActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
/*if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
ManifestRelatedVariables.REQUEST_READ_EXTERNAL)
} */
loadSettings()
ServerManagement.serverManager.addActivityConnection(this, "main",0)
ServerManagement.serverManager.getData(this, this, 0, "", "", true)
setTheme(getThemeId())
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = findNavController(R.id.mainFragmentHost)
mainBottomNavigationView.setupWithNavController(navController)
handleExtras()
println("[debug] ${getDataFromServer()}")
}
private fun handleExtras() {
when (intent.getStringExtra(IntentsKeys.startFragment)) {
"chatFragment" -> {mainBottomNavigationView.selectedItemId = R.id.chatFragment}
"exploreFragment" -> {mainBottomNavigationView.selectedItemId = R.id.exploreFragment}
// skipping home fragment because were already here
"mapFragment" -> {mainBottomNavigationView.selectedItemId = R.id.mapFragment}
"settingsFragment" -> {mainBottomNavigationView.selectedItemId = R.id.settingsFragment}
}
}
private fun loadSettings() {
val settingsSaveManager = SettingsSaveManager(this)
settingsSaveManager.loadSettings()
}
}

@ -0,0 +1,18 @@
package com.example.wikispot
import android.app.Activity
import android.os.Build
import androidx.annotation.RequiresApi
import kotlinx.android.synthetic.main.activity_main.*
// for serverManager
fun Activity.receiveData(data: String) {
when (this.localClassName) {
"activities.MainActivity" -> { this.receiveDataForMainActivity(data) }
}
}
fun Activity.receiveDataForMainActivity(data: String) {
}

@ -1,4 +1,4 @@
package com.example.wikispot.models_and_adapters
package com.example.wikispot.adapters
import android.content.Context
import android.view.LayoutInflater
@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.wikispot.R
import com.example.wikispot.modelsForAdapters.PlacePreview
import kotlinx.android.synthetic.main.explore_list_item.view.*

@ -0,0 +1,124 @@
package com.example.wikispot
import android.content.Context
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.nio.channels.FileChannel
import java.nio.charset.Charset
// for showing messages
fun Context.showToast(message: String, length: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, length).show()
}
fun Context.showSnack(message: String, view: View, length: Int = Snackbar.LENGTH_LONG) {
Snackbar.make(this, view, message, length).show()
}
// for theme
fun Context.getThemeId(): Int {
if (ThemeOptions.darkTheme) {
if (ThemeOptions.actionBar) {
return R.style.Theme_WikiSpotWithActionBarDark
} else {
return R.style.Theme_WikiSpotDark
}
} else {
if (ThemeOptions.actionBar) {
return R.style.Theme_WikiSpotWithActionBar
} else {
return R.style.Theme_WikiSpot
}
}
}
// for client
fun Context.getDataFromServer(): String {
// requesting data
val url = "http://192.168.1.230:8000/devices_list"
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
var receivedResponse = ""
client.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
response.body?.let {
receivedResponse = response.body!!.string()
}
}
override fun onFailure(call: Call, e: IOException) {
println("Request Failed")
println(e)
}
})
Thread.sleep(400)
println("[debug] received string: $receivedResponse")
try {
JSONArray(receivedResponse)
return receivedResponse
} catch (exception: Throwable) {
return "[]"
}
}
// working with files
fun Context.createFile(filename: String, filetype: String): File {
val storageDir = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
if (!storageDir?.exists()!!) {
storageDir.mkdir()
}
return File(storageDir, "$filename.$filetype")
}
fun Context.getFile(filename: String, filetype: String): String {
val file = (getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)?.absolutePath ?: "") + "/$filename.$filetype"
val stream = FileInputStream(file)
var returnString = ""
stream.use { streamInUse ->
val fileChannel = streamInUse.channel
val mappedByteBuffer = fileChannel.map(
FileChannel.MapMode.READ_ONLY,
0,
fileChannel.size()
)
returnString = Charset.defaultCharset().decode(mappedByteBuffer).toString()
}
return returnString
}
fun Context.saveString(accessKey: String, stringValue: String, preferencesFilename: String="generalPreferences") {
val sharedPreferences = getSharedPreferences(preferencesFilename, Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.apply{
putString(accessKey, stringValue)
}.apply()
}
fun Context.getStringFromSharedPreferences(accessKey: String, preferencesFilename: String="generalPreferences"): String {
val sharedPreferences = getSharedPreferences(preferencesFilename, Context.MODE_PRIVATE)
val returnedString = sharedPreferences.getString(accessKey, "")
returnedString?.let {
return returnedString
}
return ""
}

@ -1,39 +0,0 @@
package com.example.wikispot
import android.content.Context
import android.view.View
import android.widget.Toast
import com.chaquo.python.Python
import com.chaquo.python.android.AndroidPlatform
import com.google.android.material.snackbar.Snackbar
import org.json.JSONObject
fun Context.showToast(message: String, length: Int=Toast.LENGTH_SHORT) {
Toast.makeText(this, message, length).show()
}
fun Context.showSnack(message: String, view: View, length: Int = Snackbar.LENGTH_LONG) {
Snackbar.make(this, view, message, length).show()
}
fun Context.getDataFromServer(): MutableList<JSONObject> {
// initing
if (!Python.isStarted()) {
Python.start(AndroidPlatform(this))
}
// getting file
val python = Python.getInstance()
val pythonFile = python.getModule("server_manager")
// getting the data
pythonFile.callAttr("init")
val size = pythonFile.callAttr("get_length").toInt()
val jsonList = mutableListOf<JSONObject>()
for (n in 0 until size) {
jsonList.add(n, JSONObject(pythonFile.callAttr("get_json", n).toString()))
}
return jsonList
}

@ -0,0 +1,71 @@
package com.example.wikispot.fragments
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
import kotlinx.android.synthetic.main.fragment_another_debug.*
import org.json.JSONObject
import kotlin.random.Random
class anotherDebugFragment : Fragment(R.layout.fragment_another_debug) {
private lateinit var jsonManager: JsonManager
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
jsonManager = JsonManager(requireContext(), "[]", "JSONArray", true)
generateAndSaveDataBtn.setOnClickListener {
val generatedData = JSONObject()
for (n in 0 until 10) {
generatedData.put("$n", Random.nextInt(0, 100))
}
context?.let {
jsonManager = JsonManager(requireContext(), generatedData.toString(), "JSONObject", true)
jsonManager.saveJson("test")
}
println("[debug] saved generated data")
}
loadAndShowDataBtn.setOnClickListener {
val json = jsonManager.loadJson(requireContext(), "test", "JSONObject")
dataContentView.text = json.currentJsonObject.toString()
}
stopConnectionBtn.setOnClickListener {
ServerManagement.serverManager.deleteConnection("debug", "view")
}
createViewConnectionBtn.setOnClickListener {
val attributePath = attributePathInput.text.toString()
val setWholeContent = wholeContentCheckBox.isChecked
val filePath = filePathInput.text.toString()
ServerManagement.serverManager.deleteConnection("debug", "view")
ServerManagement.serverManager.addViewConnection(requireContext(), dataContentView, "debug",0, filePath, attributePath, setWholeContent)
}
// handling navigation between debug fragments
goFirstDegubFragmentBtn.setOnClickListener {
cleanup()
Navigation.findNavController(it).navigate(R.id.navigateBackToDebugFragment)
}
}
override fun onDestroy() {
super.onDestroy()
cleanup()
}
private fun cleanup() {
ServerManagement.serverManager.deleteConnection("debug")
}
}

@ -4,16 +4,16 @@ import android.annotation.SuppressLint
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.getDataFromServer
import com.example.wikispot.showSnack
import com.example.wikispot.modelClasses.JsonManager
import kotlinx.android.synthetic.main.fragment_debug.*
import org.json.JSONObject
class debugFragment : Fragment(R.layout.fragment_debug) {
private var jsonList: MutableList<JSONObject> = mutableListOf<JSONObject>()
private lateinit var jsonManager: JsonManager
@SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -21,20 +21,37 @@ class debugFragment : Fragment(R.layout.fragment_debug) {
getDataBtn.setOnClickListener {
context?.let {
jsonList = requireContext().getDataFromServer()
sizeView.text = "Amount of json's: ${jsonList.size}"
jsonManager = JsonManager(requireContext(), requireContext().getDataFromServer(), "JSONArray", true)
sizeView.text = jsonManager.getLengthOfJsonArray().toString()
}
}
displayJsonFileBtn.setOnClickListener {
getJsonFileBtn.setOnClickListener {
val id = idInput.text.toString().toInt()
if (id >= jsonList.size) {
context?.let {
requireContext().showSnack("Id out of range.", displayJsonFileBtn)
}
jsonFileContentView.text = jsonManager.getJsonObject(id).toString()
}
getAttributeContentBtn.setOnClickListener {
val attributeName = attributeNameInput.text.toString()
if ("/" in attributeName) {
attributeContentView.text = jsonManager.getAttributeContentByPath(attributeNameInput.text.toString())
} else {
jsonFileOutputView.text = jsonList[id].toString()
attributeContentView.text = jsonManager.getAttributeContent(attributeNameInput.text.toString())
}
}
clearAttributeBtn.setOnClickListener {
jsonManager.clearSelectedAttribute()
attributeContentView.text = "attribute content"
}
attributeNameInput.setOnClickListener {
attributeContentView.text = jsonManager.getCurrentJsonAttributeContent()
}
// handling navigation between debug fragments
goSecondDebugFragmentBtn.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.navigateToAnotherDebugFragment)
}
}
}

@ -2,13 +2,11 @@ package com.example.wikispot.fragments
import android.os.Bundle
import android.view.View
import androidx.activity.addCallback
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.wikispot.R
import com.example.wikispot.models_and_adapters.PlacePreviewsAdapter
import com.example.wikispot.models_and_adapters.PlaceSupplier
import com.example.wikispot.adapters.PlacePreviewsAdapter
import com.example.wikispot.modelsForAdapters.PlaceSupplier
import kotlinx.android.synthetic.main.fragment_explore.*

@ -1,23 +1,62 @@
package com.example.wikispot.fragments
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.Navigation
import com.example.wikispot.IntentsKeys
import com.example.wikispot.R
import com.example.wikispot.ThemeOptions
import com.example.wikispot.activities.MainActivity
import com.example.wikispot.modelClasses.SettingsSaveManager
import kotlinx.android.synthetic.main.fragment_settings.*
class settingsFragment : Fragment(R.layout.fragment_settings) {
private lateinit var settingsSaveManager: SettingsSaveManager
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
settingsSaveManager = SettingsSaveManager(requireContext())
loadSettings()
debugBtn.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.navigateToDebugFragment)
}
darkThemeSwitch.setOnCheckedChangeListener { _, isChecked ->
ThemeOptions.darkTheme = isChecked
settingsSaveManager.saveSettings()
restartAppPartially()
}
actionBarSwitch.setOnCheckedChangeListener { _, isChecked ->
ThemeOptions.actionBar = isChecked
settingsSaveManager.saveSettings()
restartAppPartially()
}
}
}
private fun loadSettings() {
if (ThemeOptions.darkTheme) {
darkThemeSwitch.isChecked = true
}
if (ThemeOptions.actionBar) {
actionBarSwitch.isChecked = true
}
}
private fun restartAppPartially() {
val intent = Intent(context?.applicationContext, MainActivity::class.java)
intent.putExtra(IntentsKeys.startFragment, "settingsFragment")
startActivity(intent)
activity?.finish()
}
}

@ -0,0 +1,192 @@
package com.example.wikispot.modelClasses
import android.content.Context
import com.example.wikispot.getStringFromSharedPreferences
import com.example.wikispot.saveString
import com.example.wikispot.showToast
import org.json.JSONArray
import org.json.JSONObject
data class JsonManager(val context: Context, val data: String, val inputType: String = "JSONArray", val debug: Boolean = false) {
var jsonArray: JSONArray? = null
var currentJsonObject: JSONObject? = null
private var currentJsonAttribute0: JSONObject? = null
private var currentJsonAttribute1: JSONArray? = null
init {
if (inputType == "JSONArray") {
jsonArray = JSONArray(data)
try {
currentJsonObject = jsonArray!!.getJSONObject(0)
} catch (exception: Throwable) {}
if (debug) {
println("[debug] Content of received JSONArray is ${jsonArray.toString()}")
}
} else if (inputType == "JSONObject") {
currentJsonObject = JSONObject(data)
if (debug) {
println("[debug] Content of received JSONObject is ${currentJsonObject.toString()}")
}
}
}
fun getJsonObject(i: Int): JSONObject? {
jsonArray?.let {
if ((i >= jsonArray!!.length()) or (i < 0)) {
context.showToast("Index out of range")
} else {
currentJsonObject = jsonArray?.getJSONObject(i)
return currentJsonObject
}
}
if (jsonArray == null) {
context.showToast("Json Array is null")
}
return null
}
fun getAttributeContent(name: String): String {
if (currentJsonObject != null) {
if (currentJsonAttribute0 != null) {
try {
currentJsonAttribute0 = currentJsonAttribute0!!.getJSONObject(name)
return currentJsonAttribute0.toString()
} catch (exception: Throwable) {
try {
currentJsonAttribute1 = currentJsonAttribute0!!.getJSONArray(name)
currentJsonAttribute0 = null
return currentJsonAttribute1.toString()
} catch (exception: Throwable) {
try {
return currentJsonAttribute0!!.get(name).toString()
} catch (exception: Throwable) {
context.showToast("Invalid attribute name")
}
}
}
} else if (currentJsonAttribute1 != null) {
try {
currentJsonAttribute0 = currentJsonAttribute1!!.getJSONObject(name.toInt())
return currentJsonAttribute0.toString()
} catch (exception: Throwable) {
try {
currentJsonAttribute1 = currentJsonAttribute1!!.getJSONArray(name.toInt())
currentJsonAttribute0 = null
return currentJsonAttribute1.toString()
} catch (exception: Throwable) {
try {
return currentJsonAttribute1!!.get(name.toInt()).toString()
} catch (exception: Throwable) {
context.showToast("Invalid attribute name")
}
}
}
} else {
try {
currentJsonAttribute0 = currentJsonObject!!.getJSONObject(name)
return currentJsonAttribute0.toString()
} catch (exception: Throwable) {
try {
currentJsonAttribute1 = currentJsonObject!!.getJSONArray(name)
currentJsonAttribute0 = null
return currentJsonAttribute1.toString()
} catch (exception: Throwable) {
try {
return currentJsonObject!!.get(name).toString()
} catch (exception: Throwable) {
context.showToast("Invalid attribute name")
}
}
}
}
} else {
context.showToast("Json file is null")
}
return ""
}
fun getAttributeContentByPath(path: String): String {
val steps = path.split("/")
val currentJsonAttributesBackup = listOf(currentJsonAttribute0, currentJsonAttribute1) // backing up selected jsonAttributes
// getting the attribute
clearSelectedAttribute()
var result: Any? = null
for (step in steps) {
try {
result = getAttributeContent(step)
} catch (exception: Throwable) {
context.showToast("Invalid path")
// loading back saved json attributes
currentJsonAttribute0 = currentJsonAttributesBackup[0] as JSONObject?
currentJsonAttribute1 = currentJsonAttributesBackup[1] as JSONArray?
return ""
}
}
// loading back saved json attributes
currentJsonAttribute0 = currentJsonAttributesBackup[0] as JSONObject?
currentJsonAttribute1 = currentJsonAttributesBackup[1] as JSONArray?
// returning result
return result.toString()
}
fun clearSelectedAttribute() {
currentJsonAttribute0 = null
currentJsonAttribute1 = null
}
fun getLengthOfJsonArray(): Int {
return if (jsonArray != null) {
if (debug) {
println("[debug] Length of json array is ${jsonArray!!.length()}")
}
jsonArray!!.length()
} else {
println("[debug] Length of json array is 0")
0
}
}
fun getCurrentJsonAttributeContent(): String {
if (currentJsonAttribute0 != null) {
return currentJsonAttribute0.toString()
} else if (currentJsonAttribute1 != null) {
return currentJsonAttribute1.toString()
}
return "get json attribute first"
}
// saving and loading
fun saveJson(accessKey: String) {
// finding data that could be saved
if (jsonArray != null) {
context.saveString(accessKey, jsonArray.toString(), "jsonStrings")
} else if (currentJsonObject != null) {
context.saveString(accessKey, currentJsonObject.toString(), "jsonStrings")
} else if (currentJsonAttribute0 != null) {
context.saveString(accessKey, currentJsonAttribute0.toString(), "jsonStrings")
} else if (currentJsonAttribute1 != null) {
context.saveString(accessKey, currentJsonAttribute1.toString(), "jsonStrings")
} else {
context.showToast("Nothing to save")
}
}
fun loadJson(context: Context, accessKey: String, inputType: String = "JSONArray", debug: Boolean = false): JsonManager {
return JsonManager(context, context.getStringFromSharedPreferences(accessKey, "jsonStrings"), inputType, debug)
}
}

@ -0,0 +1,205 @@
package com.example.wikispot.modelClasses
import android.app.Activity
import android.content.Context
import android.widget.TextView
import com.example.wikispot.ServerManagement
import com.example.wikispot.receiveData
import okhttp3.*
import org.json.JSONArray
import java.io.IOException
class ServerManager {
private var activityConnections = mutableListOf<ActivityConnection>()
private var viewConnections = mutableListOf<ViewConnection>()
fun getData(activity: Activity, context: Context, serverId: Int, path: String, attributePath: String, getWholeContent: Boolean=false, numberOfAttempts: Int=2) {
val dataRequestThread = Thread(DataRequest(activity, context, serverId, path, attributePath, getWholeContent, numberOfAttempts))
dataRequestThread.start()
}
inner class DataRequest(val activity: Activity, val context: Context, val serverId: Int, val path: String="", val attributePath: String, var getWholeContent: Boolean=false, val numberOfAttempts: Int=2): Runnable{
override fun run() {
for (n in 0 until numberOfAttempts) {
var url = "http://192.168.1.230:8000/devices_list"
if (path != "") {
url = "http://192.168.1.230:8000/files/$serverId/$path"
}
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
}
try {
JSONArray(receivedString)
val jsonManager = JsonManager(context, receivedString)
if (path == "") {
jsonManager.getJsonObject(serverId)
} else {
if (attributePath == "") {
getWholeContent = true
}
}
if (getWholeContent) {
activity.receiveData(jsonManager.currentJsonObject.toString())
println("[debug] testing ${activity.localClassName} ; ${activity.componentName} ; ${activity.packageName}")
} else if(attributePath != "") {
activity.receiveData(jsonManager.getAttributeContentByPath(attributePath))
} else {
println("[debug] path or whole content needs to be chosen")
}
} catch (exception: Throwable) {
activity.receiveData(receivedString)
}
}
}
override fun onFailure(call: Call, e: IOException) {
println("Request Failed")
println(e)
}
})
Thread.sleep(ServerManagement.dataRequestOnAttemptWait)
}
}
}
// connections
fun deleteConnection(connectionName: String, connectionType: String="any") { // other types are any, activity and view
if ((connectionType == "any") or (connectionType == "activity")) {
for (i in 0 until activityConnections.size) { // checking in connections
if (activityConnections[i].connectionName == connectionName) {
activityConnections[i].running = false
activityConnections.removeAt(i)
}
}
}
if ((connectionType == "any") or (connectionType == "view")) {
for (i in 0 until viewConnections.size) { // checking in connections
if (viewConnections[i].connectionName == connectionName) {
viewConnections[i].running = false
viewConnections.removeAt(i)
}
}
}
}
fun addActivityConnection(activity: Activity, connectionName: String, serverId: Int, path: String?=null) {
activityConnections.add(ActivityConnection(activity, connectionName, serverId, path))
}
inner class ActivityConnection(val activity: Activity, val connectionName: String, val serverId: Int, val path: String?=null) {
var running = true
init {
val checkingServerDataThread = Thread(CheckingServerData())
checkingServerDataThread.start()
}
inner class CheckingServerData : Runnable {
override fun run() {
while (running) {
println("[debug] connection thread running")
Thread.sleep(ServerManagement.activityConnectionOnCheckWait)
}
}
}
}
fun addViewConnection(context: Context, view: TextView, connectionName: String, serverId: Int, path: String="", attributePath: String, getWholeContent: Boolean=false) {
viewConnections.add(ViewConnection(context, view, connectionName, serverId, path, attributePath, getWholeContent))
}
inner class ViewConnection(val context: Context, val view: TextView, val connectionName: String, val serverId: Int, val path: String="", var attributePath: String, var getWholeContent: Boolean=false) {
var running = true
init {
val checkingServerDataThread = Thread(CheckingServerData())
checkingServerDataThread.start()
}
inner class CheckingServerData: Runnable {
override fun run() {
while (running) {
var url = "http://192.168.1.230:8000/devices_list"
if (path != "") {
url = "http://192.168.1.230:8000/files/$serverId/$path"
}
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
}
try {
JSONArray(receivedString)
val jsonManager = JsonManager(context, receivedString)
if (path == "") {
jsonManager.getJsonObject(serverId)
} else {
if (attributePath == "") {
throw Throwable()
}
}
if (getWholeContent) {
view.post {
view.text = jsonManager.currentJsonObject.toString()
}
} else if(attributePath != "") {
view.post {
view.text = jsonManager.getAttributeContentByPath(attributePath)
}
} else {
println("[debug] path or whole content needs to be chosen")
}
} catch (exception: Throwable) {
view.post {
view.text = receivedString
}
}
}
}
override fun onFailure(call: Call, e: IOException) {
println("Request Failed")
println(e)
}
})
Thread.sleep(ServerManagement.viewConnectionOnCheckWait)
}
}
}
}
}

@ -0,0 +1,25 @@
package com.example.wikispot.modelClasses
import android.content.Context
import com.example.wikispot.ThemeOptions
class SettingsSaveManager(val context: Context) {
fun loadSettings() {
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
ThemeOptions.darkTheme = sharedPreferences.getBoolean("darkMode", ThemeOptions.darkTheme)
ThemeOptions.actionBar = sharedPreferences.getBoolean("actionBar", ThemeOptions.actionBar)
}
fun saveSettings() {
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.apply{
putBoolean("darkMode", ThemeOptions.darkTheme)
putBoolean("actionBar", ThemeOptions.actionBar)
}.apply()
}
}

@ -1,4 +1,4 @@
package com.example.wikispot.models_and_adapters
package com.example.wikispot.modelsForAdapters
import android.media.Image

@ -0,0 +1,32 @@
package com.example.wikispot
import com.example.wikispot.modelClasses.ServerManager
object ManifestRelatedVariables {
val REQUEST_READ_EXTERNAL = 1
}
object IntentsKeys {
const val startFragment = "start_fragment"
}
object ServerManagement {
val serverManager = ServerManager()
const val activityConnectionOnCheckWait: Long = 4000
const val viewConnectionOnCheckWait: Long = 5000
const val dataRequestOnAttemptWait: Long = 2000
}
object ThemeOptions {
var darkTheme = false
var actionBar = true
}

@ -4,7 +4,7 @@ json_list = []
def init():
global json_list
json_list = eval(requests.get("http://192.168.1.120:8000/devices_list").text)
json_list = eval(requests.get("http://192.168.1.230:8000/devices_list").text)
def get_length():

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E04C4C"
tools:context=".fragments.anotherDebugFragment">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Another 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/goFirstDegubFragmentBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<Button
android:id="@+id/generateAndSaveDataBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="Generate and save data"
app:layout_constraintEnd_toStartOf="@+id/goFirstDegubFragmentBtn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<Button
android:id="@+id/loadAndShowDataBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="16dp"
android:text="Load and Show data"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/generateAndSaveDataBtn" />
<ScrollView
android:id="@+id/scrollView4"
android:layout_width="120dp"
android:layout_height="80dp"
android:layout_marginTop="16dp"
android:background="#E66C6C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.05"
app:layout_constraintStart_toEndOf="@+id/loadAndShowDataBtn"
app:layout_constraintTop_toBottomOf="@+id/goFirstDegubFragmentBtn">
<TextView
android:id="@+id/dataContentView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="data content"
android:textAlignment="center" />
</ScrollView>
<CheckBox
android:id="@+id/wholeContentCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:shadowColor="#B4B4B4"
android:text="Whole Content"
android:textColor="#FFFFFF"
android:textColorHighlight="#FFFFFF"
android:textColorHint="#FFFFFF"
android:textColorLink="#FFFFFF"
app:layout_constraintStart_toStartOf="@+id/attributePathInput"
app:layout_constraintTop_toBottomOf="@+id/attributePathInput"
app:useMaterialThemeColors="false" />
<EditText
android:id="@+id/attributePathInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:ems="10"
android:hint="attribute path"
android:inputType="textPersonName"
app:layout_constraintStart_toStartOf="@+id/loadAndShowDataBtn"
app:layout_constraintTop_toBottomOf="@+id/loadAndShowDataBtn" />
<Button
android:id="@+id/createViewConnectionBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="8dp"
android:text="Create View Connection"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@+id/wholeContentCheckBox"
app:layout_constraintTop_toBottomOf="@+id/attributePathInput" />
<Button
android:id="@+id/stopConnectionBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="Stop Connection"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="@+id/attributePathInput"
app:layout_constraintEnd_toEndOf="@+id/createViewConnectionBtn"
app:layout_constraintStart_toEndOf="@+id/attributePathInput" />
<EditText
android:id="@+id/filePathInput"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="file path"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="@+id/attributePathInput"
app:layout_constraintStart_toStartOf="@+id/loadAndShowDataBtn"
app:layout_constraintTop_toBottomOf="@+id/loadAndShowDataBtn" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -43,10 +43,10 @@
app:layout_constraintTop_toBottomOf="@+id/getDataBtn" />
<Button
android:id="@+id/displayJsonFileBtn"
android:id="@+id/getJsonFileBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Display Json File"
android:text="Get Json File"
app:layout_constraintStart_toStartOf="@+id/idInput"
app:layout_constraintTop_toBottomOf="@+id/idInput" />
@ -59,7 +59,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/displayJsonFileBtn">
app:layout_constraintTop_toBottomOf="@+id/getJsonFileBtn">
<LinearLayout
android:layout_width="match_parent"
@ -67,11 +67,12 @@
android:orientation="vertical">
<TextView
android:id="@+id/jsonFileOutputView"
android:id="@+id/jsonFileContentView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="json output"
android:text="json content"
android:textAlignment="center"
android:textSize="18sp"
tools:layout_editor_absoluteX="254dp"
tools:layout_editor_absoluteY="95dp" />
@ -86,8 +87,80 @@
android:layout_marginLeft="24dp"
android:text="Amount of json's: 0"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/displayJsonFileBtn"
app:layout_constraintBottom_toTopOf="@+id/getJsonFileBtn"
app:layout_constraintStart_toEndOf="@+id/idInput"
app:layout_constraintTop_toBottomOf="@+id/getDataBtn" />
<Button
android:id="@+id/getAttributeContentBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Get Attribute "
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/scrollView3" />
<EditText
android:id="@+id/attributeNameInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:ems="10"
android:hint=" attribute name"
android:inputType="textPersonName"
app:layout_constraintStart_toStartOf="@+id/getAttributeContentBtn"
app:layout_constraintTop_toBottomOf="@+id/getAttributeContentBtn" />
<ScrollView
android:layout_width="380dp"
android:layout_height="80dp"
android:layout_marginTop="16dp"
android:background="#FF6C6C"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/attributeNameInput">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/attributeContentView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="attribute content"
android:textAlignment="center"
android:textSize="18sp"
android:gravity="center_horizontal" />
</LinearLayout>
</ScrollView>
<Button
android:id="@+id/clearAttributeBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="Clear Attribute"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/getAttributeContentBtn"
app:layout_constraintTop_toBottomOf="@+id/scrollView3" />
<Button
android:id="@+id/goSecondDebugFragmentBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -7,6 +7,20 @@
android:background="#F57C00"
tools:context=".fragments.settingsFragment">
<TextView
android:id="@+id/actionBarThemeSwitchText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="64dp"
android:layout_marginLeft="64dp"
android:layout_marginTop="32dp"
android:text="Action Bar"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/darkThemeSwitchText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -24,8 +38,41 @@
android:id="@+id/debugBtn"
android:layout_width="30dp"
android:layout_height="30dp"
app:srcCompat="@drawable/debug_vector_asset"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/debug_vector_asset" />
<TextView
android:id="@+id/darkThemeSwitchText"
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:textColor="#FFFFFF"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="@+id/darkThemeSwitch"
android:layout_width="50dp"
android:layout_height="21dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
app:layout_constraintBottom_toBottomOf="@+id/darkThemeSwitchText"
app:layout_constraintStart_toEndOf="@+id/darkThemeSwitchText"
app:layout_constraintTop_toTopOf="@+id/darkThemeSwitchText" />
<Switch
android:id="@+id/actionBarSwitch"
android:layout_width="50dp"
android:layout_height="21dp"
app:layout_constraintBottom_toBottomOf="@+id/actionBarThemeSwitchText"
app:layout_constraintEnd_toEndOf="@+id/darkThemeSwitch"
app:layout_constraintStart_toStartOf="@+id/darkThemeSwitch"
app:layout_constraintTop_toTopOf="@+id/actionBarThemeSwitchText" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -53,5 +53,18 @@
android:id="@+id/debugFragment"
android:name="com.example.wikispot.fragments.debugFragment"
android:label="fragment_debug"
tools:layout="@layout/fragment_debug" />
tools:layout="@layout/fragment_debug" >
<action
android:id="@+id/navigateToAnotherDebugFragment"
app:destination="@id/anotherDebugFragment" />
</fragment>
<fragment
android:id="@+id/anotherDebugFragment"
android:name="com.example.wikispot.fragments.anotherDebugFragment"
android:label="fragment_another_debug"
tools:layout="@layout/fragment_another_debug" >
<action
android:id="@+id/navigateBackToDebugFragment"
app:destination="@id/debugFragment" />
</fragment>
</navigation>

@ -1,6 +1,20 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.WikiSpot" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.WikiSpot" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<style name="Theme.WikiSpotWithActionBar" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>

@ -11,6 +11,8 @@
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:windowFullscreen">true</item>
</style>
<style name="Theme.WikiSpotWithActionBar" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
@ -26,4 +28,33 @@
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<!-- Dark themes below -->
<style name="Theme.WikiSpotDark" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#B078F4</item>
<item name="colorPrimaryVariant">#5100B3</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:windowFullscreen">true</item>
</style>
<style name="Theme.WikiSpotWithActionBarDark" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#B078F4</item>
<item name="colorPrimaryVariant">#5100B3</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
</style>
</resources>

@ -4,12 +4,10 @@ buildscript {
repositories {
google()
jcenter()
maven {url "https://chaquo.com/maven"}
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.chaquo.python:gradle:9.1.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files