updates
This commit is contained in:
parent
8051c2c4ed
commit
ccfa694180
|
|
@ -4,6 +4,14 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DropdownSelection timestamp="2024-06-12T15:02:16.596717208Z">
|
||||||
|
<Target type="DEFAULT_BOOT">
|
||||||
|
<handle>
|
||||||
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=62f6513d" />
|
||||||
|
</handle>
|
||||||
|
</Target>
|
||||||
|
</DropdownSelection>
|
||||||
|
<DialogSelection />
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import com.android.build.api.dsl.Packaging
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.jetbrains.kotlin.android)
|
alias(libs.plugins.jetbrains.kotlin.android)
|
||||||
|
|
@ -28,7 +30,11 @@ android {
|
||||||
targetCompatibility = JavaVersion.VERSION_16
|
targetCompatibility = JavaVersion.VERSION_16
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "16"
|
||||||
|
}
|
||||||
|
|
||||||
|
packaging {
|
||||||
|
resources.excludes.add("META-INF/native-image/org.mongodb/bson/native-image.properties")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,4 +59,11 @@ dependencies {
|
||||||
|
|
||||||
//MongoDB
|
//MongoDB
|
||||||
implementation(libs.mongodb.driver.kotlin.sync)
|
implementation(libs.mongodb.driver.kotlin.sync)
|
||||||
|
|
||||||
|
//Api Requests
|
||||||
|
implementation(libs.retrofit.v2110)
|
||||||
|
implementation(libs.converter.jackson)
|
||||||
|
|
||||||
|
//Jsoup
|
||||||
|
implementation(libs.jsoup.jsoup)
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,13 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
<uses-feature android:name="android.hardware.camera"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
package xyz.r0r5chach.dermy_app
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.fragment.app.findFragment
|
||||||
|
import androidx.lifecycle.ReportFragment.Companion.reportFragment
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.preference.PreferenceViewHolder
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.awaitAll
|
||||||
|
import kotlinx.coroutines.joinAll
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.MediaType
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import org.json.JSONObject
|
||||||
|
import xyz.r0r5chach.dermy_app.api.DermyApi
|
||||||
|
import xyz.r0r5chach.dermy_app.fragments.SettingsFragment
|
||||||
|
import kotlin.math.log
|
||||||
|
|
||||||
|
|
||||||
|
@DelicateCoroutinesApi
|
||||||
|
class AccountPreference @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
): Preference(context, attrs, defStyleAttr) {
|
||||||
|
private val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
private lateinit var usernameField: EditText
|
||||||
|
private lateinit var passwordField: EditText
|
||||||
|
private lateinit var loggedIn: List<View>
|
||||||
|
private lateinit var loggedOut: List<View>
|
||||||
|
|
||||||
|
init {
|
||||||
|
widgetLayoutResource = R.layout.fragment_account
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||||
|
super.onBindViewHolder(holder)
|
||||||
|
usernameField = holder.findViewById(R.id.username_field) as EditText
|
||||||
|
passwordField = holder.findViewById(R.id.password_field) as EditText
|
||||||
|
|
||||||
|
val loginButton = holder.findViewById(R.id.login_button)
|
||||||
|
val registerButton = holder.findViewById(R.id.register_button)
|
||||||
|
val logOutButton = holder.findViewById(R.id.logout_button)
|
||||||
|
val backupButton = holder.findViewById(R.id.backup_button)
|
||||||
|
val restoreButton = holder.findViewById(R.id.restore_button)
|
||||||
|
|
||||||
|
loggedIn = listOf(backupButton, restoreButton, logOutButton)
|
||||||
|
loggedOut = listOf(usernameField, passwordField, loginButton, registerButton)
|
||||||
|
|
||||||
|
checkSet()
|
||||||
|
|
||||||
|
loginButton.setOnClickListener {
|
||||||
|
val api = DermyApi(preferences.getString("instance_url", null)!!).getInstance()
|
||||||
|
val toast = Toast.makeText(context, "User does not exist", Toast.LENGTH_SHORT)
|
||||||
|
GlobalScope.launch {
|
||||||
|
try {
|
||||||
|
val saltRes = api.getSalt(usernameField.text.toString())
|
||||||
|
|
||||||
|
if (saltRes.containsKey("_salt")) {
|
||||||
|
val salt = saltRes["_salt"]
|
||||||
|
val hashedPassword = "abc" //TODO: Hash password
|
||||||
|
val body =
|
||||||
|
RequestBody.create(
|
||||||
|
MediaType.get("application/json"),JSONObject()
|
||||||
|
.put("username", usernameField.text.toString())
|
||||||
|
.put("_auth", JSONObject().put("_hash", hashedPassword)).toString())
|
||||||
|
|
||||||
|
|
||||||
|
val loginRes = api.login(body)
|
||||||
|
|
||||||
|
if (loginRes.containsKey("_api_key")) {
|
||||||
|
preferences.edit()
|
||||||
|
.putString("api_key", loginRes["_api_key"])
|
||||||
|
.apply()
|
||||||
|
toast.setText("Login successful")
|
||||||
|
toast.show()
|
||||||
|
back()
|
||||||
|
} else {
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e: Exception) {
|
||||||
|
Log.d("$e", "$e")
|
||||||
|
toast.setText("Login request has failed")
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
registerButton.setOnClickListener {
|
||||||
|
val api = DermyApi(preferences.getString("instance_url", null)!!).getInstance()
|
||||||
|
val toast = Toast.makeText(context, "User already exists", Toast.LENGTH_SHORT)
|
||||||
|
GlobalScope.launch {
|
||||||
|
try {
|
||||||
|
val salt = "1234" //TODO: Make salt
|
||||||
|
val hashedPassword = "abc" //TODO: hash password
|
||||||
|
val body =
|
||||||
|
RequestBody.create(MediaType.get("application/json"),
|
||||||
|
JSONObject()
|
||||||
|
.put("username", usernameField.text.toString())
|
||||||
|
.put("_auth", JSONObject().put("_salt", salt).put("_hash", hashedPassword))
|
||||||
|
.toString())
|
||||||
|
val registerRes = api.register(body)
|
||||||
|
|
||||||
|
if (registerRes.containsKey("_success")) {
|
||||||
|
toast.setText("Registration successful")
|
||||||
|
toast.show()
|
||||||
|
} else {
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
|
Log.d("$e", "$e")
|
||||||
|
toast.setText("Registration request failed")
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logOutButton.setOnClickListener {
|
||||||
|
val api = DermyApi(preferences.getString("instance_url", null)!!).getInstance()
|
||||||
|
val toast = Toast.makeText(context, "Your API key does not belong to any user", Toast.LENGTH_SHORT)
|
||||||
|
|
||||||
|
GlobalScope.launch {
|
||||||
|
try {
|
||||||
|
val key = preferences.getString("api_key", null)!!
|
||||||
|
preferences.edit().remove("api_key").apply()
|
||||||
|
|
||||||
|
|
||||||
|
val logoutRes = api.logout(key)
|
||||||
|
if (logoutRes.containsKey("_success")) {
|
||||||
|
toast.setText("Logout successful")
|
||||||
|
toast.show()
|
||||||
|
back()
|
||||||
|
} else {
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
|
Log.d("$e", "$e")
|
||||||
|
toast.setText("Logout request failed")
|
||||||
|
toast.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
backupButton.setOnClickListener {
|
||||||
|
//TODO: Handle Backup
|
||||||
|
|
||||||
|
Toast.makeText(context, "Backup Button Pressed", Toast.LENGTH_SHORT).show() //TODO: Change text to relevant message
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreButton.setOnClickListener {
|
||||||
|
//TODO: Handle Restore
|
||||||
|
Toast.makeText(context, "Restore Button Pressed", Toast.LENGTH_SHORT).show() //TODO: Change text to relevant message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private fun checkSet() {
|
||||||
|
if(preferences.getString("api_key", null) != null) {
|
||||||
|
changeView(loggedIn, loggedOut)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
changeView(loggedOut, loggedIn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun changeView(show: List<View>, hide: List<View>) {
|
||||||
|
show.forEach { it.visibility = View.VISIBLE }
|
||||||
|
hide.forEach { it.visibility = View.GONE }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun back() {
|
||||||
|
usernameField.findFragment<SettingsFragment>().parentFragmentManager.popBackStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package xyz.r0r5chach.dermy_app
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
|
||||||
|
class LinksAdapter(private val dataSet: Array<String>): RecyclerView.Adapter<LinksAdapter.ViewHolder>() {
|
||||||
|
class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
|
||||||
|
private val title: TextView = view.findViewById(R.id.link_item_title)
|
||||||
|
|
||||||
|
fun bind(url: String) {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
try {
|
||||||
|
updateItem(getInfo(url))
|
||||||
|
}
|
||||||
|
catch (_: Exception) {
|
||||||
|
updateItem(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getInfo(url: String): Document {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
Jsoup.connect(url).get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateItem(result: Document) {
|
||||||
|
title.text = result.title()
|
||||||
|
title.setOnClickListener {
|
||||||
|
title.context.startActivity(
|
||||||
|
Intent(Intent.ACTION_VIEW, Uri.parse(result.location()))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private fun updateItem(result: String) {
|
||||||
|
title.text = result
|
||||||
|
title.setOnClickListener {
|
||||||
|
title.context.startActivity(
|
||||||
|
Intent(Intent.ACTION_VIEW, Uri.parse(result))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.links_row_item, parent, false)
|
||||||
|
return ViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount() = dataSet.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(dataSet[position])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ import xyz.r0r5chach.dermy_app.fragments.HomeFragment
|
||||||
class MainActivity: AppCompatActivity(R.layout.activity_main) {
|
class MainActivity: AppCompatActivity(R.layout.activity_main) {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
supportFragmentManager.commit {
|
supportFragmentManager.commit {
|
||||||
setReorderingAllowed(true)
|
setReorderingAllowed(true)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package xyz.r0r5chach.dermy_app.api
|
||||||
|
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.json.JSONObject
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.jackson.JacksonConverterFactory
|
||||||
|
|
||||||
|
class DermyApi(private val url: String) {
|
||||||
|
fun getInstance(): DermyApiService {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(url)
|
||||||
|
.addConverterFactory(JacksonConverterFactory.create())
|
||||||
|
.build().create(DermyApiService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package xyz.r0r5chach.dermy_app.api
|
||||||
|
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import org.json.JSONObject
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Header
|
||||||
|
import retrofit2.http.HeaderMap
|
||||||
|
import okhttp3.Headers
|
||||||
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Path
|
||||||
|
|
||||||
|
interface DermyApiService {
|
||||||
|
@GET("/account/sign-in/{username}")
|
||||||
|
suspend fun getSalt(@Path("username") username: String): Map<String, String>
|
||||||
|
|
||||||
|
@POST("/account/sign-in")
|
||||||
|
suspend fun login(@Body loginForm: RequestBody): Map<String, String>
|
||||||
|
|
||||||
|
@POST("/account/sign-up")
|
||||||
|
suspend fun register(@Body loginForm: RequestBody): Map<String,String>
|
||||||
|
|
||||||
|
@GET("/account/sign-out/{api}")
|
||||||
|
suspend fun logout(@Path("api") apiKey: String): Map<String,String>
|
||||||
|
|
||||||
|
@GET("/account/restore/{api}")
|
||||||
|
suspend fun restore(@Path("api") apiKey: String): JSONObject
|
||||||
|
|
||||||
|
@POST("/account/backup/{api}")
|
||||||
|
suspend fun backup(@Path("api") apiKey: String, @Body backup: RequestBody): JSONObject
|
||||||
|
|
||||||
|
@GET("/predict/{api}")
|
||||||
|
suspend fun predict(@Path("api") apiKey: String, @Body image: RequestBody): JSONObject
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package xyz.r0r5chach.dermy_app.db.locations;
|
||||||
|
|
||||||
|
public enum LocationCategory {
|
||||||
|
Front,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Back
|
||||||
|
}
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
package xyz.r0r5chach.dermy_app.fragments;
|
|
||||||
|
|
||||||
public class AccountFragment {
|
|
||||||
//TODO: Login if no API Key
|
|
||||||
}
|
|
||||||
|
|
@ -79,7 +79,7 @@ class CameraFragment : Fragment(R.layout.fragment_camera) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun takePhoto() {
|
private fun takePhoto() {
|
||||||
val photoFile = File(context?.getExternalFilesDir(null), "${System.currentTimeMillis()}.jpg") //TODO: Save image as MoleId
|
val photoFile = File(context?.filesDir, "${System.currentTimeMillis()}.jpg") //TODO: Save image as MoleId
|
||||||
val outputFileOptions: OutputFileOptions = OutputFileOptions.Builder(photoFile).build()
|
val outputFileOptions: OutputFileOptions = OutputFileOptions.Builder(photoFile).build()
|
||||||
imageCapture.takePicture(
|
imageCapture.takePicture(
|
||||||
outputFileOptions,
|
outputFileOptions,
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,23 @@ package xyz.r0r5chach.dermy_app.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Button
|
import android.widget.ImageButton
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
import androidx.fragment.app.replace
|
import androidx.fragment.app.replace
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import xyz.r0r5chach.dermy_app.R
|
import xyz.r0r5chach.dermy_app.R
|
||||||
|
|
||||||
|
@DelicateCoroutinesApi
|
||||||
class HomeFragment : Fragment(R.layout.fragment_home) {
|
class HomeFragment : Fragment(R.layout.fragment_home) {
|
||||||
private var buttons: IntArray = intArrayOf(R.id.add_mole_button, R.id.map_button, R.id.links_button, R.id.settings_button)
|
private var buttons: IntArray = intArrayOf(R.id.add_mole_button, R.id.map_button, R.id.links_button, R.id.settings_button)
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
for (button in buttons) {
|
for (button in buttons) {
|
||||||
view.findViewById<Button>(button).setOnClickListener {
|
view.findViewById<ImageButton>(button).setOnClickListener {
|
||||||
initButton(button)
|
initButton(button)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,24 +32,30 @@ class HomeFragment : Fragment(R.layout.fragment_home) {
|
||||||
manager.commit {
|
manager.commit {
|
||||||
setReorderingAllowed(true)
|
setReorderingAllowed(true)
|
||||||
replace<MoleFragment>(R.id.fragment_container, null)
|
replace<MoleFragment>(R.id.fragment_container, null)
|
||||||
|
addToBackStack(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.map_button -> {
|
R.id.map_button -> {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
manager.commit {
|
manager.commit {
|
||||||
setReorderingAllowed(true)
|
setReorderingAllowed(true)
|
||||||
replace<MapFragment>(R.id.fragment_container, null)
|
replace<MapFragment>(R.id.fragment_container, null)
|
||||||
|
addToBackStack(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.links_button -> {
|
R.id.links_button -> {
|
||||||
manager.commit {
|
manager.commit {
|
||||||
setReorderingAllowed(true)
|
setReorderingAllowed(true)
|
||||||
replace<LinksFragment>(R.id.fragment_container, null)
|
replace<LinksFragment>(R.id.fragment_container, null)
|
||||||
|
addToBackStack(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.settings_button -> {
|
R.id.settings_button -> {
|
||||||
manager.commit {
|
manager.commit {
|
||||||
setReorderingAllowed(true)
|
setReorderingAllowed(true)
|
||||||
replace<SettingsFragment>(R.id.fragment_container, null)
|
replace<SettingsFragment>(R.id.fragment_container, null)
|
||||||
|
addToBackStack(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package xyz.r0r5chach.dermy_app.fragments;
|
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
public class LinksFragment extends Fragment {
|
|
||||||
//TODO: NHS links etc
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package xyz.r0r5chach.dermy_app.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.ListView
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
|
import xyz.r0r5chach.dermy_app.LinksAdapter
|
||||||
|
import xyz.r0r5chach.dermy_app.R
|
||||||
|
|
||||||
|
class LinksFragment : Fragment(R.layout.fragment_links) {
|
||||||
|
//TODO: NHS links etc
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
val list = view.findViewById<RecyclerView>(R.id.links_list)
|
||||||
|
val links = resources.getStringArray(R.array.links)
|
||||||
|
|
||||||
|
val adapter = LinksAdapter(links)
|
||||||
|
list.layoutManager = LinearLayoutManager(context)
|
||||||
|
list.adapter = adapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package xyz.r0r5chach.dermy_app.fragments;
|
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
public class MapFragment extends Fragment {
|
|
||||||
//TODO: Map of all locations
|
|
||||||
//When pressed route to LocationFragment with specified location
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package xyz.r0r5chach.dermy_app.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import xyz.r0r5chach.dermy_app.R
|
||||||
|
import xyz.r0r5chach.dermy_app.db.locations.LocationCategory
|
||||||
|
|
||||||
|
class MapFragment : Fragment(R.layout.fragment_map) {
|
||||||
|
private lateinit var pager: ViewPager2
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
pager = view.findViewById(R.id.map_pager)
|
||||||
|
pager.adapter = MapPagerAdapter(requireActivity())
|
||||||
|
pager.post { pager.setCurrentItem(1, false); pager.visibility = View.VISIBLE }
|
||||||
|
|
||||||
|
}
|
||||||
|
private inner class MapPagerAdapter(fragment: FragmentActivity) : FragmentStateAdapter(fragment) {
|
||||||
|
override fun getItemCount(): Int = 4
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return when(position) {
|
||||||
|
0 -> MapPageFragment(LocationCategory.Left)
|
||||||
|
2 -> MapPageFragment(LocationCategory.Right)
|
||||||
|
3 -> MapPageFragment(LocationCategory.Back)
|
||||||
|
else -> MapPageFragment(LocationCategory.Front)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package xyz.r0r5chach.dermy_app.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.ContactsContract.CommonDataKinds.Im
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import xyz.r0r5chach.dermy_app.R
|
||||||
|
import xyz.r0r5chach.dermy_app.db.locations.LocationCategory
|
||||||
|
|
||||||
|
class MapPageFragment(private val category: LocationCategory): Fragment(R.layout.fragment_map_page) {
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val image = view.findViewById<ImageView>(R.id.category_image)
|
||||||
|
|
||||||
|
when(category) {
|
||||||
|
LocationCategory.Front -> {
|
||||||
|
image.setImageResource(R.drawable.front_body)
|
||||||
|
}
|
||||||
|
LocationCategory.Left -> {
|
||||||
|
image.setImageResource(R.drawable.side_body)
|
||||||
|
}
|
||||||
|
LocationCategory.Back -> {
|
||||||
|
image.setImageResource(R.drawable.back_body)
|
||||||
|
}
|
||||||
|
LocationCategory.Right -> {
|
||||||
|
image.setImageResource(R.drawable.side_body)
|
||||||
|
image.rotationY = 180.0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,17 +1,36 @@
|
||||||
package xyz.r0r5chach.dermy_app.fragments
|
package xyz.r0r5chach.dermy_app.fragments
|
||||||
|
|
||||||
|
import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.fragment.app.commit
|
||||||
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import xyz.r0r5chach.dermy_app.AccountPreference
|
||||||
import xyz.r0r5chach.dermy_app.R
|
import xyz.r0r5chach.dermy_app.R
|
||||||
|
|
||||||
|
|
||||||
|
@DelicateCoroutinesApi
|
||||||
class SettingsFragment : PreferenceFragmentCompat() {
|
class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||||
} //TODO: Disclaimers
|
|
||||||
//TODO: Useful Links
|
findPreference<Preference>("disclaimer")
|
||||||
|
?.setOnPreferenceClickListener {
|
||||||
|
val dialog = AlertDialog.Builder(requireContext())
|
||||||
|
|
||||||
|
dialog
|
||||||
|
.setMessage(R.string.disclaimer)
|
||||||
|
.setTitle("Disclaimer")
|
||||||
|
.setNeutralButton("Ok") { window, _ -> window.dismiss() }
|
||||||
|
.create().show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Export File
|
//TODO: Export File
|
||||||
//TODO: Backup data
|
//TODO: Backup data
|
||||||
//TODO: Recover Account
|
//TODO: Recover Account
|
||||||
// Login button
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M13.0001 10.9999L22.0002 10.9997L22.0002 12.9997L13.0001 12.9999L13.0001 21.9998L11.0001 21.9998L11.0001 12.9999L2.00004 13.0001L2 11.0001L11.0001 10.9999L11 2.00025L13 2.00024L13.0001 10.9999Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="oval">
|
||||||
|
<solid android:color="#000000"/>
|
||||||
|
<size
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"/>
|
||||||
|
</shape>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M12 1L21.5 6.5V17.5L12 23L2.5 17.5V6.5L12 1ZM12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M3 3H12.382C12.7607 3 13.107 3.214 13.2764 3.55279L14 5H20C20.5523 5 21 5.44772 21 6V17C21 17.5523 20.5523 18 20 18H13.618C13.2393 18 12.893 17.786 12.7236 17.4472L12 16H5V22H3V3Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M13.0607 8.11097L14.4749 9.52518C17.2086 12.2589 17.2086 16.691 14.4749 19.4247L14.1214 19.7782C11.3877 22.5119 6.95555 22.5119 4.22188 19.7782C1.48821 17.0446 1.48821 12.6124 4.22188 9.87874L5.6361 11.293C3.68348 13.2456 3.68348 16.4114 5.6361 18.364C7.58872 20.3166 10.7545 20.3166 12.7072 18.364L13.0607 18.0105C15.0133 16.0578 15.0133 12.892 13.0607 10.9394L11.6465 9.52518L13.0607 8.11097ZM19.7782 14.1214L18.364 12.7072C20.3166 10.7545 20.3166 7.58872 18.364 5.6361C16.4114 3.68348 13.2456 3.68348 11.293 5.6361L10.9394 5.98965C8.98678 7.94227 8.98678 11.1081 10.9394 13.0607L12.3536 14.4749L10.9394 15.8891L9.52518 14.4749C6.79151 11.7413 6.79151 7.30911 9.52518 4.57544L9.87874 4.22188C12.6124 1.48821 17.0446 1.48821 19.7782 4.22188C22.5119 6.95555 22.5119 11.3877 19.7782 14.1214Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M2 5L9 2L15 5L21.303 2.2987C21.5569 2.18992 21.8508 2.30749 21.9596 2.56131C21.9862 2.62355 22 2.69056 22 2.75827V19L15 22L9 19L2.69696 21.7013C2.44314 21.8101 2.14921 21.6925 2.04043 21.4387C2.01375 21.3765 2 21.3094 2 21.2417V5ZM16 19.3955L20 17.6812V5.03308L16 6.74736V19.3955ZM14 19.2639V6.73607L10 4.73607V17.2639L14 19.2639ZM8 17.2526V4.60451L4 6.31879V18.9669L8 17.2526Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M4 3H20C20.5523 3 21 3.44772 21 4V11H3V4C3 3.44772 3.44772 3 4 3ZM3 13H21V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V13ZM7 16V18H10V16H7ZM7 6V8H10V6H7Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="200dp"
|
||||||
|
android:height="200dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M4 22C4 17.5817 7.58172 14 12 14C16.4183 14 20 17.5817 20 22H4ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13Z"
|
||||||
|
android:fillColor="?attr/buttonIcon"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.fragment.app.FragmentContainerView
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/fragment_container"
|
android:id="@+id/fragment_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"/>
|
||||||
android:name="xyz.r0r5chach.dermy.fragments.CameraFragment" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -1,6 +1,126 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_height="match_parent">
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/username_field"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:autofillHints="username"
|
||||||
|
android:hint="@string/string_username"
|
||||||
|
android:inputType="text"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/password_field"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/password_field"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:autofillHints="password"
|
||||||
|
android:hint="@string/string_password"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/login_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/username_field"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/login_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:text="@string/string_login"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/register_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/password_field"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/register_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:text="@string/string_register"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/backup_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/login_button"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/backup_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:text="@string/string_backup"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/restore_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/login_button"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/restore_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:text="@string/string_restore"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/logout_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/backup_button"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/logout_button"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:text="@string/string_logout"
|
||||||
|
app:layout_constrainedHeight="true"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHeight_min="48dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/restore_button"
|
||||||
|
app:layout_constraintWidth_max="320dp"
|
||||||
|
app:layout_constraintWidth_min="250dp"
|
||||||
|
app:layout_constraintWidth_percent="0.25"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -4,60 +4,64 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<Button
|
<ImageButton
|
||||||
android:id="@+id/add_mole_button"
|
android:id="@+id/add_mole_button"
|
||||||
|
android:background="@drawable/add_icon"
|
||||||
|
android:contentDescription="@string/string_add_mole"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:text="@string/string_add_mole"
|
|
||||||
app:layout_constrainedWidth="true"
|
app:layout_constrainedWidth="true"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/links_button"
|
app:layout_constraintBottom_toTopOf="@+id/links_button"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/map_button"
|
app:layout_constraintEnd_toStartOf="@+id/map_button"
|
||||||
app:layout_constraintHeight_percent="0.1"
|
app:layout_constraintHeight_percent="0.15"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintWidth_max="320dp"
|
app:layout_constraintWidth_max="320dp"
|
||||||
app:layout_constraintWidth_percent="0.28" />
|
app:layout_constraintWidth_percent="0.28" />
|
||||||
|
|
||||||
<Button
|
<ImageButton
|
||||||
android:id="@+id/map_button"
|
android:id="@+id/map_button"
|
||||||
|
android:background="@drawable/map_icon"
|
||||||
|
android:contentDescription="@string/string_open_body_map"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:text="@string/string_body_map"
|
|
||||||
app:layout_constrainedWidth="true"
|
app:layout_constrainedWidth="true"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/settings_button"
|
app:layout_constraintBottom_toTopOf="@+id/settings_button"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHeight_percent="0.1"
|
app:layout_constraintHeight_percent="0.15"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toEndOf="@+id/add_mole_button"
|
app:layout_constraintStart_toEndOf="@+id/add_mole_button"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintWidth_max="320dp"
|
app:layout_constraintWidth_max="320dp"
|
||||||
app:layout_constraintWidth_percent="0.28" />
|
app:layout_constraintWidth_percent="0.28" />
|
||||||
|
|
||||||
<Button
|
<ImageButton
|
||||||
android:id="@+id/links_button"
|
android:id="@+id/links_button"
|
||||||
|
android:background="@drawable/links_icon"
|
||||||
|
android:contentDescription="@string/string_open_useful_links"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:text="@string/string_links"
|
|
||||||
app:layout_constrainedWidth="true"
|
app:layout_constrainedWidth="true"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/settings_button"
|
app:layout_constraintEnd_toStartOf="@+id/settings_button"
|
||||||
app:layout_constraintHeight_percent="0.1"
|
app:layout_constraintHeight_percent="0.15"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/add_mole_button"
|
app:layout_constraintTop_toBottomOf="@+id/add_mole_button"
|
||||||
app:layout_constraintWidth_max="320dp"
|
app:layout_constraintWidth_max="320dp"
|
||||||
app:layout_constraintWidth_percent="0.28" />
|
app:layout_constraintWidth_percent="0.28" />
|
||||||
|
|
||||||
<Button
|
<ImageButton
|
||||||
android:id="@+id/settings_button"
|
android:id="@+id/settings_button"
|
||||||
|
android:background="@drawable/cog_icon"
|
||||||
|
android:contentDescription="@string/string_open_settings"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:text="@string/string_settings"
|
|
||||||
app:layout_constrainedWidth="true"
|
app:layout_constrainedWidth="true"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHeight_percent="0.1"
|
app:layout_constraintHeight_percent="0.15"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toEndOf="@+id/links_button"
|
app:layout_constraintStart_toEndOf="@+id/links_button"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/map_button"
|
app:layout_constraintTop_toBottomOf="@+id/map_button"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,20 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/links_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -1,6 +1,13 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<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_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/map_pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"/>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,254 @@
|
||||||
|
<?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">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/category_image"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="50dp"
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:layout_marginEnd="50dp"
|
||||||
|
android:layout_marginBottom="50dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/front_body" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_wrist_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/genitals_button"
|
||||||
|
tools:layout_editor_absoluteY="383dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_wrist_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/genitals_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:layout_editor_absoluteY="383dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_hand_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/left_thigh_button"
|
||||||
|
tools:layout_editor_absoluteY="437dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_hand_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/right_thigh_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:layout_editor_absoluteY="437dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_thigh_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="240dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/left_hand_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_thigh_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/left_breast_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_thigh_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="240dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/left_thigh_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_hand_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/right_breast_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/genitals_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginBottom="500dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/left_wrist_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_wrist_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/stomach_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/stomach_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="100dp"
|
||||||
|
android:layout_marginBottom="100dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/genitals_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/neck_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_shoulder_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="189dp"
|
||||||
|
android:layout_marginEnd="350dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/left_breast_button"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_shoulder_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginStart="350dp"
|
||||||
|
android:layout_marginTop="189dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/right_breast_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_breast_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/left_thigh_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/left_shoulder_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_breast_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/left_collar_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_breast_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/right_thigh_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/left_breast_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_shoulder_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/right_collar_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_collar_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="45dp"
|
||||||
|
android:layout_marginEnd="415dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/left_breast_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/neck_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/left_eye_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/forehead_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="200dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
android:text="99"
|
||||||
|
android:textSize="11sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/front_nose_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/front_nose_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
android:textSize="11sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/lips_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/left_eye_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_eye_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/forehead_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_eye_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginStart="400dp"
|
||||||
|
android:layout_marginTop="60dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/right_collar_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/front_nose_button"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/left_eye_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginTop="60dp"
|
||||||
|
android:layout_marginEnd="400dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/left_collar_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/front_nose_button"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/lips_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/chin_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/front_nose_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/chin_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/neck_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/lips_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/neck_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/stomach_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/left_collar_button"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/right_collar_button"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/chin_button" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/right_collar_button"
|
||||||
|
android:layout_width="47dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_marginStart="415dp"
|
||||||
|
android:layout_marginTop="45dp"
|
||||||
|
android:background="@drawable/circle_button"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/right_breast_button"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/neck_button"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/right_eye_button" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?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="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/link_item_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginBottom="50dp"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -12,5 +12,6 @@
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="buttonIcon">@color/white</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -1,5 +1,34 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">dermy_app</string>
|
<string name="app_name">Dermy</string>
|
||||||
<!-- TODO: Remove or change this placeholder text -->
|
<!-- TODO: Remove or change this placeholder text -->
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||||
|
<string name="string_add_mole">Add Mole</string>
|
||||||
|
<string name="string_open_body_map">Open Body Map</string>
|
||||||
|
<string name="string_open_useful_links">Open Useful Links</string>
|
||||||
|
<string name="string_open_settings">Open Settings</string>
|
||||||
|
<string name="string_login">Login</string>
|
||||||
|
<string name="string_username">username</string>
|
||||||
|
<string name="string_password">password</string>
|
||||||
|
<string name="string_backup">Backup</string>
|
||||||
|
<string name="string_restore">Restore</string>
|
||||||
|
<string name="string_logout">Logout</string>
|
||||||
|
<string name="string_register">Register</string>
|
||||||
|
<string name="disclaimer">
|
||||||
|
1. General Information
|
||||||
|
\nThe information provided by Dermy (“we,” “us” or “our”) on [Your App Name] (the “App”) is for general informational purposes only and is based on a deep learning algorithm. While our model, based on MobileNetV3, attempts to predict the likelihood of a mole being malignant or benign, it has an accuracy rating of approximately 80%. All information on the App is provided in good faith; however, we make no representation or warranty of any kind, express or implied, regarding the accuracy, adequacy, validity, reliability, availability, or completeness of any information on the App.
|
||||||
|
\n\n2. Not Medical Advice
|
||||||
|
\nThe App cannot and does not provide medical advice. The health information provided is for general informational and educational purposes only and is not a substitute for professional medical advice, diagnosis, or treatment. Always seek the advice of your physician or other qualified health provider with any questions you may have regarding a medical condition. Never disregard professional medical advice or delay in seeking it because of something you have read on this App.
|
||||||
|
\n\n3. Limitation of Accuracy
|
||||||
|
\nOur model\'s predictions should not be taken as definitive or conclusive. While our algorithm uses advanced techniques, it is not infallible and its accuracy is limited to approximately 80%. The results generated by the App should not be used as a sole basis for making health decisions. Users should follow up with a qualified healthcare professional for any concerns regarding their health.
|
||||||
|
\n\n4. Personal Responsibility
|
||||||
|
\nYou acknowledge you are using our App voluntarily and that any choices, actions, and results now and in the future are solely your responsibility. We strongly encourage you to consult with a healthcare professional before making any health-related decisions based on the information provided by the App. We will not be liable to you or any other party for any decision made or action taken in reliance on the information given in the App.
|
||||||
|
\n\n5. External Links Disclaimer
|
||||||
|
\nThe App may contain (or you may be sent through the App) links to other websites or content belonging to or originating from third parties or links to websites and features in banners or other advertising. Such external links are not investigated, monitored, or checked for accuracy, adequacy, validity, reliability, availability, or completeness by us. We do not warrant, endorse, guarantee, or assume responsibility for the accuracy or reliability of any information offered by third-party websites linked through the App or any website or feature linked in any banner or other advertising. We will not be a party to or in any way be responsible for monitoring any transaction between you and third-party providers of products or services.</string>
|
||||||
|
|
||||||
|
<string-array name="links">
|
||||||
|
<item>https://www.nhs.uk/service-search/other-health-services/dermatology</item>
|
||||||
|
<item>https://www.britishskinfoundation.org.uk/news/find-your-nearest-dermatology-clinic</item>
|
||||||
|
<item>https://www.privatehealth.co.uk/dermatology/specialists/</item>
|
||||||
|
<item>https://www.sknclinics.co.uk/treatments-and-pricing/dermatology</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -12,5 +12,6 @@
|
||||||
<!-- Status bar color. -->
|
<!-- Status bar color. -->
|
||||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="buttonIcon">@color/black</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -1,4 +1,31 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
<PreferenceCategory
|
||||||
|
android:title="Account"
|
||||||
|
app:allowDividerAbove="false"
|
||||||
|
app:allowDividerBelow="false"
|
||||||
|
app:icon="@drawable/user_icon">
|
||||||
|
<xyz.r0r5chach.dermy_app.AccountPreference
|
||||||
|
app:key="api_key"
|
||||||
|
app:layout="@layout/fragment_account" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:title="Server"
|
||||||
|
app:icon="@drawable/server_icon"
|
||||||
|
app:allowDividerAbove="false"
|
||||||
|
app:allowDividerBelow="false">
|
||||||
|
<EditTextPreference
|
||||||
|
app:defaultValue="https://dermy.r0r-5chach.xyz/"
|
||||||
|
app:key="instance_url"
|
||||||
|
app:title="Instance URL" />
|
||||||
|
<Preference
|
||||||
|
app:key="disclaimer"
|
||||||
|
app:title="Disclaimer"
|
||||||
|
app:icon="@drawable/flag_icon"/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
[versions]
|
[versions]
|
||||||
agp = "8.4.1"
|
agp = "8.4.1"
|
||||||
fragmentKtx = "1.7.1"
|
fragmentKtx = "1.7.1"
|
||||||
|
jsoup = "1.17.2"
|
||||||
kotlin = "1.9.0"
|
kotlin = "1.9.0"
|
||||||
coreKtx = "1.13.1"
|
coreKtx = "1.13.1"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
|
|
@ -12,12 +13,19 @@ cameraView = "1.3.3"
|
||||||
cameraCore = "1.3.3"
|
cameraCore = "1.3.3"
|
||||||
cameraLifecycle = "1.3.3"
|
cameraLifecycle = "1.3.3"
|
||||||
mongodbDriverKotlinSync = "5.1.1"
|
mongodbDriverKotlinSync = "5.1.1"
|
||||||
|
playServicesCronet = "18.1.0"
|
||||||
preference = "1.2.1"
|
preference = "1.2.1"
|
||||||
|
retrofit = "1"
|
||||||
|
retrofitVersion = "2.11.0"
|
||||||
roomCommon = "2.6.1"
|
roomCommon = "2.6.1"
|
||||||
|
volley = "1.2.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentKtx" }
|
androidx-fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentKtx" }
|
||||||
|
converter-jackson = { module = "com.squareup.retrofit2:converter-jackson", version.ref = "retrofitVersion" }
|
||||||
|
jsoup = { module = "org.jsoup:jsoup" }
|
||||||
|
jsoup-jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
|
|
@ -29,6 +37,10 @@ androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycl
|
||||||
androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
|
androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
|
||||||
androidx-room-common = { group = "androidx.room", name = "room-common", version.ref = "roomCommon" }
|
androidx-room-common = { group = "androidx.room", name = "room-common", version.ref = "roomCommon" }
|
||||||
mongodb-driver-kotlin-sync = { module = "org.mongodb:mongodb-driver-kotlin-sync", version.ref = "mongodbDriverKotlinSync" }
|
mongodb-driver-kotlin-sync = { module = "org.mongodb:mongodb-driver-kotlin-sync", version.ref = "mongodbDriverKotlinSync" }
|
||||||
|
play-services-cronet = { module = "com.google.android.gms:play-services-cronet", version.ref = "playServicesCronet" }
|
||||||
|
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||||
|
retrofit-v2110 = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" }
|
||||||
|
volley = { module = "com.android.volley:volley", version.ref = "volley" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue