Merge pull request #3 from Tucan444/Development
First working version of WikiSpot Server and app
174
README.md
@ -1,21 +1,169 @@
|
||||
# Mabasej_Team
|
||||
We are working on system, that will help tourists in cities to get information about city more easily.
|
||||
|
||||
# Hardware
|
||||
- work in progress (but probabbly we will use rpi with external antena for wifi)
|
||||
## Hardware
|
||||
- Raspberry PI (for now tested only on rpi4. Works on rpi zero too, but it will be slow if more devices are connected)
|
||||
- External/Internal WiFi antena
|
||||
|
||||
# Software
|
||||
## Software
|
||||
- python 3.9.2 compatible server with basic web interface
|
||||
- python 3.x based mobile app with help of android studio
|
||||
- Kotlin based mobile app
|
||||
|
||||
# Server
|
||||
To run server you need to install
|
||||
- hypercorn - "pip install hypercorn"
|
||||
- fastapi - "pip install fastapi"
|
||||
- requests - "pip install requests"
|
||||
- aiofiles - "pip install aiofiles"
|
||||
## Install
|
||||
Wikispot is in testing stages, but it is possible to install it using our .img file (link coming soon) based on DietPi or custom script.
|
||||
|
||||
then run by command - "hypercorn main:app --bind <IP:port>"
|
||||
To connect to another rpi you need to edit settings.json with different ID and fill heartbeat table.
|
||||
| Device | Server compatible | Instalation |
|
||||
| :-------------------- | :------------------------------------------------------------------------------------------ | :-----------: |
|
||||
| Ubuntu (I7, 16GB ram) | :heavy_check_mark: WORKING (Only server) | Manual/script |
|
||||
| RPI 4b (2GB) | :heavy_check_mark: WORKING | .img/script |
|
||||
| RPI 400 (4GB) | :grey_question: Untested. Should work. | .img/script |
|
||||
| RPI 3b+ | :grey_question: Untested. Should work. | .img/script |
|
||||
| RPI zero w | :white_check_mark: Working with fewer devices (Only server. No AP, Computer vision) | .img/script |
|
||||
| RPI 2 | :question: Untested. | :x: |
|
||||
| RPI | :question: Untested. | :x: |
|
||||
|
||||
This is not finished product
|
||||
|
||||
### Fresh istall (.img) Only RPI
|
||||
login credentials
|
||||
> login: dietpi
|
||||
|
||||
> password: WikiSpot2021
|
||||
|
||||
|
||||
requirements:
|
||||
1. WikiSpot image file (download: *soon*)
|
||||
2. MicroSd card (recommended: >=16GB, :exclamation: ALL DATA STORED ON SD CARD WILL BE FORMATED :exclamation:)
|
||||
3. BalenaEtcher (or another sd card flasher) *link:* https://www.balena.io/etcher/
|
||||
4. SD card reader
|
||||
|
||||
|
||||
Install:
|
||||
1. Download all required files (wikispot.img and balenaetcher) and install BalenaEtcher
|
||||
2. Insert SD card into computer/reader, open BalenaEtcher -> chose Flash from file -> chose downloaded wikispot.img -> Select your sd in *Select target* -> Flash!
|
||||
3. :exclamation: WINDOWS will show unformated drive. Cancel it. It is because of uncompatible format for windows :exclamation:
|
||||
4. After flashing open partition *boot* (should apear as USB), find file *dietpi.txt* and open it in text editor.
|
||||
- Accept license by changing `AUTO_SETUP_ACCEPT_LICENSE=0` to `AUTO_SETUP_ACCEPT_LICENSE=1`
|
||||
- Change name of WikiSpot `AUTO_SETUP_NET_HOSTNAME=WikiSpot-CHANGE_ME` by changing only *CHANGE_ME* or leave *CHANGE_ME* for random number name *WikiSpot-54346
|
||||
- You can set static ip address by changing `AUTO_SETUP_NET_USESTATIC=0` to `AUTO_SETUP_NET_USESTATIC=1` And entering your setting into required lines.
|
||||
- If you want to use computer vision plugin with rpi camera set `ENABLE_COMPUTER_VISION_PLUGIN=0` to `ENABLE_COMPUTER_VISION_PLUGIN=1` (*recommended only on RPI4)
|
||||
- If you want to use RPI as access point to WikiSpot change `#AUTO_SETUP_INSTALL_SOFTWARE_ID=60` to `AUTO_SETUP_INSTALL_SOFTWARE_ID=60`
|
||||
- *wifi setup in testing*
|
||||
5. :grey_exclamation:For advanced users:grey_exclamation: You can now change contens of WikiSpot server in `/boot/WikiSpot`according to an example in server filesystem
|
||||
6. Eject sd card from computer, insert it in Raspberry Pi and power it on. :bangbang:Raspberry Pi needs to be connected to intenet via Ethernet (*wifi coming soon*) othervise the setup will crash.
|
||||
7. The setup will take approximately 25-40 min (RPI 4b (2gb) and 70 mb download speed)
|
||||
8. Done you can start using WikiSpot and edit contents of WikiSpot with our app (*coming soon*)
|
||||
|
||||
|
||||
### Script install
|
||||
*coming soon*
|
||||
|
||||
|
||||
### Manual install
|
||||
*coming soon*
|
||||
|
||||
|
||||
## Server filesystem
|
||||
|
||||
```
|
||||
└── test_directory
|
||||
├── cache # files forwarded from another servers to client
|
||||
├── engine.py # engine for server (log, recovery, update)
|
||||
├── files # content of WikiSpot server
|
||||
│ └── test.jpg
|
||||
├── filesystem.json # data settings of server (name, description, files)
|
||||
├── main.py # main server file
|
||||
├── plugins # plugins file
|
||||
│ └── computer_vision # oficial WikiSpot computer vision plugin for RPI 4
|
||||
│ ├── MobileNetSSD_deploy.caffemodel
|
||||
│ ├── MobileNetSSD_deploy.prototxt
|
||||
│ └── com_vision.py
|
||||
├── run.py # start script for server
|
||||
├── settings.json # settings (log, debug, connected WikiSpots, cache size,...)
|
||||
├── system.py # update and clean script
|
||||
└── version.json # version of WikiSpot
|
||||
```
|
||||
|
||||
|
||||
### filesystem
|
||||
|
||||
```
|
||||
{
|
||||
"ID": 0, # ID of WikiSpots, Needs to be different, because network will crash
|
||||
"location": "25.997417761947318, -97.15738221291177", # Location of WikiSpot server copied from google maps
|
||||
"description": {
|
||||
"title": "WikiSpot demo", # Name of WikiSpot server (swiming pool, school, ...)
|
||||
"description_s": "This is showcase of WikiSpot", # Short description showed on web/app in list of servers
|
||||
"description_l": "This will show after opening server in app", # Long description showed after opening the server in web/app
|
||||
"photo_s": "test.jpg", # Small image showed on web/app in list of servers
|
||||
"photo_b": "test.png" # Big image showed after opening the server in web/app
|
||||
},
|
||||
"files": [ # files on server in /files that will be mediated to the web/app
|
||||
{
|
||||
"name": "test", # Name of the file, without spaces. App will change "_" to spaces
|
||||
"format": ".jpg", # Format of the file
|
||||
"description": "This is test file" # Description showed next to the file
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
To manualy add new file to server (on setup or via ssh) add file to `server_directory/files`
|
||||
and add record for file into `files` list in `filesystem.json`. :exclamation:do not forget "," after last record:exclamation:
|
||||
|
||||
```
|
||||
|
||||
{
|
||||
"name": "new_file_name",
|
||||
"format": ".txt",
|
||||
"description": "This is how you add new file"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### settings.json
|
||||
|
||||
```
|
||||
{
|
||||
"time_to_heartbeat": 20, # Time to ping of another online servers in seconds
|
||||
"time_to_heartbeat_offline": 25, # Time to ping of another offline servers in seconds
|
||||
"save_table": true, # Save connected servers to reconnect after restart
|
||||
"time_to_save": 60, # Time to save server in seconds
|
||||
"max_mess": 20, # Maximum messages stored in RAM
|
||||
"cache_size_mb": 1000, # Maximum size of cache directory in mb
|
||||
"clear_cache_on_startup": false, # Remove contents of cache on startup (slower first downloads)
|
||||
"log": { # Log settings
|
||||
"save_error": true, # Save errors into log.txt
|
||||
"print_error": true, # Print errors into console (if running as service into linux log)
|
||||
"save_warning": true, # Save warnings into log.txt
|
||||
"print_warning": true, # Print warnings into console (if running as service into linux log)
|
||||
"save_message": false, # Save messages (new server, etc. not messages from clients) into log.txt
|
||||
"print_message": true, # Print messages into console (if running as service into linux log)
|
||||
"enable_debug": false # Enable debug into console (if running as service into linux log)
|
||||
},
|
||||
"heartbeat_table": { # Saved servers
|
||||
"ID": [],
|
||||
"IP": [],
|
||||
"location": [],
|
||||
"file_system": [],
|
||||
"last_heartbeat": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you want to manually add server on first setup or via ssh fill heartbeat table like this.
|
||||
|
||||
```
|
||||
"heartbeat_table": { # Saved servers
|
||||
"ID": [1], # ID of server as integer (number)
|
||||
"IP": ["192.168.1.2"], # IP of server as string
|
||||
"location": [""], # Empty string as placeholder. location will be downloaded after first connection
|
||||
"file_system": [""], # Empty string as placeholder. filesystem will be downloaded after first connection
|
||||
"last_heartbeat": [10] # After how many seconds will server try to connect for the first time
|
||||
}
|
||||
```
|
||||
|
||||
:bangbang:If the server will be offline for long time (heartbeat + offline heartbeat) it will be removed from heartbeat table. If the save function is disabled server will trying to connect after restart:bangbang:
|
||||
|
||||
|
||||
|
||||
*This is not finished product*
|
||||
|
123
app/WikiSpot/.idea/codeStyles/Project.xml
Normal file
@ -0,0 +1,123 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_ATTRIBUTE />
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
app/WikiSpot/.idea/codeStyles/codeStyleConfig.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
10
app/WikiSpot/.idea/dictionaries/ben44.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="ben44">
|
||||
<words>
|
||||
<w>backstack</w>
|
||||
<w>datatype</w>
|
||||
<w>filetype</w>
|
||||
<w>initing</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
10
app/WikiSpot/.idea/runConfigurations.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,7 +1,8 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'com.chaquo.python'
|
||||
id 'kotlin-android-extensions'
|
||||
id 'androidx.navigation.safeargs.kotlin'
|
||||
}
|
||||
|
||||
android {
|
||||
@ -10,28 +11,14 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.wikispot"
|
||||
minSdkVersion 16
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
python {
|
||||
srcDirs = ["src/main/python"]
|
||||
}
|
||||
}
|
||||
}
|
||||
python {
|
||||
buildPython "/urs/local/bin/python3"
|
||||
buildPython "python3"
|
||||
}
|
||||
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
@ -49,12 +36,11 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
@ -64,7 +50,14 @@ 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'
|
||||
implementation 'com.google.android.gms:play-services-maps:17.0.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
|
||||
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'
|
||||
}
|
24
app/WikiSpot/app/src/debug/res/values/google_maps_api.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<resources>
|
||||
<!--
|
||||
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:
|
||||
|
||||
https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=65:0D:80:30:57:9C:7B:EB:35:6F:CC:61:21:5D:C1:2A:73:E1:D8:20%3Bcom.example.wikispot
|
||||
|
||||
You can also add your credentials to an existing key, using these values:
|
||||
|
||||
Package name:
|
||||
com.example.wikispot
|
||||
|
||||
SHA-1 certificate fingerprint:
|
||||
65:0D:80:30:57:9C:7B:EB:35:6F:CC:61:21:5D:C1:2A:73:E1:D8:20
|
||||
|
||||
Alternatively, follow the directions here:
|
||||
https://developers.google.com/maps/documentation/android/start#get-key
|
||||
|
||||
Once you have your key (it starts with "AIza"), replace the "google_maps_key"
|
||||
string in this file.
|
||||
-->
|
||||
<string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">AIzaSyAixBio8FevppLsncIkFUQarx2kUB-0dW0</string>
|
||||
</resources>
|
@ -2,15 +2,40 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.wikispot">
|
||||
|
||||
<!--
|
||||
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
|
||||
Google Maps Android API v2, but you must specify either coarse or fine
|
||||
location permissions for the "MyLocation" functionality.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<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:theme="@style/Theme.WikiSpotWithActionBar">
|
||||
<activity android:name=".activities.MainActivity"
|
||||
android:launchMode="singleTask">
|
||||
android:theme="@style/Theme.WikiSpot"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<!--
|
||||
The API key for Google Maps-based APIs is defined as a string resource.
|
||||
(See the file "res/values/google_maps_api.xml").
|
||||
Note that the API key is linked to the encryption key used to sign the APK.
|
||||
You need a different API key for each encryption key, including the release key that is used to
|
||||
sign the APK for publishing.
|
||||
You can define the keys for the debug and release targets in src/debug/ and src/release/.
|
||||
-->
|
||||
<meta-data
|
||||
android:name="com.google.android.geo.API_KEY"
|
||||
android:value="@string/google_maps_key" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.MainActivity">
|
||||
<!--android:screenOrientation="portrait"> -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
BIN
app/WikiSpot/app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 144 KiB |
@ -1,3 +0,0 @@
|
||||
package com.example.wikispot
|
||||
|
||||
object Constants {}
|
@ -0,0 +1,117 @@
|
||||
package com.example.wikispot
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.nio.channels.FileChannel
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
|
||||
// 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.moreColors) {
|
||||
return R.style.Theme_WikiSpotDark
|
||||
} else {
|
||||
return R.style.Theme_WikiSpotDark_
|
||||
}
|
||||
} else {
|
||||
if (!ThemeOptions.moreColors) {
|
||||
return R.style.Theme_WikiSpot
|
||||
} else {
|
||||
return R.style.Theme_WikiSpot_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ""
|
||||
}
|
||||
|
||||
// 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() {
|
||||
val builder = AlertDialog.Builder(this)
|
||||
builder.setTitle("Confirm")
|
||||
builder.setMessage("Do you want to quit the application?")
|
||||
builder.setPositiveButton("Yes") { _, _ -> finish()}
|
||||
builder.setNegativeButton("No") { _, _ -> }
|
||||
builder.show()
|
||||
}
|
@ -1,31 +1,195 @@
|
||||
package com.example.wikispot.activities
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import android.util.DisplayMetrics
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import com.example.wikispot.R
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.wikispot.*
|
||||
import com.example.wikispot.adapters.FileViewsAdapter
|
||||
import com.example.wikispot.adapters.LabeledValuesAdapter
|
||||
import com.example.wikispot.adapters.PlacePreviewsAdapter
|
||||
import com.example.wikispot.fragments.*
|
||||
import com.example.wikispot.modelClasses.JsonManager
|
||||
import com.example.wikispot.modelClasses.JsonManagerLite
|
||||
import com.example.wikispot.modelClasses.SettingsSaveManager
|
||||
import com.example.wikispot.modelsForAdapters.*
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_explore.*
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
import kotlinx.android.synthetic.main.fragment_info.*
|
||||
import kotlinx.android.synthetic.main.fragment_info.view.*
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onBackPressed() {
|
||||
val builder = AlertDialog.Builder(this)
|
||||
builder.setTitle("Confirm")
|
||||
builder.setMessage("Do you want to quit the application?")
|
||||
builder.setPositiveButton("Yes") {_, _ -> finish()}
|
||||
builder.setNegativeButton("No") {_, _ -> }
|
||||
builder.show()
|
||||
|
||||
try {
|
||||
when (val currentlyShownFragment = mainFragmentHost.childFragmentManager.fragments[0]) {
|
||||
is chatFragment -> {
|
||||
askToQuit()
|
||||
}
|
||||
is exploreFragment -> {
|
||||
askToQuit()
|
||||
}
|
||||
is homeFragment -> {
|
||||
askToQuit()
|
||||
}
|
||||
is mapFragment -> {
|
||||
askToQuit()
|
||||
}
|
||||
is settingsFragment -> {
|
||||
askToQuit()
|
||||
}
|
||||
is infoFragment -> {
|
||||
when (CustomBackstackVariables.infoFragmentBackDestination) {
|
||||
"exploreFragment" -> { currentlyShownFragment.goExploreFragment() }
|
||||
"mapFragment" -> {currentlyShownFragment.goMapFragment()}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println(e) }
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
doPreparations()
|
||||
loadSettings()
|
||||
setTheme(getThemeId())
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
val navController = findNavController(R.id.mainFragmentHost)
|
||||
val bottomNavView = findViewById<BottomNavigationView>(R.id.mainBottomNavigationView)
|
||||
mainBottomNavigationView.setupWithNavController(navController)
|
||||
|
||||
bottomNavView.setupWithNavController(navController)
|
||||
handleExtras()
|
||||
}
|
||||
|
||||
private fun doPreparations() {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
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() {
|
||||
super.onResume()
|
||||
// server communication
|
||||
|
||||
connectExploreFragmentAdapterModel()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
PlaceSupplier.saveToCache(this)
|
||||
ServerManagement.serverManager.deleteConnection("exploreListConnection")
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
"debugFragment" -> {
|
||||
StartDirections.settingsFragmentStartDirection = "debugFragment"
|
||||
mainBottomNavigationView.selectedItemId = R.id.settingsFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadSettings() {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
val settingsSaveManager = SettingsSaveManager(this)
|
||||
settingsSaveManager.loadSettings()
|
||||
}
|
||||
|
||||
private fun connectExploreFragmentAdapterModel () {
|
||||
// loading from cache
|
||||
PlaceSupplier.loadFromCache(this)
|
||||
|
||||
// connecting to server
|
||||
val dataReceiver: (String) -> Unit = { data: String ->
|
||||
val json = JsonManager(this, data)
|
||||
|
||||
PlaceSupplier.controlJson = JsonManagerLite(data)
|
||||
|
||||
for (i in 1 until json.getLengthOfJsonArray()) {
|
||||
|
||||
json.getJsonObject(i)
|
||||
val id = json.getAttributeContent("ID").toInt()
|
||||
val location = json.getAttributeContent("location")
|
||||
json.getAttributeContent("description")
|
||||
val title = json.getAttributeContent("title")
|
||||
val shortDescription = json.getAttributeContent("description_s")
|
||||
val place = PlacePreview(title, shortDescription, location, null, id)
|
||||
|
||||
if (!PlaceSupplier.checkIfContains(place)) {
|
||||
|
||||
val imageReceiver: (Bitmap) -> Unit = { bitmap: Bitmap ->
|
||||
place.img = bitmap
|
||||
}
|
||||
|
||||
ServerManagement.serverManager.getImage(imageReceiver, id, json.getAttributeContentByPath("description/photo_s"), 3)
|
||||
|
||||
PlaceSupplier.appendPlace(place)
|
||||
} else {
|
||||
val containingPlace = PlaceSupplier.getContainingInstance(place)
|
||||
if ((containingPlace != null) and (containingPlace?.img == null)) {
|
||||
val imageReceiver: (Bitmap) -> Unit = { bitmap: Bitmap ->
|
||||
containingPlace?.img = bitmap
|
||||
}
|
||||
|
||||
ServerManagement.serverManager.getImage(imageReceiver, id, json.getAttributeContentByPath("description/photo_s"), 3)
|
||||
}
|
||||
|
||||
// checking if location wasn't changed
|
||||
if ((containingPlace != null) and (containingPlace?.location != location)) {
|
||||
containingPlace?.location = location
|
||||
|
||||
try {
|
||||
mainFragmentHost.childFragmentManager.fragments[0]?.let {
|
||||
if (it is exploreFragment) {
|
||||
it.explore_recycler_view.post {
|
||||
val layoutManager = LinearLayoutManager(it.requireContext())
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
it.explore_recycler_view.layoutManager = layoutManager
|
||||
|
||||
val adapter = PlacePreviewsAdapter(it.requireContext(), PlaceSupplier.places)
|
||||
it.explore_recycler_view.adapter = adapter
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] e4 that i couldnt fix si try catch Exception: $e") }
|
||||
}
|
||||
}
|
||||
|
||||
json.clearSelectedAttribute()
|
||||
}
|
||||
}
|
||||
|
||||
ServerManagement.serverManager.addReceiverConnection(dataReceiver, this, "exploreListConnection", 0, "", "GET_WHOLE_ARRAY", 10000)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package com.example.wikispot.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.wikispot.GeneralVariables
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.modelsForAdapters.Message
|
||||
import kotlinx.android.synthetic.main.message.view.*
|
||||
|
||||
|
||||
class ChatMessagesAdapter(private val context: Context, private val messages: Array<Message?>) : RecyclerView.Adapter<ChatMessagesAdapter.MyViewHolder>() {
|
||||
|
||||
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
|
||||
|
||||
var message: Message? = null
|
||||
var pos: Int = 0
|
||||
|
||||
fun setData(message: Message?, pos: Int) {
|
||||
message?.let {
|
||||
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_VIEW_END
|
||||
itemView.message_content_text.textAlignment = View.TEXT_ALIGNMENT_VIEW_END
|
||||
}
|
||||
}
|
||||
|
||||
this.message = message
|
||||
this.pos = pos
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||
val message = messages[position]
|
||||
holder.setIsRecyclable(false)
|
||||
holder.setData(message, position)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.message, parent, false)
|
||||
return MyViewHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return messages.size
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
package com.example.wikispot.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.core.view.setPadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.ServerManagement
|
||||
import com.example.wikispot.modelsForAdapters.FileView
|
||||
import kotlinx.android.synthetic.main.file_view.view.*
|
||||
|
||||
|
||||
class FileViewsAdapter(private val context: Context, private val fileViews: Array<FileView?>) : RecyclerView.Adapter<FileViewsAdapter.MyViewHolder>() {
|
||||
|
||||
private val rotateOpen: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.open_rotation_anim) }
|
||||
private val rotateClose: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.close_rotation_anim) }
|
||||
private val fadeIn: Animation by lazy {AnimationUtils.loadAnimation(context, R.anim.fade_in) }
|
||||
private val fadeOut: Animation by lazy {AnimationUtils.loadAnimation(context, R.anim.fade_out) }
|
||||
|
||||
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
|
||||
|
||||
var fileView: FileView? = null
|
||||
var pos: Int = 0
|
||||
var textInfo: String? = null
|
||||
var imgInfo: String? = null
|
||||
var pdfUrl: String? = null
|
||||
var generalUrl: String? = null
|
||||
var opened = false
|
||||
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
if (!opened) {
|
||||
itemView.downloadFileBtn.visibility = View.VISIBLE
|
||||
itemView.downloadFileBtn.startAnimation(fadeIn)
|
||||
if (generalUrl == null) {
|
||||
itemView.showFileBtn.startAnimation(rotateOpen)
|
||||
}
|
||||
|
||||
fileView?.let {
|
||||
textInfo?.let {
|
||||
itemView.textContent.textSize = 18F
|
||||
itemView.textContent.setPadding(32)
|
||||
val dataReceiver: (String) -> Unit = { data: String ->
|
||||
itemView.textContent.post {
|
||||
itemView.textContent.text = data
|
||||
}
|
||||
}
|
||||
|
||||
val textInformation = textInfo!!.split("|||||")
|
||||
|
||||
ServerManagement.serverManager.getData(dataReceiver, itemView.context, textInformation[0].toInt(), textInformation[1])
|
||||
}
|
||||
imgInfo?.let {
|
||||
itemView.imageContent.visibility = View.VISIBLE
|
||||
val imageReceiver2: (Bitmap) -> Unit = { bitmap: Bitmap ->
|
||||
itemView.imageContent.post {
|
||||
itemView.imageContent.setImageBitmap(bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
val imgInformation = imgInfo!!.split("|||||")
|
||||
|
||||
ServerManagement.serverManager.getImage(imageReceiver2, imgInformation[0].toInt(), imgInformation[1])
|
||||
}
|
||||
pdfUrl?.let {
|
||||
itemView.pdfContent.visibility = View.VISIBLE
|
||||
ServerManagement.serverManager.loadPdfView(itemView.pdfContent, pdfUrl!!, true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (generalUrl == null) {
|
||||
itemView.showFileBtn.startAnimation(rotateClose)
|
||||
}
|
||||
val downloadBtnVanishActionThread = Thread(DownloadBtnVanishAction())
|
||||
downloadBtnVanishActionThread.start()
|
||||
|
||||
itemView.textContent.textSize = 0F
|
||||
itemView.textContent.setPadding(0)
|
||||
|
||||
itemView.imageContent.visibility = View.GONE
|
||||
itemView.pdfContent.visibility = View.GONE
|
||||
}
|
||||
|
||||
opened = !opened
|
||||
}
|
||||
|
||||
itemView.downloadFileBtn.setOnClickListener {
|
||||
textInfo?.let {
|
||||
val textInformation = textInfo!!.split("|||||")
|
||||
val url = "${ServerManagement.baseUrl}files/${textInformation[0]}/${textInformation[1]}"
|
||||
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
startActivity(context, browserIntent, null)
|
||||
}
|
||||
|
||||
imgInfo?.let {
|
||||
val imgInformation = imgInfo!!.split("|||||")
|
||||
val url = "${ServerManagement.baseUrl}files/${imgInformation[0]}/${imgInformation[1]}"
|
||||
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
startActivity(context, browserIntent, null)
|
||||
}
|
||||
|
||||
pdfUrl?.let {
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(pdfUrl))
|
||||
startActivity(context, browserIntent, null)
|
||||
}
|
||||
|
||||
generalUrl?.let {
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(generalUrl))
|
||||
startActivity(context, browserIntent, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setData(fileView: FileView?, pos: Int) {
|
||||
fileView?.let {
|
||||
fileView.textInfo?.let {
|
||||
textInfo = it
|
||||
}
|
||||
fileView.imgInfo?.let {
|
||||
imgInfo = it
|
||||
}
|
||||
fileView.pdfUrl?.let {
|
||||
pdfUrl = it
|
||||
}
|
||||
fileView.generalUrl?.let {
|
||||
generalUrl = it
|
||||
itemView.showFileBtn.visibility = View.INVISIBLE
|
||||
// setting new margins
|
||||
|
||||
var params = itemView.downloadFileBtn.layoutParams as ConstraintLayout.LayoutParams
|
||||
params.marginEnd = 24
|
||||
itemView.downloadFileBtn.layoutParams = params
|
||||
|
||||
params = itemView.showFileBtn.layoutParams as ConstraintLayout.LayoutParams
|
||||
params.marginEnd = 0
|
||||
itemView.showFileBtn.layoutParams = params
|
||||
|
||||
}
|
||||
|
||||
itemView.filenameText.text = fileView.filename.replace("_", " ")
|
||||
itemView.fileDescription.text = fileView.fileDescription
|
||||
}
|
||||
|
||||
this.fileView = fileView
|
||||
this.pos = pos
|
||||
}
|
||||
|
||||
inner class DownloadBtnVanishAction: Runnable {
|
||||
override fun run() {
|
||||
|
||||
itemView.post {
|
||||
itemView.downloadFileBtn.startAnimation(fadeOut)
|
||||
}
|
||||
|
||||
Thread.sleep(600)
|
||||
|
||||
itemView.post {
|
||||
itemView.downloadFileBtn.clearAnimation()
|
||||
itemView.downloadFileBtn.visibility = View.GONE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||
val fileView = fileViews[position]
|
||||
holder.setData(fileView, position)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.file_view, parent, false)
|
||||
return MyViewHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return fileViews.size
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.example.wikispot.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.wikispot.CustomBackstackVariables
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.ServerManagement
|
||||
import com.example.wikispot.fragments.exploreFragmentDirections
|
||||
import com.example.wikispot.modelsForAdapters.PlacePreview
|
||||
import com.example.wikispot.showToast
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import kotlinx.android.synthetic.main.explore_list_item.view.*
|
||||
|
||||
|
||||
class PlacePreviewsAdapter(private val context: Context, private val placePreviews: Array<PlacePreview?>) : RecyclerView.Adapter<PlacePreviewsAdapter.MyViewHolder>() {
|
||||
|
||||
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
|
||||
|
||||
var currentPlacePreview: PlacePreview? = null
|
||||
var pos: Int = 0
|
||||
var location: LatLng? = null
|
||||
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
CustomBackstackVariables.infoFragmentBackDestination = "exploreFragment"
|
||||
ServerManagement.selectedServerId = currentPlacePreview?.id!!
|
||||
val action = exploreFragmentDirections.navigateToInfoFragment(true)
|
||||
Navigation.findNavController(it).navigate(action)
|
||||
}
|
||||
|
||||
itemView.item_location_img.setOnClickListener {
|
||||
if (location != null) {
|
||||
val action = exploreFragmentDirections.navigateToMapFragment(location!!)
|
||||
Navigation.findNavController(it).navigate(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setData(placePreview: PlacePreview?, pos: Int) {
|
||||
placePreview?.let {
|
||||
itemView.item_title.text = placePreview.title
|
||||
itemView.item_description.text = placePreview.description
|
||||
|
||||
try {
|
||||
val coordinates = placePreview.location!!.split(",")
|
||||
location = LatLng(coordinates[0].toDouble(), coordinates[1].toDouble())
|
||||
} catch (e: Throwable) {
|
||||
println("[debug] Failed getting coordinates in ${placePreview.title}, explore fragment list. Exception: $e")}
|
||||
|
||||
|
||||
placePreview.img?.let {
|
||||
itemView.item_img.setImageBitmap(placePreview.img)
|
||||
}
|
||||
}
|
||||
|
||||
this.currentPlacePreview = placePreview
|
||||
this.pos = pos
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||
val placePreview = placePreviews[position]
|
||||
holder.setData(placePreview, position)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.explore_list_item, parent, false)
|
||||
return MyViewHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return placePreviews.size
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.example.wikispot.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.example.wikispot.GeneralVariables
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.modelsForAdapters.LabeledValue
|
||||
import kotlinx.android.synthetic.main.labeled_value_item.view.*
|
||||
|
||||
|
||||
class LabeledValuesAdapter(private val context: Context, private val labeledValues: Array<LabeledValue?>) : RecyclerView.Adapter<LabeledValuesAdapter.MyViewHolder>() {
|
||||
|
||||
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
|
||||
|
||||
var currentLabeledValue: LabeledValue? = null
|
||||
var pos: Int = 0
|
||||
|
||||
fun setData(labeledValue: LabeledValue?, pos: Int) {
|
||||
labeledValue?.let {
|
||||
if (labeledValue.label.startsWith(GeneralVariables.translatePrefix)) {
|
||||
itemView.label.text = context.resources.getString(context.resources.getIdentifier(labeledValue.label.slice(GeneralVariables.translatePrefix.length until labeledValue.label.length),
|
||||
"string", context.packageName))
|
||||
} else {
|
||||
itemView.label.text = labeledValue.label
|
||||
}
|
||||
|
||||
if (labeledValue.value.startsWith(GeneralVariables.translatePrefix)) {
|
||||
itemView.value.text = context.resources.getString(context.resources.getIdentifier(labeledValue.value.slice(GeneralVariables.translatePrefix.length until labeledValue.value.length),
|
||||
"string", context.packageName))
|
||||
} else {
|
||||
itemView.value.text = labeledValue.value
|
||||
}
|
||||
}
|
||||
|
||||
this.currentLabeledValue = labeledValue
|
||||
this.pos = pos
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||
val labeledValue = labeledValues[position]
|
||||
holder.setData(labeledValue, position)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.labeled_value_item, parent, false)
|
||||
return MyViewHolder(view)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return labeledValues.size
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.example.wikispot
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
||||
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()
|
||||
}
|
70
app/WikiSpot/app/src/main/java/com/example/wikispot/fragments/anotherDebugFragment.kt
Normal file
@ -0,0 +1,70 @@
|
||||
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 filePath = filePathInput.text.toString()
|
||||
|
||||
ServerManagement.serverManager.deleteConnection("debug", "view")
|
||||
ServerManagement.serverManager.addViewConnection(requireContext(), dataContentView, "debug",0, filePath, attributePath)
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,204 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.example.wikispot.R
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.wikispot.*
|
||||
import com.example.wikispot.adapters.ChatMessagesAdapter
|
||||
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 okhttp3.*
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
class chatFragment : Fragment(R.layout.fragment_chat) {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
updateRecyclerView()
|
||||
|
||||
writeBar.setOnClickListener {
|
||||
val scrollDownThread = Thread(ScrollDown(300))
|
||||
scrollDownThread.start()
|
||||
}
|
||||
userMessageText.setOnClickListener {
|
||||
val scrollDownThread = Thread(ScrollDown(300))
|
||||
scrollDownThread.start()
|
||||
}
|
||||
userMessageText.setOnFocusChangeListener { _, _ ->
|
||||
val scrollDownThread = Thread(ScrollDown(300))
|
||||
scrollDownThread.start()
|
||||
}
|
||||
|
||||
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()
|
||||
loadIdFromCache()
|
||||
|
||||
val dataReceiver: (String) -> Unit = { data: String ->
|
||||
|
||||
try {
|
||||
val json = JsonManager(requireContext(), data, "JSONObject")
|
||||
|
||||
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)}"
|
||||
|
||||
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()
|
||||
|
||||
MessagesSupplier.clearWaitingMessages()
|
||||
|
||||
for (i in 0 until length) {
|
||||
val jsonOfMessage = JsonManager(requireContext(), json.getAttributeContentByPath("data/$i"), "JSONObject")
|
||||
val message = Message(jsonOfMessage.getAttributeContent("sender"),
|
||||
jsonOfMessage.getAttributeContent("message"),
|
||||
jsonOfMessage.getAttributeContent("timestamp"))
|
||||
|
||||
if (!MessagesSupplier.checkIfContains(message)) {
|
||||
MessagesSupplier.appendMessage(message)
|
||||
updateRecyclerView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug][chat fragment] Exception: $e") }
|
||||
}
|
||||
|
||||
ServerManagement.serverManager.addChatConnection(dataReceiver, requireContext(), "chatConnection")
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
saveIdToCache()
|
||||
|
||||
ServerManagement.serverManager.deleteConnection("chatConnection")
|
||||
}
|
||||
|
||||
private fun updateRecyclerView() {
|
||||
|
||||
try {
|
||||
chat_messages_recycler_view.post {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
chat_messages_recycler_view.layoutManager = layoutManager
|
||||
|
||||
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 ScrollDown(private val after: Long): Runnable {
|
||||
override fun run() {
|
||||
Thread.sleep(after)
|
||||
try {
|
||||
chat_messages_recycler_view.post {
|
||||
chat_messages_recycler_view.scrollToPosition(MessagesSupplier.messages.size - 1)
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] e6 Exception: $e") }
|
||||
}
|
||||
}
|
||||
|
||||
inner class MessagePost(private val message: Message): Runnable {
|
||||
override fun run() {
|
||||
|
||||
val url = "${ServerManagement.baseUrl}messages/post"
|
||||
|
||||
val json: MediaType? = "application/json; charset=utf-8".toMediaTypeOrNull()
|
||||
|
||||
val body:RequestBody = RequestBody.create(json, JSONObject()
|
||||
.put("m_sender", message.senderId)
|
||||
.put("message", message.content).toString())
|
||||
|
||||
val request: Request = Request.Builder()
|
||||
.url(url)
|
||||
.post(body)
|
||||
.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 loadIdFromCache() {
|
||||
val id = requireContext().getStringFromSharedPreferences("id")
|
||||
if (id != "") {
|
||||
GeneralVariables.id = id
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun saveIdToCache() {
|
||||
GeneralVariables.id?.let {
|
||||
requireContext().saveString("id", GeneralVariables.id!!)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import com.example.wikispot.*
|
||||
import com.example.wikispot.activities.MainActivity
|
||||
import com.example.wikispot.modelsForAdapters.MessagesSupplier
|
||||
import kotlinx.android.synthetic.main.fragment_debug.*
|
||||
|
||||
|
||||
class debugFragment : Fragment(R.layout.fragment_debug) {
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
goSecondDebugFragmentBtn.setOnClickListener {
|
||||
Navigation.findNavController(it).navigate(R.id.navigateToAnotherDebugFragment)
|
||||
}
|
||||
|
||||
getNumberOfSentRequestsBtn.setOnClickListener {
|
||||
outputText.text = ServerManagement.totalNumberOfRequestsSent.toString()
|
||||
}
|
||||
|
||||
clearServerConnectionsBtn.setOnClickListener {
|
||||
ServerManagement.serverManager.clearConnections()
|
||||
}
|
||||
|
||||
editTextIp.setText(ServerManagement.baseUrl)
|
||||
|
||||
changeUrlBtn.setOnClickListener {
|
||||
ServerManagement.baseUrl = editTextIp.text.toString()
|
||||
requireContext().saveString("baseUrlSave", editTextIp.text.toString())
|
||||
restartAppPartially()
|
||||
}
|
||||
|
||||
restartAppPartiallyBtn.setOnClickListener {
|
||||
restartAppPartially()
|
||||
}
|
||||
|
||||
closeAppBtn.setOnClickListener {
|
||||
activity?.finish()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun restartAppPartially() {
|
||||
val intent = Intent(context?.applicationContext, MainActivity::class.java)
|
||||
|
||||
intent.putExtra(IntentsKeys.startFragment, "debugFragment")
|
||||
|
||||
ServerManagement.serverManager.clearConnections()
|
||||
MessagesSupplier.wipeData()
|
||||
GeneralVariables.id = null
|
||||
|
||||
startActivity(intent)
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
@ -1,8 +1,36 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.wikispot.GeneralVariables
|
||||
import com.example.wikispot.IntentsKeys
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.ServerManagement
|
||||
import com.example.wikispot.activities.MainActivity
|
||||
import com.example.wikispot.adapters.PlacePreviewsAdapter
|
||||
import com.example.wikispot.modelsForAdapters.PlaceSupplier
|
||||
import kotlinx.android.synthetic.main.fragment_explore.*
|
||||
|
||||
|
||||
class exploreFragment : Fragment(R.layout.fragment_explore) {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupRecyclerView()
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
explore_recycler_view.layoutManager = layoutManager
|
||||
|
||||
val adapter = context?.let { PlacePreviewsAdapter(it, PlaceSupplier.places) }
|
||||
explore_recycler_view.adapter = adapter
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,251 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.wikispot.GeneralVariables
|
||||
import com.example.wikispot.MapManagement
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.ServerManagement
|
||||
import com.example.wikispot.adapters.FileViewsAdapter
|
||||
import com.example.wikispot.adapters.LabeledValuesAdapter
|
||||
import com.example.wikispot.modelClasses.JsonManager
|
||||
import com.example.wikispot.modelClasses.JsonManagerLite
|
||||
import com.example.wikispot.modelsForAdapters.FileView
|
||||
import com.example.wikispot.modelsForAdapters.FileViewsSupplier
|
||||
import com.example.wikispot.modelsForAdapters.LabeledValue
|
||||
import com.example.wikispot.modelsForAdapters.LabeledValuesSupplier
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
import kotlinx.android.synthetic.main.fragment_info.*
|
||||
import kotlinx.android.synthetic.main.fragment_info.view.*
|
||||
|
||||
|
||||
class homeFragment : Fragment(R.layout.fragment_home) {
|
||||
|
||||
var infoFragmentLoadedIn = false
|
||||
|
||||
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() {
|
||||
super.onResume()
|
||||
|
||||
// connecting to server
|
||||
|
||||
val serverConnectorThread = Thread(ServerConnector())
|
||||
serverConnectorThread.start()
|
||||
|
||||
val dataReceiver0: (String) -> Unit = { data: String ->
|
||||
try {
|
||||
val json = JsonManager(requireContext(), data)
|
||||
|
||||
json.findJsonObjectByAttribute("ID", json.getAttributeContent("connected_id"))
|
||||
|
||||
if (!infoFragmentLoadedIn) {
|
||||
|
||||
infoFragmentLoadedIn = true
|
||||
|
||||
val phoneNumberLoaded = json.getAttributeContentByPath("description/phone_number")
|
||||
if (phoneNumberLoaded != GeneralVariables.variableMissingKeyword) {
|
||||
GeneralVariables.phoneNumber = phoneNumberLoaded.toInt()
|
||||
}
|
||||
|
||||
val emailLoaded = json.getAttributeContentByPath("description/email")
|
||||
if (emailLoaded != GeneralVariables.variableMissingKeyword) {
|
||||
GeneralVariables.email = emailLoaded
|
||||
}
|
||||
|
||||
homeFragmentInnerFragment.post {
|
||||
homeFragmentInnerFragment?.let { fragment ->
|
||||
val title = json.getAttributeContentByPath("description/title")
|
||||
val description = json.getAttributeContentByPath("description/description_l")
|
||||
|
||||
if (title != GeneralVariables.variableMissingKeyword) {
|
||||
fragment.mainTitle.text = title
|
||||
}
|
||||
|
||||
if (description != GeneralVariables.variableMissingKeyword) {
|
||||
fragment.mainDescription.text = description
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val imageReceiver: (Bitmap) -> Unit = { bitmap: Bitmap ->
|
||||
homeFragmentInnerFragment?.let {
|
||||
homeFragmentInnerFragment.post {
|
||||
try {
|
||||
homeFragmentInnerFragment.mainImage.setImageBitmap(bitmap)
|
||||
} catch (e: Throwable) { println("[debug] e7 Exception: $e") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerManagement.serverManager.getImage(imageReceiver, json.getAttributeContent("ID").toInt(),
|
||||
json.getAttributeContentByPath("description/photo_b"), 3)
|
||||
|
||||
}
|
||||
} catch (e: Throwable) { println(e) }
|
||||
}
|
||||
|
||||
val dataReceiver1: (String) -> Unit = {connectedId: String ->
|
||||
ServerManagement.connectedServerId = connectedId.toInt()
|
||||
}
|
||||
|
||||
ServerManagement.serverManager.getData(dataReceiver0, requireContext(), 0, "", "GET_WHOLE_ARRAY", 4)
|
||||
ServerManagement.serverManager.getData(dataReceiver1, requireContext(), 0, "", "connected_id", 3)
|
||||
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
ServerManagement.serverManager.deleteConnection("sensorsConnection")
|
||||
ServerManagement.serverManager.deleteConnection("mapConnection")
|
||||
ServerManagement.serverManager.deleteConnection("fileViewsConnection")
|
||||
saveCache()
|
||||
}
|
||||
|
||||
private fun tryConnectingToServer() {
|
||||
ServerManagement.connectedServerId?.let{ connectedServerId: Int ->
|
||||
context?.let {
|
||||
val dataReceiver1: (String) -> Unit = { data1: String ->
|
||||
|
||||
try {
|
||||
val json = JsonManager(requireContext(), data1, "JSONObject")
|
||||
val names = json.currentJsonObject!!.names()
|
||||
|
||||
names?.let {
|
||||
LabeledValuesSupplier.wipeData()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
labeled_values_recycler_view.post {
|
||||
val layoutManager = LinearLayoutManager(requireContext())
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
labeled_values_recycler_view.layoutManager = layoutManager
|
||||
|
||||
val adapter = LabeledValuesAdapter(requireContext(), LabeledValuesSupplier.labeledValues)
|
||||
labeled_values_recycler_view.adapter = adapter
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] Exception in main activity, sensors connection : $e") }
|
||||
|
||||
}
|
||||
|
||||
if (!ServerManagement.serverManager.checkIfConnectionAlreadyExists("sensorsConnection")){
|
||||
ServerManagement.serverManager.addReceiverConnection(dataReceiver1, requireContext(), "sensorsConnection", connectedServerId, ServerManagement.sensors_keyword)
|
||||
}
|
||||
|
||||
// getting other needed information
|
||||
val dataReceiver2: (String) -> Unit = {data1: String ->
|
||||
context?.let {
|
||||
var json = JsonManager(requireContext(), data1)
|
||||
json = JsonManager(requireContext(), json.findJsonObjectByAttribute("ID", connectedServerId), "JSONObject") // todo doesnt return correct result
|
||||
val positionsList = json.getAttributeContent("location").split(",")
|
||||
MapManagement.connectedServerPosition = LatLng(positionsList[0].toDouble(), positionsList[1].toDouble())
|
||||
}
|
||||
}
|
||||
|
||||
if (!ServerManagement.serverManager.checkIfConnectionAlreadyExists("mapConnection")){
|
||||
ServerManagement.serverManager.addReceiverConnection(dataReceiver2, requireContext(), "mapConnection", connectedServerId, "", "GET_WHOLE_ARRAY")
|
||||
}
|
||||
|
||||
val dataReceiver3: (String) -> Unit = { data1: String ->
|
||||
|
||||
fun updateFileViewsRecyclerView(fragment: Fragment) {
|
||||
try {
|
||||
fragment.context?.let {
|
||||
fragment.homeFragmentInnerFragment?.let {
|
||||
it.file_views_recycler_view.post {
|
||||
val layoutManager = LinearLayoutManager(fragment.requireContext())
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
it.file_views_recycler_view.layoutManager = layoutManager
|
||||
|
||||
val adapter = FileViewsAdapter(fragment.requireContext(), FileViewsSupplier.fileViews)
|
||||
it.file_views_recycler_view.adapter = adapter
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] e1 that i couldnt fix so try catch Exception: $e") }
|
||||
}
|
||||
|
||||
try {
|
||||
val json = JsonManager(requireContext(), data1)
|
||||
json.findJsonObjectByAttribute("ID", connectedServerId)
|
||||
|
||||
json.getAttributeContent("files")
|
||||
|
||||
for (n in 0 until json.currentJsonAttribute1!!.length()) {
|
||||
val fileInfo = JsonManagerLite(json.getAttributeContentByPath("files/$n"), "JSONObject")
|
||||
val filetype = fileInfo.getAttributeContentByPath("format").split(".")[1]
|
||||
val filename = fileInfo.getAttributeContentByPath("name")
|
||||
val fileDescription = fileInfo.getAttributeContentByPath("description")
|
||||
|
||||
// handling text
|
||||
if ("txt json".contains(filetype)) {
|
||||
val fileView = FileView(filetype, filename, fileDescription, "$connectedServerId|||||$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView(this)
|
||||
}
|
||||
}
|
||||
|
||||
// handling images
|
||||
if ("jpg png".contains(filetype)) {
|
||||
val fileView = FileView(filetype, filename, fileDescription, null, "$connectedServerId|||||$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView(this)
|
||||
}
|
||||
}
|
||||
|
||||
// handling pdf files
|
||||
if ("pdf".contains(filetype)) {
|
||||
val fileView = FileView(filetype, filename, fileDescription, null, null, "${ServerManagement.baseUrl}files/$connectedServerId/$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView(this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] Exception in home fragment, files data request : $e") }
|
||||
|
||||
}
|
||||
|
||||
if (!ServerManagement.serverManager.checkIfConnectionAlreadyExists("fileViewsConnection")) {
|
||||
ServerManagement.serverManager.addReceiverConnection(dataReceiver3, requireContext(), "fileViewsConnection", connectedServerId, "", "GET_WHOLE_ARRAY")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class ServerConnector(private val numberOfAttempts: Int=3): Runnable {
|
||||
override fun run() {
|
||||
for (n in 0 until numberOfAttempts) {
|
||||
tryConnectingToServer()
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadCache() {}
|
||||
|
||||
private fun saveCache() {}
|
||||
}
|
@ -0,0 +1,323 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.example.wikispot.GeneralVariables
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.ServerManagement
|
||||
import com.example.wikispot.adapters.FileViewsAdapter
|
||||
import com.example.wikispot.adapters.LabeledValuesAdapter
|
||||
import com.example.wikispot.modelClasses.JsonManager
|
||||
import com.example.wikispot.modelClasses.JsonManagerLite
|
||||
import com.example.wikispot.modelsForAdapters.FileView
|
||||
import com.example.wikispot.modelsForAdapters.FileViewsSupplier
|
||||
import com.example.wikispot.modelsForAdapters.LabeledValue
|
||||
import com.example.wikispot.modelsForAdapters.LabeledValuesSupplier
|
||||
import com.example.wikispot.showToast
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import kotlinx.android.synthetic.main.fragment_info.*
|
||||
|
||||
|
||||
class infoFragment : Fragment(R.layout.fragment_info) {
|
||||
|
||||
private val args: infoFragmentArgs by navArgs()
|
||||
var location: LatLng? = null
|
||||
var phoneNumber: Int? = null
|
||||
var email: String? = null
|
||||
var executeLoadFunction = false
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
LabeledValuesSupplier.wipeData()
|
||||
FileViewsSupplier.wipeData()
|
||||
updateSensorsRecyclerView()
|
||||
updateFileViewsRecyclerView()
|
||||
|
||||
//file_views_recycler_view.isNestedScrollingEnabled = false
|
||||
|
||||
try {
|
||||
executeLoadFunction = args.executeLoadFuntion
|
||||
} catch (e: Throwable) {
|
||||
if (!e.toString().contains("has null arguments")){
|
||||
println("[debug] Exception in Info Fragment while getting args: $e")
|
||||
}
|
||||
}
|
||||
|
||||
if (executeLoadFunction) {
|
||||
load()
|
||||
} else {
|
||||
getContactInfoFromGeneralVariables()
|
||||
}
|
||||
|
||||
locationBtn.setOnClickListener {
|
||||
if (executeLoadFunction) {
|
||||
if (location != null) {
|
||||
val action = infoFragmentDirections.infoFragmentToMapFragment(location!!)
|
||||
Navigation.findNavController(it).navigate(action)
|
||||
}
|
||||
} else {
|
||||
Navigation.findNavController(it).navigate(R.id.homeFragment_to_mapFragment)
|
||||
}
|
||||
}
|
||||
|
||||
phoneBtn.setOnClickListener {
|
||||
if (phoneNumber != null) {
|
||||
phoneNumber?.let {
|
||||
val intent = Intent(Intent.ACTION_DIAL)
|
||||
intent.data = Uri.parse("tel:$phoneNumber")
|
||||
startActivity(intent)
|
||||
}
|
||||
} else {
|
||||
requireContext().showToast("Phone number not found.")
|
||||
}
|
||||
}
|
||||
|
||||
emailBtn.setOnClickListener {
|
||||
if (email != null) {
|
||||
email?.let{
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
|
||||
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf(email))
|
||||
|
||||
intent.type = "text/plain"
|
||||
|
||||
startActivity(Intent.createChooser(intent, "Send Email"))
|
||||
}
|
||||
} else {
|
||||
requireContext().showToast("Email address not found.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun load() {
|
||||
val serverId = ServerManagement.selectedServerId
|
||||
|
||||
val dataReceiver: (String) -> Unit = { data: String ->
|
||||
context?.let {
|
||||
try {
|
||||
val json = JsonManager(requireContext(), data)
|
||||
json.findJsonObjectByAttribute("ID", serverId)
|
||||
|
||||
val phoneNumberLoaded = json.getAttributeContentByPath("description/phone_number")
|
||||
if (phoneNumberLoaded != GeneralVariables.variableMissingKeyword) {
|
||||
phoneNumber = phoneNumberLoaded.toInt()
|
||||
checkContactInformation()
|
||||
}
|
||||
|
||||
val emailLoaded = json.getAttributeContentByPath("description/email")
|
||||
if (emailLoaded != GeneralVariables.variableMissingKeyword) {
|
||||
email = emailLoaded
|
||||
checkContactInformation()
|
||||
}
|
||||
|
||||
mainTitle?.let {
|
||||
mainTitle.post {
|
||||
val title = json.getAttributeContentByPath("description/title")
|
||||
if (title != GeneralVariables.variableMissingKeyword) {
|
||||
mainTitle.text = title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mainDescription?.let {
|
||||
mainDescription.post {
|
||||
val description = json.getAttributeContentByPath("description/description_l")
|
||||
if (description != GeneralVariables.variableMissingKeyword) {
|
||||
mainDescription.text = description
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val imageReceiver1: (Bitmap) -> Unit = { bitmap: Bitmap ->
|
||||
mainImage.post {
|
||||
mainImage?.let {
|
||||
mainImage.setImageBitmap(bitmap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val coordinates = json.getAttributeContent("location").split(",")
|
||||
location = LatLng(coordinates[0].toDouble(), coordinates[1].toDouble())
|
||||
|
||||
ServerManagement.serverManager.getImage(imageReceiver1, json.getAttributeContent("ID").toInt(),
|
||||
json.getAttributeContentByPath("description/photo_b"), 2)
|
||||
|
||||
// getting files
|
||||
|
||||
json.getAttributeContent("files")
|
||||
|
||||
for (n in 0 until json.currentJsonAttribute1!!.length()) {
|
||||
val fileInfo = JsonManagerLite(json.getAttributeContentByPath("files/$n"), "JSONObject")
|
||||
val filetype = fileInfo.getAttributeContentByPath("format").split(".")[1]
|
||||
val filename = fileInfo.getAttributeContentByPath("name")
|
||||
val fileDescription = fileInfo.getAttributeContent("description")
|
||||
|
||||
// handling text
|
||||
if ("txt json".contains(filetype)) {
|
||||
val fileView = FileView(filetype, filename, fileDescription, "$serverId|||||$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView()
|
||||
}
|
||||
}
|
||||
|
||||
// handling images
|
||||
else if ("jpg png".contains(filetype)) {
|
||||
val fileView = FileView(filetype, filename, fileDescription, null, "$serverId|||||$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView()
|
||||
}
|
||||
}
|
||||
|
||||
// handling pdf files
|
||||
else if ("pdf".contains(filetype)) {
|
||||
val fileView = FileView(filetype, filename, fileDescription, null, null, "${ServerManagement.baseUrl}files/$serverId/$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
val fileView = FileView(filetype, filename, fileDescription, null, null, null, "${ServerManagement.baseUrl}files/$serverId/$filename.$filetype")
|
||||
if (!FileViewsSupplier.checkIfContains(fileView)) {
|
||||
FileViewsSupplier.appendFileView(fileView)
|
||||
updateFileViewsRecyclerView()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] exception in infoFragment load data request Exception: $e") }
|
||||
}
|
||||
}
|
||||
|
||||
val sensorsDataReceiver: (String) -> Unit = { data: String ->
|
||||
try {
|
||||
context?.let {
|
||||
val json = JsonManager(requireContext(), data, "JSONObject")
|
||||
val names = json.currentJsonObject!!.names()
|
||||
|
||||
LabeledValuesSupplier.wipeData()
|
||||
|
||||
if (names != null) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateSensorsRecyclerView()
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] Exception in info fragment, load, sensorsDataReceiver : $e") }
|
||||
}
|
||||
|
||||
context?.let {
|
||||
ServerManagement.serverManager.getData(dataReceiver, requireContext(), serverId, "", "GET_WHOLE_ARRAY", 3)
|
||||
ServerManagement.serverManager.addReceiverConnection(sensorsDataReceiver, requireContext(), "infoFragmentSensorsConnection",
|
||||
serverId, ServerManagement.sensors_keyword)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getContactInfoFromGeneralVariables(numberOfAttempts: Int = 8) {
|
||||
class RetrieveContactInfoFromGeneralVariables(val attemptsCount: Int): Runnable {
|
||||
override fun run() {
|
||||
for (i in 0 until attemptsCount) {
|
||||
phoneNumber = GeneralVariables.phoneNumber
|
||||
email = GeneralVariables.email
|
||||
|
||||
if (phoneNumber != null) {
|
||||
checkContactInformation()
|
||||
break
|
||||
}
|
||||
if (email != null) {
|
||||
checkContactInformation()
|
||||
break
|
||||
}
|
||||
Thread.sleep(300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val retrieveContactInfoFromGeneralVariables = Thread(RetrieveContactInfoFromGeneralVariables(numberOfAttempts))
|
||||
retrieveContactInfoFromGeneralVariables.start()
|
||||
}
|
||||
|
||||
private fun checkContactInformation() {
|
||||
phoneNumber?.let {
|
||||
try {
|
||||
phoneBtn.post {
|
||||
phoneBtn?.let {
|
||||
phoneBtn.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] Exception in checkContactInformation: $e") }
|
||||
}
|
||||
|
||||
email?.let {
|
||||
try {
|
||||
emailBtn.post {
|
||||
emailBtn?.let {
|
||||
emailBtn.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] Exception in checkContactInformation: $e") }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
ServerManagement.serverManager.deleteConnection("infoFragmentSensorsConnection")
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
private fun updateSensorsRecyclerView() {
|
||||
|
||||
try {
|
||||
labeled_values_recycler_view.post {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
labeled_values_recycler_view.layoutManager = layoutManager
|
||||
|
||||
val adapter = context?.let { LabeledValuesAdapter(it, LabeledValuesSupplier.labeledValues) }
|
||||
labeled_values_recycler_view.adapter = adapter
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] e3 Exception: $e") }
|
||||
|
||||
}
|
||||
|
||||
private fun updateFileViewsRecyclerView() {
|
||||
|
||||
try {
|
||||
file_views_recycler_view.post {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
|
||||
layoutManager.orientation = LinearLayoutManager.VERTICAL
|
||||
file_views_recycler_view.layoutManager = layoutManager
|
||||
|
||||
val adapter = context?.let { FileViewsAdapter(it, FileViewsSupplier.fileViews) }
|
||||
file_views_recycler_view.adapter = adapter
|
||||
}
|
||||
} catch (e: Throwable) { println("[debug] e2 Exception: $e") }
|
||||
|
||||
}
|
||||
|
||||
fun goExploreFragment() {
|
||||
Navigation.findNavController(mainTitle).navigate(R.id.navigateBackToExploreFragment)
|
||||
}
|
||||
|
||||
fun goMapFragment() {
|
||||
val action = infoFragmentDirections.infoFragmentToMapFragment(LatLng(0.toDouble(), 0.toDouble()), true)
|
||||
Navigation.findNavController(mainTitle).navigate(action)
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,99 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import com.example.wikispot.CustomBackstackVariables
|
||||
import com.example.wikispot.MapManagement
|
||||
import com.example.wikispot.R
|
||||
import com.example.wikispot.ServerManagement
|
||||
import com.example.wikispot.modelsForAdapters.PlaceSupplier
|
||||
import com.google.android.gms.maps.CameraUpdateFactory
|
||||
import com.google.android.gms.maps.GoogleMap
|
||||
import com.google.android.gms.maps.OnMapReadyCallback
|
||||
import com.google.android.gms.maps.SupportMapFragment
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import com.google.android.gms.maps.model.Marker
|
||||
import com.google.android.gms.maps.model.MarkerOptions
|
||||
import kotlinx.android.synthetic.main.fragment_map.*
|
||||
import java.time.Clock
|
||||
|
||||
class mapFragment : Fragment(), GoogleMap.OnMarkerClickListener {
|
||||
|
||||
class mapFragment : Fragment(R.layout.fragment_map) {
|
||||
val args: mapFragmentArgs by navArgs()
|
||||
private var loadFromMapManager = true
|
||||
private var loadLastCoordinates = false
|
||||
var location: LatLng? = null
|
||||
var lastClickedMarkerTitle = ""
|
||||
|
||||
private val callback = OnMapReadyCallback { googleMap ->
|
||||
/**
|
||||
* Manipulates the map once available.
|
||||
* This callback is triggered when the map is ready to be used.
|
||||
* This is where we can add markers or lines, add listeners or move the camera.
|
||||
* In this case, we just add a marker near Sydney, Australia.
|
||||
* If Google Play services is not installed on the device, the user will be prompted to
|
||||
* install it inside the SupportMapFragment. This method will only be triggered once the
|
||||
* user has installed Google Play services and returned to the app.
|
||||
*/
|
||||
/*val pb = LatLng(49.11274928646463, 18.443442353021045)
|
||||
googleMap.addMarker(MarkerOptions().position(pb).title("Povazska Bystrica"))
|
||||
googleMap.moveCamera(CameraUpdateFactory.newLatLng(pb))
|
||||
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(pb, 16.0f)) */
|
||||
|
||||
try {
|
||||
location = args.location
|
||||
loadLastCoordinates = args.loadLastCoordinates
|
||||
loadFromMapManager = false
|
||||
} catch (e: Throwable) { println("[debug] Exception in Map Fragment while getting args: $e") }
|
||||
|
||||
if (loadFromMapManager) {
|
||||
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(MapManagement.connectedServerPosition, 15.0F))
|
||||
} else if (loadLastCoordinates){
|
||||
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(MapManagement.lastCoordinates, 15F))
|
||||
} else {
|
||||
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(location, 15.0F))
|
||||
}
|
||||
|
||||
// loading other markers
|
||||
for (n in PlaceSupplier.places.indices) {
|
||||
val coordinates = PlaceSupplier.places[n]?.location!!.split(",")
|
||||
googleMap.addMarker(MarkerOptions().position(LatLng(coordinates[0].toDouble(), coordinates[1].toDouble())).title(PlaceSupplier.places[n]?.title)
|
||||
.snippet(PlaceSupplier.places[n]!!.description))
|
||||
}
|
||||
|
||||
googleMap.setOnMarkerClickListener(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_map, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
|
||||
mapFragment?.getMapAsync(callback)
|
||||
}
|
||||
|
||||
override fun onMarkerClick(marker: Marker?): Boolean {
|
||||
marker?.let {
|
||||
if (marker.title == lastClickedMarkerTitle) {
|
||||
for (n in PlaceSupplier.places.indices) {
|
||||
if (marker.title == PlaceSupplier.places[n]!!.title) {
|
||||
CustomBackstackVariables.infoFragmentBackDestination = "mapFragment"
|
||||
MapManagement.lastCoordinates = marker.position
|
||||
ServerManagement.selectedServerId = PlaceSupplier.places[n]!!.id!!
|
||||
val action = mapFragmentDirections.mapFragmentToInfoFragment(true)
|
||||
Navigation.findNavController(navControllerView).navigate(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
lastClickedMarkerTitle = marker.title
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
@ -1,12 +1,69 @@
|
||||
package com.example.wikispot.fragments
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.example.wikispot.R
|
||||
import androidx.navigation.Navigation
|
||||
import com.example.wikispot.*
|
||||
import com.example.wikispot.activities.MainActivity
|
||||
import com.example.wikispot.modelClasses.ServerManager
|
||||
import com.example.wikispot.modelClasses.SettingsSaveManager
|
||||
import kotlinx.android.synthetic.main.fragment_settings.*
|
||||
import javax.xml.transform.sax.TemplatesHandler
|
||||
|
||||
|
||||
class settingsFragment : Fragment(R.layout.fragment_settings) {
|
||||
|
||||
private lateinit var settingsSaveManager: SettingsSaveManager
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
StartDirections.settingsFragmentStartDirection?.let {
|
||||
when (StartDirections.settingsFragmentStartDirection) {
|
||||
"debugFragment" -> {
|
||||
Navigation.findNavController(debugBtn).navigate(R.id.navigateToDebugFragment)
|
||||
StartDirections.settingsFragmentStartDirection = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settingsSaveManager = SettingsSaveManager(requireContext())
|
||||
|
||||
loadSettings()
|
||||
|
||||
debugBtn.setOnClickListener {
|
||||
Navigation.findNavController(it).navigate(R.id.navigateToDebugFragment)
|
||||
}
|
||||
|
||||
darkThemeSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
ThemeOptions.darkTheme = isChecked
|
||||
settingsSaveManager.saveSettings()
|
||||
restartAppPartially()
|
||||
}
|
||||
|
||||
moreColorsSwitch.setOnCheckedChangeListener { _, isChecked ->
|
||||
ThemeOptions.moreColors = isChecked
|
||||
settingsSaveManager.saveSettings()
|
||||
restartAppPartially()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadSettings() {
|
||||
darkThemeSwitch.isChecked = ThemeOptions.darkTheme
|
||||
moreColorsSwitch.isChecked = ThemeOptions.moreColors
|
||||
}
|
||||
|
||||
private fun restartAppPartially() {
|
||||
val intent = Intent(context?.applicationContext, MainActivity::class.java)
|
||||
|
||||
intent.putExtra(IntentsKeys.startFragment, "settingsFragment")
|
||||
|
||||
ServerManagement.serverManager.clearConnections()
|
||||
|
||||
startActivity(intent)
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
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
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
data class JsonManager(private val context: Context, val data: String, val inputType: String = "JSONArray", val debug: Boolean = false) {
|
||||
|
||||
var jsonArray: JSONArray? = null
|
||||
var currentJsonObject: JSONObject? = null
|
||||
var currentJsonAttribute0: JSONObject? = null
|
||||
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) {
|
||||
if (debug) {
|
||||
context.showToast("Invalid attribute name: $name")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (debug) {
|
||||
context.showToast("Invalid attribute name: $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) {
|
||||
if (debug) {
|
||||
context.showToast("Invalid attribute name: $name")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug) {
|
||||
context.showToast("Invalid attribute name: $name")
|
||||
}
|
||||
}
|
||||
|
||||
return GeneralVariables.variableMissingKeyword
|
||||
}
|
||||
|
||||
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 GeneralVariables.variableMissingKeyword
|
||||
}
|
||||
}
|
||||
|
||||
// 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"
|
||||
}
|
||||
|
||||
fun findJsonObjectByAttribute(attributePath: String, value: Any): String {
|
||||
val currentJsonObjectSave = currentJsonObject
|
||||
|
||||
for (i in 0 until getLengthOfJsonArray()) {
|
||||
|
||||
getJsonObject(i)
|
||||
|
||||
val attributeContent = getAttributeContentByPath(attributePath)
|
||||
|
||||
if (attributeContent != GeneralVariables.variableMissingKeyword) {
|
||||
|
||||
if (attributeContent == value.toString()) {
|
||||
return currentJsonObject.toString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
currentJsonObject = currentJsonObjectSave
|
||||
return currentJsonObject.toString()
|
||||
|
||||
}
|
||||
|
||||
// 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,135 @@
|
||||
package com.example.wikispot.modelClasses
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
data class JsonManagerLite(val data: String, val inputType: String = "JSONArray") {
|
||||
|
||||
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) {}
|
||||
|
||||
} else if (inputType == "JSONObject") {
|
||||
currentJsonObject = JSONObject(data)
|
||||
}
|
||||
}
|
||||
|
||||
fun getJsonObject(i: Int): JSONObject? {
|
||||
jsonArray?.let {
|
||||
currentJsonObject = jsonArray?.getJSONObject(i)
|
||||
return currentJsonObject
|
||||
}
|
||||
|
||||
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) { }
|
||||
}
|
||||
}
|
||||
} 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) { }
|
||||
}
|
||||
}
|
||||
} 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) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
fun getAttributeContentByPath(path: String): String {
|
||||
val steps = path.split("/")
|
||||
|
||||
val currentJsonAttributesBackup = listOf(currentJsonAttribute0, currentJsonAttribute1) // backing up selected jsonAttributes
|
||||
|
||||
// getting the attribute
|
||||
clearSelectedAttributes()
|
||||
var result: Any? = null
|
||||
for (step in steps) {
|
||||
try {
|
||||
result = getAttributeContent(step)
|
||||
} catch (exception: Throwable) {
|
||||
// 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 clearSelectedAttributes() {
|
||||
currentJsonAttribute0 = null
|
||||
currentJsonAttribute1 = null
|
||||
}
|
||||
|
||||
fun getLengthOfJsonArray(): Int {
|
||||
return if (jsonArray != null) {
|
||||
jsonArray!!.length()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentJsonAttributeContent(): String {
|
||||
if (currentJsonAttribute0 != null) {
|
||||
return currentJsonAttribute0.toString()
|
||||
} else if (currentJsonAttribute1 != null) {
|
||||
return currentJsonAttribute1.toString()
|
||||
}
|
||||
return "get json attribute first"
|
||||
}
|
||||
}
|
@ -0,0 +1,551 @@
|
||||
package com.example.wikispot.modelClasses
|
||||
|
||||
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 okhttp3.*
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
|
||||
|
||||
class ServerManager {
|
||||
|
||||
private var receiverConnections = mutableListOf<ReceiverConnection>()
|
||||
private var viewConnections = mutableListOf<ViewConnection>()
|
||||
private var chatConnections = mutableListOf<ChatConnection>()
|
||||
|
||||
// single time requests
|
||||
|
||||
fun getData(dataReceiver: (String) -> Unit, context: Context, serverId: Int, path: String, attributePath: String = "", numberOfAttempts: Int = 2) {
|
||||
val dataRequestThread = Thread(DataRequest(dataReceiver, context, serverId, path, attributePath, numberOfAttempts))
|
||||
dataRequestThread.start()
|
||||
}
|
||||
|
||||
inner class DataRequest(val dataReceiver: (String) -> Unit, val context: Context, val serverId: Int, val path: String = "", val attributePath: String, private val numberOfAttempts: Int = 2): Runnable{
|
||||
override fun run() {
|
||||
for (n in 0 until numberOfAttempts) {
|
||||
var url = "${ServerManagement.baseUrl}devices_list"
|
||||
|
||||
if (path != "") {
|
||||
if (path.contains(ServerManagement.sensors_keyword)){
|
||||
url = "${ServerManagement.baseUrl}$serverId/sensors"
|
||||
} else {
|
||||
url = "${ServerManagement.baseUrl}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 == "") {
|
||||
if (attributePath == "GET_WHOLE_ARRAY") {
|
||||
dataReceiver(jsonManager.jsonArray.toString())
|
||||
return
|
||||
}
|
||||
jsonManager.getJsonObject(0)
|
||||
} else {
|
||||
if (attributePath == "") {
|
||||
throw Throwable()
|
||||
}
|
||||
}
|
||||
|
||||
if (attributePath != "") {
|
||||
dataReceiver(jsonManager.getAttributeContentByPath(attributePath))
|
||||
} else {
|
||||
dataReceiver(jsonManager.currentJsonObject.toString())
|
||||
}
|
||||
|
||||
} catch (exception: Throwable) {
|
||||
try {
|
||||
JSONObject(receivedString)
|
||||
|
||||
val jsonManager = JsonManager(context, receivedString, "JSONObject")
|
||||
|
||||
if (attributePath != "") {
|
||||
dataReceiver(jsonManager.getAttributeContentByPath(attributePath))
|
||||
} else {
|
||||
dataReceiver(jsonManager.currentJsonObject.toString())
|
||||
}
|
||||
|
||||
} catch (exception: Throwable) {
|
||||
dataReceiver(receivedString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
println("Request Failed")
|
||||
println(e)
|
||||
}
|
||||
})
|
||||
|
||||
ServerManagement.totalNumberOfRequestsSent += 1
|
||||
|
||||
Thread.sleep(ServerManagement.dataRequestOnAttemptWait)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getImage(imageReceiver: (Bitmap) -> Unit, serverId: Int, path: String, numberOfAttempts: Int = 2) {
|
||||
val imageRequestThread = Thread(ImageRequest(imageReceiver, serverId, path, numberOfAttempts))
|
||||
imageRequestThread.start()
|
||||
}
|
||||
|
||||
inner class ImageRequest(val imageReceiver: (Bitmap) -> Unit, val serverId: Int, val path: String, private val numberOfAttempts: Int): Runnable {
|
||||
override fun run() {
|
||||
for (i in 0 until numberOfAttempts) {
|
||||
val url = "${ServerManagement.baseUrl}files/$serverId/$path"
|
||||
|
||||
try {
|
||||
val inputStream = java.net.URL(url).openStream()
|
||||
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
|
||||
} catch (e: Throwable) { println(e) }
|
||||
|
||||
ServerManagement.totalNumberOfRequestsSent += 1
|
||||
|
||||
Thread.sleep(ServerManagement.imageRequestOnAttemptWait)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadPdfView(view: PDFView, url: String, swipeHorizontal: Boolean = false) {
|
||||
val pdfLoadingRequestThread = Thread(PdfLoadingRequest(view, url, swipeHorizontal))
|
||||
pdfLoadingRequestThread.start()
|
||||
}
|
||||
|
||||
inner class PdfLoadingRequest(val view: PDFView, val url: String, private val swipeHorizontal: Boolean = false): Runnable {
|
||||
override fun run() {
|
||||
val inputStream = java.net.URL(url).openStream()
|
||||
view.post {
|
||||
view.fromStream(inputStream).swipeHorizontal(swipeHorizontal).load()
|
||||
view.zoomTo(view.width / 490.0F)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// connections
|
||||
|
||||
fun clearConnections() {
|
||||
for (i in 0 until receiverConnections.size) {
|
||||
try {
|
||||
receiverConnections[i].running = false
|
||||
} 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{
|
||||
if ((connectionType == "any") or (connectionType == "receiver")) {
|
||||
for (n in 0 until receiverConnections.size) {
|
||||
if (receiverConnections[n].connectionName == connectionName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((connectionType == "any") or (connectionType == "view")) {
|
||||
for (n in 0 until viewConnections.size) {
|
||||
if (viewConnections[n].connectionName == connectionName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((connectionType == "any") or (connectionType == "chat")) {
|
||||
for (n in 0 until chatConnections.size) {
|
||||
if (chatConnections[n].connectionName == connectionName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun deleteConnection(connectionName: String, connectionType: String = "any") { // other types are any, activity and view
|
||||
if ((connectionType == "any") or (connectionType == "receiver")) {
|
||||
val indexesToRemove = mutableListOf<Int>()
|
||||
for (i in 0 until receiverConnections.size) { // checking in connections
|
||||
try {
|
||||
if (receiverConnections[i].connectionName == connectionName) {
|
||||
receiverConnections[i].running = false
|
||||
indexesToRemove.add(i)
|
||||
}
|
||||
} catch (e: Throwable) { println("In deleteConnection: $e") }
|
||||
}
|
||||
|
||||
for (i in 0 until indexesToRemove.size) {
|
||||
receiverConnections.removeAt(indexesToRemove[i] - i)
|
||||
}
|
||||
}
|
||||
|
||||
if ((connectionType == "any") or (connectionType == "view")) {
|
||||
val indexesToRemove = mutableListOf<Int>()
|
||||
for (i in 0 until viewConnections.size) { // checking in connections
|
||||
try {
|
||||
if (viewConnections[i].connectionName == connectionName) {
|
||||
viewConnections[i].running = false
|
||||
indexesToRemove.add(i)
|
||||
}
|
||||
} catch (e: Throwable) { println("In deleteConnection: $e") }
|
||||
}
|
||||
|
||||
for (i in 0 until indexesToRemove.size) {
|
||||
viewConnections.removeAt(indexesToRemove[i] - i)
|
||||
}
|
||||
}
|
||||
|
||||
if ((connectionType == "any") or (connectionType == "chat")) {
|
||||
val indexesToRemove = mutableListOf<Int>()
|
||||
for (i in 0 until chatConnections.size) { // checking in connections
|
||||
try {
|
||||
if (chatConnections[i].connectionName == connectionName) {
|
||||
chatConnections[i].running = false
|
||||
indexesToRemove.add(i)
|
||||
}
|
||||
} catch (e: Throwable) { println("In deleteConnection: $e") }
|
||||
}
|
||||
|
||||
for (i in 0 until indexesToRemove.size) {
|
||||
chatConnections.removeAt(indexesToRemove[i] - i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addReceiverConnection(dataReceiver: (String) -> Unit, context: Context, connectionName: String, serverId: Int, path: String = "", attributePath: String = "", waitTime: Long = ServerManagement.receiverConnectionOnCheckWait) {
|
||||
receiverConnections.add(ReceiverConnection(dataReceiver, context, connectionName, serverId, path, attributePath, waitTime))
|
||||
}
|
||||
|
||||
inner class ReceiverConnection(val dataReceiver: (String) -> Unit, val context: Context, val connectionName: String, val serverId: Int, val path: String = "", val attributePath: String, val waitTime: Long) {
|
||||
|
||||
var running = true
|
||||
|
||||
init {
|
||||
val checkingServerDataThread = Thread(CheckingServerData())
|
||||
checkingServerDataThread.start()
|
||||
}
|
||||
|
||||
inner class CheckingServerData : Runnable {
|
||||
override fun run() {
|
||||
while (running) {
|
||||
var url = "${ServerManagement.baseUrl}devices_list"
|
||||
|
||||
if (path != "") {
|
||||
if (path.contains(ServerManagement.sensors_keyword)){
|
||||
url = "${ServerManagement.baseUrl}$serverId/sensors"
|
||||
} else {
|
||||
url = "${ServerManagement.baseUrl}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 == "") {
|
||||
if (attributePath == "GET_WHOLE_ARRAY") {
|
||||
dataReceiver(jsonManager.jsonArray.toString())
|
||||
return
|
||||
}
|
||||
jsonManager.getJsonObject(0)
|
||||
} else {
|
||||
if (attributePath == "") {
|
||||
throw Throwable()
|
||||
}
|
||||
}
|
||||
|
||||
if (attributePath != "") {
|
||||
dataReceiver(jsonManager.getAttributeContentByPath(attributePath))
|
||||
} else {
|
||||
dataReceiver(jsonManager.currentJsonObject.toString())
|
||||
}
|
||||
|
||||
} catch (exception: Throwable) {
|
||||
try {
|
||||
JSONObject(receivedString)
|
||||
|
||||
val jsonManager = JsonManager(context, receivedString, "JSONObject")
|
||||
|
||||
if (attributePath != "") {
|
||||
dataReceiver(jsonManager.getAttributeContentByPath(attributePath))
|
||||
} else {
|
||||
dataReceiver(jsonManager.currentJsonObject.toString())
|
||||
}
|
||||
|
||||
} catch (exception: Throwable) {
|
||||
dataReceiver(receivedString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
println("Request Failed")
|
||||
println(e)
|
||||
}
|
||||
})
|
||||
|
||||
ServerManagement.totalNumberOfRequestsSent += 1
|
||||
|
||||
Thread.sleep(waitTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun addViewConnection(context: Context, view: TextView, connectionName: String, serverId: Int, path: String = "", attributePath: String = "") {
|
||||
viewConnections.add(ViewConnection(context, view, connectionName, serverId, path, attributePath))
|
||||
}
|
||||
|
||||
inner class ViewConnection(val context: Context, val view: TextView, val connectionName: String, val serverId: Int, val path: String = "", var attributePath: String) {
|
||||
|
||||
var running = true
|
||||
|
||||
init {
|
||||
val checkingServerDataThread = Thread(CheckingServerData())
|
||||
checkingServerDataThread.start()
|
||||
}
|
||||
|
||||
inner class CheckingServerData: Runnable {
|
||||
override fun run() {
|
||||
while (running) {
|
||||
var url = "${ServerManagement.baseUrl}devices_list"
|
||||
|
||||
if (path != "") {
|
||||
if (path.contains(ServerManagement.sensors_keyword)){
|
||||
url = "${ServerManagement.baseUrl}$serverId/sensors"
|
||||
} else {
|
||||
url = "${ServerManagement.baseUrl}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 == "") {
|
||||
if (attributePath == "GET_WHOLE_ARRAY") {
|
||||
view.text = jsonManager.jsonArray.toString()
|
||||
return
|
||||
}
|
||||
jsonManager.getJsonObject(0)
|
||||
} else {
|
||||
if (attributePath == "") {
|
||||
throw Throwable()
|
||||
}
|
||||
}
|
||||
|
||||
if (attributePath != "") {
|
||||
view.post {
|
||||
view.text = jsonManager.getAttributeContentByPath(attributePath)
|
||||
}
|
||||
} else {
|
||||
view.post {
|
||||
view.text = jsonManager.currentJsonObject.toString()
|
||||
}
|
||||
}
|
||||
|
||||
} catch (exception: Throwable) {
|
||||
try {
|
||||
JSONObject(receivedString)
|
||||
|
||||
val jsonManager = JsonManager(context, receivedString, "JSONObject")
|
||||
|
||||
if (attributePath != "") {
|
||||
view.post {
|
||||
view.text = jsonManager.getAttributeContentByPath(attributePath)
|
||||
}
|
||||
} else {
|
||||
view.post {
|
||||
view.text = jsonManager.currentJsonObject.toString()
|
||||
}
|
||||
}
|
||||
|
||||
} catch (exception: Throwable) {
|
||||
view.post {
|
||||
view.text = receivedString
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
println("Request Failed")
|
||||
println(e)
|
||||
}
|
||||
})
|
||||
|
||||
ServerManagement.totalNumberOfRequestsSent += 1
|
||||
|
||||
Thread.sleep(ServerManagement.viewConnectionOnCheckWait)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
46
app/WikiSpot/app/src/main/java/com/example/wikispot/modelClasses/SettingsSaveManager.kt
Normal file
@ -0,0 +1,46 @@
|
||||
package com.example.wikispot.modelClasses
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import com.example.wikispot.GeneralVariables
|
||||
import com.example.wikispot.IntentsKeys
|
||||
import com.example.wikispot.ThemeOptions
|
||||
import com.example.wikispot.activities.MainActivity
|
||||
|
||||
class SettingsSaveManager(val context: Context) {
|
||||
|
||||
fun loadSettings() {
|
||||
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
ThemeOptions.darkTheme = sharedPreferences.getBoolean("darkMode", ThemeOptions.darkTheme)
|
||||
ThemeOptions.moreColors = sharedPreferences.getBoolean("moreColors", ThemeOptions.moreColors)
|
||||
|
||||
// checking if we want to use system default theme
|
||||
try {
|
||||
GeneralVariables.appRunningFirstTime = sharedPreferences.getBoolean("appRunningFirstTime", true)
|
||||
|
||||
if (GeneralVariables.appRunningFirstTime) {
|
||||
ThemeOptions.darkTheme = (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
println(e)
|
||||
}
|
||||
|
||||
// saving settings cause some things might change based on system preferences
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
fun saveSettings() {
|
||||
val sharedPreferences = context.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
val editor = sharedPreferences.edit()
|
||||
|
||||
editor.apply{
|
||||
putBoolean("appRunningFirstTime", false)
|
||||
putBoolean("darkMode", ThemeOptions.darkTheme)
|
||||
putBoolean("moreColors", ThemeOptions.moreColors)
|
||||
}.apply()
|
||||
}
|
||||
|
||||
}
|
107
app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/ExploreListModel.kt
Normal file
@ -0,0 +1,107 @@
|
||||
package com.example.wikispot.modelsForAdapters
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import com.example.wikispot.getStringFromSharedPreferences
|
||||
import com.example.wikispot.modelClasses.JsonManager
|
||||
import com.example.wikispot.modelClasses.JsonManagerLite
|
||||
import com.example.wikispot.saveString
|
||||
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)
|
||||
|
||||
object PlaceSupplier {
|
||||
|
||||
var controlJson: JsonManagerLite? = null
|
||||
|
||||
var places = arrayOf<PlacePreview?>()
|
||||
|
||||
fun appendPlace(place: PlacePreview) {
|
||||
val array = places.copyOf(places.size + 1)
|
||||
array[places.size] = place
|
||||
places = array
|
||||
}
|
||||
|
||||
fun checkIfContains(place: PlacePreview): Boolean {
|
||||
for (n in places.indices) {
|
||||
places[n]?.let {
|
||||
if (places[n]?.title == place.title) {
|
||||
if (places[n]?.description == place.description) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getContainingInstance(place: PlacePreview): PlacePreview? {
|
||||
for (n in places.indices) {
|
||||
places[n]?.let {
|
||||
if (places[n]?.title == place.title) {
|
||||
if (places[n]?.description == place.description) {
|
||||
return places[n]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// loading from and saving to cache
|
||||
fun loadFromCache(context: Context) {
|
||||
println("loading")
|
||||
var save = context.getStringFromSharedPreferences("placePreviews", "exploreFragmentCache")
|
||||
if (save.isEmpty()) {
|
||||
save = "[]"
|
||||
}
|
||||
val jsonManager = JsonManager(context, save)
|
||||
for (n in 0 until jsonManager.getLengthOfJsonArray()) {
|
||||
val savedData = jsonManager.jsonArray?.get(n).toString().split("|||||")
|
||||
val place = PlacePreview(savedData[0], savedData[1], savedData[2], null, savedData[3].toInt())
|
||||
if (!checkIfContains(place)) {
|
||||
appendPlace(place)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun saveToCache(context: Context) {
|
||||
val save = JSONArray()
|
||||
|
||||
var i = 0
|
||||
for (n in places.indices) {
|
||||
val place = places[n]
|
||||
if (getSavePermission(place)) {
|
||||
save.put(i, "${place!!.title}|||||${place.description}|||||${place.location}|||||${place.id}")
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
context.saveString("placePreviews", save.toString(), "exploreFragmentCache")
|
||||
}
|
||||
|
||||
private fun getSavePermission(place: PlacePreview?): Boolean {
|
||||
if (controlJson == null) {
|
||||
return true
|
||||
}
|
||||
|
||||
place?.let {
|
||||
for (n in 1 until controlJson!!.getLengthOfJsonArray()) {
|
||||
controlJson!!.getJsonObject(n)
|
||||
if (place.id == controlJson!!.getAttributeContent("ID").toInt()) {
|
||||
if (place.title == controlJson!!.getAttributeContentByPath("description/title")) {
|
||||
val tempPlace = PlacePreview("", controlJson!!.getAttributeContentByPath("description/description_s"),
|
||||
controlJson!!.getAttributeContentByPath("location"))
|
||||
if (place.description == tempPlace.description) {
|
||||
if (place.location == tempPlace.location) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
34
app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/FilesListModel.kt
Normal file
@ -0,0 +1,34 @@
|
||||
package com.example.wikispot.modelsForAdapters
|
||||
|
||||
data class FileView(val filetype: String, val filename: String, val fileDescription: String,
|
||||
var textInfo: String? = null, var imgInfo: String? = null, var pdfUrl: String? = null,
|
||||
var generalUrl: String? = null)
|
||||
|
||||
|
||||
object FileViewsSupplier {
|
||||
|
||||
var fileViews = arrayOf<FileView?>()
|
||||
|
||||
fun appendFileView(fileView: FileView) {
|
||||
val array = fileViews.copyOf(fileViews.size + 1)
|
||||
array[fileViews.size] = fileView
|
||||
fileViews = array
|
||||
}
|
||||
|
||||
fun checkIfContains(fileView: FileView): Boolean{
|
||||
for (n in fileViews.indices) {
|
||||
if (fileViews[n]!!.filename == fileView.filename) {
|
||||
if (fileViews[n]!!.filetype == fileView.filetype) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun wipeData() {
|
||||
fileViews = arrayOf()
|
||||
}
|
||||
|
||||
}
|
||||
|
97
app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/MessagesListModel.kt
Normal file
@ -0,0 +1,97 @@
|
||||
package com.example.wikispot.modelsForAdapters
|
||||
|
||||
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)}"
|
||||
}
|
||||
|
||||
private fun getRandomGenerator(seedString: String): Random {
|
||||
var n: Long = 0
|
||||
for (element in seedString) {
|
||||
n += element.toInt()
|
||||
}
|
||||
|
||||
return Random(n)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
object MessagesSupplier {
|
||||
|
||||
var messages = arrayOf<Message?>()
|
||||
|
||||
fun appendMessage(message: Message) {
|
||||
val array = messages.copyOf(messages.size + 1)
|
||||
array[messages.size] = message
|
||||
messages = array
|
||||
|
||||
if (messages.size > GeneralVariables.max_amount_of_saved_messages) {
|
||||
deleteMessageByIndex(0)
|
||||
println(messages.size)
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteMessageByIndex(i: Int) {
|
||||
messages = messages.copyOfRange(0, i) + messages.copyOfRange(i + 1, messages.size)
|
||||
}
|
||||
|
||||
fun checkIfContains(message: Message, checkTimestamp: Boolean=true): Boolean {
|
||||
for (i in messages.indices) {
|
||||
messages[i]?.let {
|
||||
if (message.senderId == it.senderId) {
|
||||
if (message.content == it.content) {
|
||||
if (checkTimestamp) {
|
||||
if (message.timestamp == it.timestamp) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun clearWaitingMessages() {
|
||||
val positionsOfItemsToRemove = mutableListOf<Int>()
|
||||
for (i in messages.indices) {
|
||||
if (messages[i]!!.timestamp == "waiting") {
|
||||
positionsOfItemsToRemove.add(i)
|
||||
println("waiting at: $i")
|
||||
}
|
||||
}
|
||||
|
||||
var subtractAmount = 0
|
||||
for (index in positionsOfItemsToRemove) {
|
||||
deleteMessageByIndex(index - subtractAmount)
|
||||
subtractAmount += 1
|
||||
}
|
||||
}
|
||||
|
||||
fun getIndexOfLastMessageFromSelf(): Int? {
|
||||
var i: Int? = null
|
||||
for (n in messages.indices) {
|
||||
if (messages[n]!!.senderId == GeneralVariables.id) {
|
||||
i = n
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
fun wipeData() {
|
||||
messages = arrayOf()
|
||||
}
|
||||
|
||||
}
|
30
app/WikiSpot/app/src/main/java/com/example/wikispot/modelsForAdapters/SensorsListModel.kt
Normal file
@ -0,0 +1,30 @@
|
||||
package com.example.wikispot.modelsForAdapters
|
||||
|
||||
data class LabeledValue(val label: String, val value: String)
|
||||
|
||||
|
||||
object LabeledValuesSupplier {
|
||||
|
||||
var labeledValues = arrayOf<LabeledValue?>()
|
||||
|
||||
fun appendLabeledValue(labeledValue: LabeledValue) {
|
||||
val array = labeledValues.copyOf(labeledValues.size + 1)
|
||||
array[labeledValues.size] = labeledValue
|
||||
labeledValues = array
|
||||
}
|
||||
|
||||
fun checkIfContains(labeledValue: LabeledValue): Boolean{
|
||||
for (n in labeledValues.indices) {
|
||||
if (labeledValues[n]!!.label == labeledValue.label) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun wipeData() {
|
||||
labeledValues = arrayOf()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
package com.example.wikispot
|
||||
|
||||
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
|
||||
|
||||
var email:String? = null
|
||||
var phoneNumber: Int? = null
|
||||
|
||||
const val max_amount_of_saved_messages = 32
|
||||
const val variableMissingKeyword = "_[{(V,a,r,i,a,b,l,e, ,m,i,s,s,i,n,g)}]_"
|
||||
|
||||
const val translatePrefix = "[translate]-"
|
||||
|
||||
}
|
||||
|
||||
object IntentsKeys {
|
||||
|
||||
const val startFragment = "start_fragment"
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 connectedServerId: Int? = null
|
||||
var selectedServerId = 0
|
||||
|
||||
const val sensors_keyword = "_[{(S,e,n,s,o,r,s)}]_"
|
||||
|
||||
var totalNumberOfRequestsSent = 0
|
||||
}
|
||||
|
||||
|
||||
object MapManagement {
|
||||
var connectedServerPosition: LatLng? = LatLng(0.toDouble(), 0.toDouble())
|
||||
var lastCoordinates = LatLng(0.toDouble(), 0.toDouble())
|
||||
}
|
||||
|
||||
|
||||
object ScreenParameters {
|
||||
var height = 1
|
||||
var width = 1
|
||||
}
|
||||
|
||||
|
||||
object CustomBackstackVariables {
|
||||
var infoFragmentBackDestination = "exploreFragment"
|
||||
}
|
||||
|
||||
|
||||
object ThemeOptions {
|
||||
var darkTheme = false
|
||||
var moreColors = false
|
||||
}
|
||||
|
||||
object StartDirections {
|
||||
var settingsFragmentStartDirection: String? = null
|
||||
}
|
15
app/WikiSpot/app/src/main/python/server_manager.py
Normal file
@ -0,0 +1,15 @@
|
||||
import requests
|
||||
json_list = []
|
||||
|
||||
|
||||
def init():
|
||||
global json_list
|
||||
json_list = eval(requests.get("http://192.168.1.230:8000/devices_list").text)
|
||||
|
||||
|
||||
def get_length():
|
||||
return len(json_list)
|
||||
|
||||
|
||||
def get_json(i):
|
||||
return json_list[i]
|
11
app/WikiSpot/app/src/main/res/anim/close_rotation_anim.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
|
||||
|
||||
<rotate
|
||||
android:fromDegrees="-180"
|
||||
android:toDegrees="0"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:duration="600"/>
|
||||
|
||||
</set>
|
9
app/WikiSpot/app/src/main/res/anim/fade_in.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="0"
|
||||
android:toAlpha="1"
|
||||
android:duration="600"/>
|
||||
|
||||
</set>
|
9
app/WikiSpot/app/src/main/res/anim/fade_out.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
|
||||
|
||||
<alpha
|
||||
android:fromAlpha="1"
|
||||
android:toAlpha="0"
|
||||
android:duration="600"/>
|
||||
|
||||
</set>
|
11
app/WikiSpot/app/src/main/res/anim/open_rotation_anim.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true">
|
||||
|
||||
<rotate
|
||||
android:fromDegrees="0"
|
||||
android:toDegrees="-180"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:duration="600"/>
|
||||
|
||||
</set>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_checked="true" android:color="?attr/bottomNavBarCheckedItemColor" />
|
||||
<item android:color="?attr/colorOnPrimary" />
|
||||
|
||||
</selector>
|
BIN
app/WikiSpot/app/src/main/res/drawable/blank.png
Normal file
After Width: | Height: | Size: 304 B |
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:centerX="1"
|
||||
android:startColor="?attr/bottomNavBarGradientStartColor"
|
||||
android:endColor="?attr/bottomNavBarGradientEndColor"
|
||||
android:angle="45"
|
||||
android:type="sweep" />
|
||||
</shape>
|
||||
|
||||
<!-- <gradient
|
||||
android:centerX="1"
|
||||
android:startColor="#FCDD94"
|
||||
android:endColor="#C5F8AB"
|
||||
android:angle="45"
|
||||
android:type="sweep" /> -->
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<gradient
|
||||
android:startColor="?attr/chatFragmentGradientStartColor"
|
||||
android:centerColor="?attr/chatFragmentGradientCenterColor"
|
||||
android:endColor="?attr/chatFragmentGradientEndColor"
|
||||
android:angle="90"
|
||||
/>
|
||||
|
||||
<stroke
|
||||
android:color="?attr/chatFragmentBgStrokeColor"
|
||||
android:width="10dp"/>
|
||||
|
||||
</shape>
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:startColor="?attr/contrastingGradientStartColor"
|
||||
android:centerColor="?attr/contrastingGradientCenterColor"
|
||||
android:endColor="?attr/contrastingGradientEndColor"/>
|
||||
|
||||
</shape>
|
@ -0,0 +1,10 @@
|
||||
<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">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,8h-2.81c-0.45,-0.78 -1.07,-1.45 -1.82,-1.96L17,4.41 15.59,3l-2.17,2.17C12.96,5.06 12.49,5 12,5c-0.49,0 -0.96,0.06 -1.41,0.17L8.41,3 7,4.41l1.62,1.63C7.88,6.55 7.26,7.22 6.81,8L4,8v2h2.09c-0.05,0.33 -0.09,0.66 -0.09,1v1L4,12v2h2v1c0,0.34 0.04,0.67 0.09,1L4,16v2h2.81c1.04,1.79 2.97,3 5.19,3s4.15,-1.21 5.19,-3L20,18v-2h-2.09c0.05,-0.33 0.09,-0.66 0.09,-1v-1h2v-2h-2v-1c0,-0.34 -0.04,-0.67 -0.09,-1L20,10L20,8zM14,16h-4v-2h4v2zM14,12h-4v-2h4v2z"/>
|
||||
</vector>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:startColor="?attr/exploreFragmentGradientStartColor"
|
||||
android:centerColor="?attr/exploreFragmentGradientCenterColor"
|
||||
android:endColor="?attr/exploreFragmentGradientEndColor"
|
||||
android:type="linear"
|
||||
android:angle="-90"
|
||||
/>
|
||||
|
||||
</shape>
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:startColor="?attr/homeFragmentGradientStartColor"
|
||||
android:centerColor="?attr/homeFragmentGradientCenterColor"
|
||||
android:endColor="?attr/homeFragmentGradientEndColor"
|
||||
android:angle="135" />
|
||||
</shape>
|
||||
|
||||
<!-- <gradient
|
||||
android:startColor="#79AFFB"
|
||||
android:centerColor="#9E94F8"
|
||||
android:endColor="#EB8FFB"
|
||||
android:angle="135" /> -->
|
@ -0,0 +1,10 @@
|
||||
<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/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M7,10l5,5 5,-5z"/>
|
||||
</vector>
|
@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:tint="?attr/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM6,9h12v2L6,11L6,9zM14,14L6,14v-2h8v2zM18,8L6,8L6,6h12v2z"/>
|
||||
|
@ -0,0 +1,10 @@
|
||||
<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/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z"/>
|
||||
</vector>
|
@ -0,0 +1,10 @@
|
||||
<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/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
|
||||
</vector>
|
@ -0,0 +1,10 @@
|
||||
<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/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
|
||||
</vector>
|
@ -0,0 +1,10 @@
|
||||
<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/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
|
||||
</vector>
|
@ -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/generalIconsColor"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108"
|
||||
android:tint="#2E0F4B">
|
||||
<group android:scaleX="0.21506493"
|
||||
android:scaleY="0.21506493"
|
||||
android:translateX="29.16"
|
||||
android:translateY="36.080723">
|
||||
<group android:translateY="136.26562">
|
||||
<path android:pathData="M83.765625,-16.046875L67.109375,-78L50.234375,-16.046875Q48.265625,-9,47.09375,-5.921875Q45.9375,-2.859375,43.046875,-0.421875Q40.171875,2,35.390625,2Q31.53125,2,29.03125,0.546875Q26.53125,-0.890625,24.984375,-3.53125Q23.4375,-6.1875,22.453125,-9.8125Q21.46875,-13.453125,20.703125,-16.5625L3.546875,-86.21875Q2,-92.296875,2,-95.46875Q2,-99.5,4.8125,-102.25Q7.625,-105,11.765625,-105Q17.46875,-105,19.4375,-101.3125Q21.40625,-97.640625,22.875,-90.625L36.375,-30L51.5,-86.734375Q53.1875,-93.25,54.515625,-96.640625Q55.859375,-100.046875,58.875,-102.515625Q61.90625,-105,67.109375,-105Q72.375,-105,75.296875,-102.40625Q78.21875,-99.828125,79.34375,-96.78125Q80.46875,-93.734375,82.359375,-86.734375L97.625,-30L111.125,-90.625Q112.109375,-95.375,112.984375,-98.0625Q113.859375,-100.75,116,-102.875Q118.15625,-105,122.234375,-105Q126.3125,-105,129.15625,-102.28125Q132,-99.5625,132,-95.46875Q132,-92.578125,130.45312,-86.21875L113.296875,-16.5625Q111.546875,-9.5,110.375,-6.21875Q109.21875,-2.9375,106.4375,-0.46875Q103.671875,2,98.609375,2Q93.828125,2,90.9375,-0.390625Q88.0625,-2.796875,86.9375,-5.78125Q85.8125,-8.78125,83.765625,-16.046875Z"
|
||||
android:fillColor="#2E0F4B"/>
|
||||
<path android:pathData="M224,-30.5Q224,-21.203125,219.23438,-13.796875Q214.46875,-6.390625,205.28125,-2.1875Q196.10938,2,183.51562,2Q168.42188,2,158.60938,-3.640625Q151.6875,-7.78125,147.35938,-14.703125Q143.03125,-21.625,143.03125,-28.171875Q143.03125,-31.96875,145.625,-34.671875Q148.21875,-37.375,152.23438,-37.375Q155.48438,-37.375,157.73438,-35.25Q159.98438,-33.125,161.57812,-28.9375Q163.54688,-23.984375,165.82812,-20.65625Q168.10938,-17.328125,172.25,-15.15625Q176.39062,-13,183.14062,-13Q192.40625,-13,198.20312,-17.359375Q204,-21.71875,204,-28.234375Q204,-33.40625,200.875,-36.625Q197.75,-39.84375,192.78125,-41.546875Q187.82812,-43.25,179.53125,-45.15625Q168.53125,-47.78125,161.10938,-51.28125Q153.70312,-54.796875,149.34375,-60.859375Q145,-66.921875,145,-75.921875Q145,-84.515625,149.59375,-91.171875Q154.1875,-97.84375,162.875,-101.421875Q171.5625,-105,183.32812,-105Q192.70312,-105,199.54688,-102.625Q206.40625,-100.25,210.92188,-96.3125Q215.45312,-92.375,217.53125,-88.046875Q219.625,-83.71875,219.625,-79.609375Q219.625,-75.84375,217.04688,-72.828125Q214.48438,-69.8125,210.65625,-69.8125Q207.15625,-69.8125,205.34375,-71.71875Q203.53125,-73.640625,201.40625,-78Q198.59375,-83.65625,194.65625,-86.828125Q190.71875,-90,182,-90Q173.92188,-90,168.95312,-86.421875Q164,-82.84375,164,-77.8125Q164,-74.703125,165.6875,-72.4375Q167.375,-70.171875,170.32812,-68.53125Q173.28125,-66.90625,176.29688,-65.984375Q179.32812,-65.0625,186.28125,-63.296875Q194.85938,-61.25,201.8125,-58.765625Q208.78125,-56.28125,213.65625,-52.734375Q218.53125,-49.203125,221.26562,-43.78125Q224,-38.359375,224,-30.5Z"
|
||||
android:fillColor="#2E0F4B"/>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:startColor="?attr/infoFragmentGradientStartColor"
|
||||
android:centerColor="?attr/infoFragmentGradientCenterColor"
|
||||
android:endColor="?attr/infoFragmentGradientEndColor"
|
||||
android:angle="225"/>
|
||||
|
||||
</shape>
|
@ -0,0 +1,10 @@
|
||||
<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/generalIconsColor">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||
</vector>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:centerY="0.7"
|
||||
android:centerX="1.1"
|
||||
android:startColor="?attr/settingsFragmentGradientStartColor"
|
||||
android:centerColor="?attr/settingsFragmentGradientCenterColor"
|
||||
android:endColor="?attr/settingsFragmentGradientEndColor"
|
||||
android:type="sweep"/>
|
||||
|
||||
</shape>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:startColor="?attr/textBackgroundGradientStartColor"
|
||||
android:endColor="?attr/textBackgroundGradientEndColor"
|
||||
android:angle="45"
|
||||
android:type="linear" />
|
||||
</shape>
|
@ -10,9 +10,13 @@
|
||||
android:id="@+id/mainBottomNavigationView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
app:itemRippleColor="?attr/bottomNavBarRippleColor"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:itemIconTint="@color/bottom_nav_bar_item_color"
|
||||
app:itemTextColor="@color/bottom_nav_bar_item_color"
|
||||
android:background="@drawable/bottom_nav_bar_gradient_background"
|
||||
app:menu="@menu/main_bottom_nav_menu" />
|
||||
|
||||
<fragment
|
||||
@ -27,4 +31,5 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/main_activity_navigation" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
67
app/WikiSpot/app/src/main/res/layout/explore_list_item.xml
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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_margin="5dp"
|
||||
android:backgroundTint="?attr/exploreFragmentListItemBackgroundColor"
|
||||
card_view:cardCornerRadius="10dp"
|
||||
card_view:cardElevation="4dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="4dp">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_img"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent"
|
||||
card_view:srcCompat="@drawable/ic_baseline_image_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
card_view:layout_constraintStart_toEndOf="@+id/item_img"
|
||||
card_view:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintEnd_toStartOf="@+id/item_location_img"
|
||||
card_view:layout_constraintHorizontal_bias="0.15"
|
||||
card_view:layout_constraintStart_toEndOf="@+id/item_img"
|
||||
card_view:layout_constraintTop_toBottomOf="@+id/item_title"
|
||||
tools:text="Description" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_location_img"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent"
|
||||
card_view:srcCompat="@drawable/loacation_vector_asset" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
107
app/WikiSpot/app/src/main/res/layout/file_view.xml
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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_marginLeft="4dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:backgroundTint="?attr/fileViewBackgroundColor"
|
||||
card_view:cardCornerRadius="10dp"
|
||||
card_view:cardElevation="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/filenameText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="28dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Filename" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/showFileBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="36dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:scaleX="4"
|
||||
android:scaleY="4"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent"
|
||||
card_view:srcCompat="@drawable/ic_baseline_arrow_drop_down_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="52dp"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
android:textSize="0sp"
|
||||
card_view:layout_constraintBottom_toTopOf="@+id/imageContent"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintHorizontal_bias="0.497"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:layout_constraintTop_toBottomOf="@+id/filenameText"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
card_view:layout_constraintBottom_toTopOf="@+id/pdfContent"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintHorizontal_bias="0.5"
|
||||
card_view:layout_constraintStart_toEndOf="@+id/filenameText"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:srcCompat="@drawable/blank" />
|
||||
|
||||
<com.github.barteksc.pdfviewer.PDFView
|
||||
android:id="@+id/pdfContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
android:layout_margin="5dp"
|
||||
android:visibility="gone"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintHorizontal_bias="0.5"
|
||||
card_view:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/downloadFileBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:visibility="gone"
|
||||
card_view:layout_constraintBottom_toBottomOf="@+id/showFileBtn"
|
||||
card_view:layout_constraintEnd_toStartOf="@+id/showFileBtn"
|
||||
card_view:layout_constraintTop_toTopOf="@+id/showFileBtn"
|
||||
card_view:srcCompat="@drawable/ic_baseline_download_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileDescription"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
card_view:layout_constraintEnd_toStartOf="@+id/showFileBtn"
|
||||
card_view:layout_constraintStart_toStartOf="@+id/filenameText"
|
||||
card_view:layout_constraintTop_toBottomOf="@+id/filenameText"
|
||||
tools:text="file_description" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
124
app/WikiSpot/app/src/main/res/layout/fragment_another_debug.xml
Normal file
@ -0,0 +1,124 @@
|
||||
<?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="?attr/debugFragmentBackground"
|
||||
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:textColor="@color/white"
|
||||
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:textColor="@color/white"
|
||||
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:textColor="@color/white"
|
||||
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>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/attributePathInput"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="50dp"
|
||||
android:ems="10"
|
||||
android:textColor="@color/white"
|
||||
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_marginTop="8dp"
|
||||
android:textColor="@color/white"
|
||||
android:text="create view connection"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="@+id/attributePathInput"
|
||||
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:textColor="@color/white"
|
||||
android:text="stop connection"
|
||||
android:textSize="13sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/attributePathInput"
|
||||
app:layout_constraintStart_toEndOf="@+id/attributePathInput"
|
||||
app:layout_constraintTop_toTopOf="@+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>
|
@ -4,21 +4,55 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#E11976D2"
|
||||
android:background="@drawable/chat_fragment_gradient_background"
|
||||
tools:background="@drawable/chat_fragment_gradient_background"
|
||||
tools:context=".fragments.chatFragment">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Chat Fragment"
|
||||
android:textStyle="bold"
|
||||
android:textSize="24sp"
|
||||
android:textColor="@android:color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/chat_messages_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/writeBar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Chat Fragment" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/writeBar"
|
||||
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"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
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>
|
132
app/WikiSpot/app/src/main/res/layout/fragment_debug.xml
Normal file
@ -0,0 +1,132 @@
|
||||
<?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="?attr/debugFragmentBackground"
|
||||
tools:context=".fragments.debugFragment">
|
||||
|
||||
<Button
|
||||
android:id="@+id/goSecondDebugFragmentBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:text="2"
|
||||
app:layout_constraintEnd_toEndOf="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="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:text="get number of sent requests"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/goSecondDebugFragmentBtn"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/debugFragmentTitle" />
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView3"
|
||||
android:layout_width="252dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/clearServerConnectionsBtn">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/outputText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:background="#6A5252"
|
||||
android:backgroundTint="#E39595"
|
||||
android:padding="4dp"
|
||||
android:text="output" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/changeUrlBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:text="change url"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/editTextIp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextIp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:ems="10"
|
||||
android:inputType="textPersonName"
|
||||
app:layout_constraintEnd_toEndOf="@+id/scrollView3"
|
||||
app:layout_constraintStart_toStartOf="@+id/scrollView3"
|
||||
app:layout_constraintTop_toBottomOf="@+id/scrollView3" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/clearServerConnectionsBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:text="clear server connections"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/getNumberOfSentRequestsBtn" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/restartAppPartiallyBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:text="restart app partially"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
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:textColor="@color/white"
|
||||
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>
|
@ -4,20 +4,32 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#C200897B"
|
||||
android:background="@drawable/explore_fragment_gradient_background"
|
||||
tools:background="@drawable/explore_fragment_gradient_background"
|
||||
tools:context=".fragments.exploreFragment">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Explore Fragment"
|
||||
android:textStyle="bold"
|
||||
android:textSize="24sp"
|
||||
android:textColor="@android:color/white"
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/explore_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="32dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,23 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView 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="#7CB342"
|
||||
tools:context=".fragments.homeFragment">
|
||||
android:background="@drawable/home_fragment_gradient_background"
|
||||
tools:background="@drawable/home_fragment_gradient_background"
|
||||
tools:context=".fragments.homeFragment"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Home Fragment"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<TextView
|
||||
android:id="@+id/home_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="60dp"
|
||||
android:background="@drawable/text_background_gradient"
|
||||
android:padding="5dp"
|
||||
android:text="@string/home"
|
||||
android:textColor="?attr/textOnTextBgColor"
|
||||
android:textSize="28sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/homeFragmentInnerFragment"
|
||||
android:name="com.example.wikispot.fragments.infoFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
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.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
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>
|
||||
|
||||
|
||||
</ScrollView>
|
144
app/WikiSpot/app/src/main/res/layout/fragment_info.xml
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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="@drawable/info_fragment_gradient_background"
|
||||
tools:background="@drawable/info_fragment_gradient_background"
|
||||
tools:context=".fragments.infoFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mainTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:background="@drawable/text_background_gradient"
|
||||
android:padding="5dp"
|
||||
android:text=""
|
||||
android:textColor="?attr/textOnTextBgColor"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/mainImage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:src="@drawable/ic_baseline_image_24"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/mainTitle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mainDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text=""
|
||||
android:textAlignment="center"
|
||||
android:textColor="?attr/secondaryTextColor"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/mainImage" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/labeled_values_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false"/>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:background="@drawable/text_background_gradient"
|
||||
android:padding="4dp"
|
||||
android:text="@string/files"
|
||||
android:textAlignment="center"
|
||||
android:textColor="?attr/textOnTextBgColor"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
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>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/file_views_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/locationBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:src="@drawable/loacation_vector_asset"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/phoneBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:src="@drawable/ic_baseline_phone_24"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/emailBtn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:src="@drawable/ic_baseline_email_24"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
@ -1,23 +1,20 @@
|
||||
<?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"
|
||||
<LinearLayout android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FBC02D"
|
||||
tools:context=".fragments.mapFragment">
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal">
|
||||
<fragment xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/map"
|
||||
android:name="com.google.android.gms.maps.SupportMapFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.mapFragment" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/navControllerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Map Fragment"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
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:layout_weight="1"
|
||||
android:text=""
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
@ -4,20 +4,67 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F57C00"
|
||||
android:background="@drawable/settings_fragment_gradient_background"
|
||||
tools:background="@drawable/settings_fragment_gradient_background"
|
||||
tools:context=".fragments.settingsFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/debugBtn"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
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:text="Settings Fragment"
|
||||
android:textColor="@android:color/white"
|
||||
android:layout_marginStart="64dp"
|
||||
android:layout_marginTop="88dp"
|
||||
android:text="@string/dark_theme"
|
||||
android:background="@drawable/text_background_gradient"
|
||||
android:padding="5dp"
|
||||
android:textColor="?attr/textOnTextBgColor"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
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"
|
||||
tools:ignore="UseSwitchCompatOrMaterialXml" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/moreColorsSwitchText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="@string/more_colors"
|
||||
android:background="@drawable/text_background_gradient"
|
||||
android:padding="5dp"
|
||||
android:textColor="?attr/textOnTextBgColor"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="@+id/darkThemeSwitchText"
|
||||
app:layout_constraintStart_toStartOf="@+id/darkThemeSwitchText"
|
||||
app:layout_constraintTop_toBottomOf="@+id/darkThemeSwitchText" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/moreColorsSwitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/moreColorsSwitchText"
|
||||
app:layout_constraintStart_toEndOf="@+id/moreColorsSwitchText"
|
||||
app:layout_constraintTop_toTopOf="@+id/moreColorsSwitchText"
|
||||
tools:ignore="UseSwitchCompatOrMaterialXml" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
47
app/WikiSpot/app/src/main/res/layout/labeled_value_item.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:backgroundTint="@color/invisible"
|
||||
card_view:cardElevation="0dp"
|
||||
card_view:cardCornerRadius="5dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/contrasting_gradient_background"
|
||||
android:padding="4dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/label"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
android:textSize="30sp"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintEnd_toStartOf="@+id/value"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
android:textSize="30sp"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
50
app/WikiSpot/app/src/main/res/layout/message.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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_margin="5dp"
|
||||
android:backgroundTint="?attr/messageBackground"
|
||||
card_view:cardCornerRadius="6dp"
|
||||
card_view:cardElevation="0dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="4dp"
|
||||
android:textAlignment="textStart">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message_author_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintHorizontal_bias="0.5"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Author" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message_content_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:textAlignment="textStart"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/generalTextColor"
|
||||
card_view:layout_constraintBottom_toBottomOf="parent"
|
||||
card_view:layout_constraintEnd_toEndOf="parent"
|
||||
card_view:layout_constraintHorizontal_bias="0.5"
|
||||
card_view:layout_constraintStart_toStartOf="parent"
|
||||
card_view:layout_constraintTop_toBottomOf="@+id/message_author_text"
|
||||
tools:text="message content" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 26 KiB |
@ -16,14 +16,24 @@
|
||||
android:label="fragment_explore"
|
||||
tools:layout="@layout/fragment_explore">
|
||||
<action
|
||||
android:id="@+id/action_exploreFragment_to_mapFragment"
|
||||
android:id="@+id/navigateToMapFragment"
|
||||
app:destination="@id/mapFragment" />
|
||||
<action
|
||||
android:id="@+id/navigateToInfoFragment"
|
||||
app:destination="@id/infoFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/homeFragment"
|
||||
android:name="com.example.wikispot.fragments.homeFragment"
|
||||
android:label="fragment_home"
|
||||
tools:layout="@layout/fragment_home" />
|
||||
tools:layout="@layout/fragment_home" >
|
||||
<action
|
||||
android:id="@+id/homeFragment_to_chatFragment"
|
||||
app:destination="@id/chatFragment" />
|
||||
<action
|
||||
android:id="@+id/homeFragment_to_mapFragment"
|
||||
app:destination="@id/mapFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/mapFragment"
|
||||
android:name="com.example.wikispot.fragments.mapFragment"
|
||||
@ -32,10 +42,59 @@
|
||||
<action
|
||||
android:id="@+id/action_mapFragment_to_exploreFragment"
|
||||
app:destination="@id/exploreFragment" />
|
||||
<argument
|
||||
android:name="location"
|
||||
app:argType="com.google.android.gms.maps.model.LatLng" />
|
||||
<action
|
||||
android:id="@+id/mapFragment_to_infoFragment"
|
||||
app:destination="@id/infoFragment" >
|
||||
</action>
|
||||
<argument
|
||||
android:name="loadLastCoordinates"
|
||||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/settingsFragment"
|
||||
android:name="com.example.wikispot.fragments.settingsFragment"
|
||||
android:label="fragment_settings"
|
||||
tools:layout="@layout/fragment_settings" />
|
||||
tools:layout="@layout/fragment_settings" >
|
||||
<action
|
||||
android:id="@+id/navigateToDebugFragment"
|
||||
app:destination="@id/debugFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/debugFragment"
|
||||
android:name="com.example.wikispot.fragments.debugFragment"
|
||||
android:label="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>
|
||||
<fragment
|
||||
android:id="@+id/infoFragment"
|
||||
android:name="com.example.wikispot.fragments.infoFragment"
|
||||
android:label="fragment_info"
|
||||
tools:layout="@layout/fragment_info" >
|
||||
<argument
|
||||
android:name="executeLoadFuntion"
|
||||
app:argType="boolean"
|
||||
android:defaultValue="false" />
|
||||
<action
|
||||
android:id="@+id/navigateBackToExploreFragment"
|
||||
app:destination="@id/exploreFragment" />
|
||||
<action
|
||||
android:id="@+id/infoFragment_to_mapFragment"
|
||||
app:destination="@id/mapFragment" />
|
||||
</fragment>
|
||||
</navigation>
|
17
app/WikiSpot/app/src/main/res/values-de-rDE/strings.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?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>
|
||||
<string name="closed">Geschlossen</string>
|
||||
<string name="open">Öffnen</string>
|
||||
<string name="number_of_people">Anzahl der Personen :</string>
|
||||
<string name="status">Status :</string>
|
||||
<string name="temperature">Temperatur :</string>
|
||||
<string name="more_colors">Mehr Farben</string>
|
||||
</resources>
|
17
app/WikiSpot/app/src/main/res/values-es-rES/strings.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">WikiSpot</string>
|
||||
<string name="chat">Chat</string>
|
||||
<string name="explore">Explorar</string>
|
||||
<string name="home">Casa</string>
|
||||
<string name="map">Mapa</string>
|
||||
<string name="settings">Ajustes</string>
|
||||
<string name="files">Archivos</string>
|
||||
<string name="dark_theme">Tema oscuro</string>
|
||||
<string name="temperature">Temperatura :</string>
|
||||
<string name="status">Estado :</string>
|
||||
<string name="number_of_people">Número de personas:</string>
|
||||
<string name="open">Abierto</string>
|
||||
<string name="closed">Cerrado</string>
|
||||
<string name="more_colors">Mas colores</string>
|
||||
</resources>
|
17
app/WikiSpot/app/src/main/res/values-fr-rFR/strings.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">WikiSpot</string>
|
||||
<string name="dark_theme">Thème sombre</string>
|
||||
<string name="files">Des dossiers</string>
|
||||
<string name="settings">Paramètres</string>
|
||||
<string name="map">Carte</string>
|
||||
<string name="home">Domicile</string>
|
||||
<string name="explore">Explorer</string>
|
||||
<string name="chat">Discuter</string>
|
||||
<string name="status">Statut :</string>
|
||||
<string name="temperature">Température :</string>
|
||||
<string name="number_of_people">Nombre de personnes :</string>
|
||||
<string name="open">Ouvert</string>
|
||||
<string name="closed">Fermé</string>
|
||||
<string name="more_colors">Plus de couleurs</string>
|
||||
</resources>
|
17
app/WikiSpot/app/src/main/res/values-ja-rJP/strings.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?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>
|
||||
<string name="closed">閉まっている</string>
|
||||
<string name="open">開いた</string>
|
||||
<string name="number_of_people">人々の数 :</string>
|
||||
<string name="status">状態 :</string>
|
||||
<string name="temperature">温度:</string>
|
||||
<string name="more_colors">より多くの色</string>
|
||||
</resources>
|
@ -1,16 +0,0 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.WikiSpot" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- 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>
|
||||
</resources>
|