diff --git a/app/WikiSpot/.idea/dictionaries/ben44.xml b/app/WikiSpot/.idea/dictionaries/ben44.xml index 99a2559..c0e6255 100644 --- a/app/WikiSpot/.idea/dictionaries/ben44.xml +++ b/app/WikiSpot/.idea/dictionaries/ben44.xml @@ -1,6 +1,7 @@ + filetype initing diff --git a/app/WikiSpot/app/build.gradle b/app/WikiSpot/app/build.gradle index 626736c..c0f702e 100644 --- a/app/WikiSpot/app/build.gradle +++ b/app/WikiSpot/app/build.gradle @@ -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' diff --git a/app/WikiSpot/app/src/main/AndroidManifest.xml b/app/WikiSpot/app/src/main/AndroidManifest.xml index 3a494d4..2230352 100644 --- a/app/WikiSpot/app/src/main/AndroidManifest.xml +++ b/app/WikiSpot/app/src/main/AndroidManifest.xml @@ -1,19 +1,21 @@ + - + diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/activities/MainActivity.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/activities/MainActivity.kt index 79a7d0b..27b0916 100644 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/activities/MainActivity.kt +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/activities/MainActivity.kt @@ -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() } } diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/activityExtentions.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/activityExtentions.kt new file mode 100644 index 0000000..c1d117f --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/activityExtentions.kt @@ -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) { + +} \ No newline at end of file diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/models_and_adapters/PlacePreviewsAdapter.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/adapters/PlacePreviewsAdapter.kt similarity index 94% rename from app/WikiSpot/app/src/main/java/com/example/wikispot/models_and_adapters/PlacePreviewsAdapter.kt rename to app/WikiSpot/app/src/main/java/com/example/wikispot/adapters/PlacePreviewsAdapter.kt index 7e3eaf9..08d694b 100644 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/models_and_adapters/PlacePreviewsAdapter.kt +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/adapters/PlacePreviewsAdapter.kt @@ -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.* diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/contextExtentions.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/contextExtentions.kt new file mode 100644 index 0000000..5084d18 --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/contextExtentions.kt @@ -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 "" +} diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/extentions.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/extentions.kt deleted file mode 100644 index 1ce3859..0000000 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/extentions.kt +++ /dev/null @@ -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 { - // 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() - - for (n in 0 until size) { - jsonList.add(n, JSONObject(pythonFile.callAttr("get_json", n).toString())) - } - - return jsonList -} \ No newline at end of file diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/anotherDebugFragment.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/anotherDebugFragment.kt new file mode 100644 index 0000000..86e38de --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/anotherDebugFragment.kt @@ -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") + } + +} \ No newline at end of file diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/debugFragment.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/debugFragment.kt index bd99a56..b458d39 100644 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/debugFragment.kt +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/debugFragment.kt @@ -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 = mutableListOf() + 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) + } } } \ No newline at end of file diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/exploreFragment.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/exploreFragment.kt index 057e6e9..1901784 100644 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/exploreFragment.kt +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/exploreFragment.kt @@ -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.* diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/settingsFragment.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/settingsFragment.kt index 1226405..fb2ed9f 100644 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/settingsFragment.kt +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/settingsFragment.kt @@ -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() + } } -} \ No newline at end of file + 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() + } +} diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/JsonManager.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/JsonManager.kt new file mode 100644 index 0000000..a6f9b49 --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/JsonManager.kt @@ -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) + } + +} diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/ServerManager.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/ServerManager.kt new file mode 100644 index 0000000..8b50b8d --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/ServerManager.kt @@ -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() + private var viewConnections = mutableListOf() + + 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) + } + } + } + + } + +} diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/SettingsSaveManager.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/SettingsSaveManager.kt new file mode 100644 index 0000000..221c1be --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/SettingsSaveManager.kt @@ -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() + } + +} diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/models_and_adapters/ExploreListModel.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/ExploreListModel.kt similarity index 96% rename from app/WikiSpot/app/src/main/java/com/example/wikispot/models_and_adapters/ExploreListModel.kt rename to app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/ExploreListModel.kt index 97763ec..7287c50 100644 --- a/app/WikiSpot/app/src/main/java/com/example/wikispot/models_and_adapters/ExploreListModel.kt +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/ExploreListModel.kt @@ -1,4 +1,4 @@ -package com.example.wikispot.models_and_adapters +package com.example.wikispot.modelsForAdapters import android.media.Image diff --git a/app/WikiSpot/app/src/main/java/com/example/wikispot/projectScopeVariables.kt b/app/WikiSpot/app/src/main/java/com/example/wikispot/projectScopeVariables.kt new file mode 100644 index 0000000..7a99e0c --- /dev/null +++ b/app/WikiSpot/app/src/main/java/com/example/wikispot/projectScopeVariables.kt @@ -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 + +} diff --git a/app/WikiSpot/app/src/main/python/server_manager.py b/app/WikiSpot/app/src/main/python/server_manager.py index dbe1a12..1a84fae 100644 --- a/app/WikiSpot/app/src/main/python/server_manager.py +++ b/app/WikiSpot/app/src/main/python/server_manager.py @@ -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(): diff --git a/app/WikiSpot/app/src/main/res/layout/fragment_another_debug.xml b/app/WikiSpot/app/src/main/res/layout/fragment_another_debug.xml new file mode 100644 index 0000000..42143cd --- /dev/null +++ b/app/WikiSpot/app/src/main/res/layout/fragment_another_debug.xml @@ -0,0 +1,135 @@ + + + + + +