Refactor
parent
44da3fc059
commit
882a03312f
|
@ -15,22 +15,19 @@ window.loggedIn = async () => {
|
||||||
let localList = null;
|
let localList = null;
|
||||||
async function openLocal() {
|
async function openLocal() {
|
||||||
// Get the list of local folders for next screen
|
// Get the list of local folders for next screen
|
||||||
(async () => {
|
localList = JSON.parse(window.nativex?.configGetLocalFolders());
|
||||||
const res = await fetch("http://127.0.0.1/api/config/local-folders");
|
|
||||||
localList = await res.json();
|
|
||||||
|
|
||||||
// Add HTML for folders list
|
// Add HTML for folders list
|
||||||
document.getElementById("folder-list").innerHTML = localList
|
document.getElementById("folder-list").innerHTML = localList
|
||||||
.map(
|
.map(
|
||||||
(folder) => `
|
(folder) => `
|
||||||
<div class="folder-choose">
|
<div class="folder-choose">
|
||||||
<input type="checkbox" id="folder-${folder.id}" ${folder.enabled ? "checked" : ""}>
|
<input type="checkbox" id="folder-${folder.id}" ${folder.enabled ? "checked" : ""}>
|
||||||
<label for="${folder.id}">${folder.name}</label>
|
<label for="${folder.id}">${folder.name}</label>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
})();
|
|
||||||
|
|
||||||
// Show the folders list
|
// Show the folders list
|
||||||
sync.classList.add("invisible");
|
sync.classList.add("invisible");
|
||||||
|
|
|
@ -189,23 +189,9 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadDefaultUrl(): Boolean {
|
fun loadDefaultUrl(): Boolean {
|
||||||
// Load accounts
|
|
||||||
val authHeader = nativex.account.authHeader
|
|
||||||
val memoriesUrl = nativex.account.memoriesUrl
|
|
||||||
|
|
||||||
// Load app interface if authenticated
|
// Load app interface if authenticated
|
||||||
if (authHeader != null && memoriesUrl != null) {
|
host = nativex.http.loadWebView(binding.webview)
|
||||||
// Get host name
|
if (host != null) return true
|
||||||
host = Uri.parse(memoriesUrl).host
|
|
||||||
|
|
||||||
// Set authorization header
|
|
||||||
binding.webview.loadUrl(
|
|
||||||
memoriesUrl, mapOf(
|
|
||||||
"Authorization" to authHeader
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load welcome page
|
// Load welcome page
|
||||||
binding.webview.loadUrl("file:///android_asset/welcome.html");
|
binding.webview.loadUrl("file:///android_asset/welcome.html");
|
||||||
|
|
|
@ -10,19 +10,22 @@ import android.widget.Toast
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import gallery.memories.service.AccountService
|
import gallery.memories.service.AccountService
|
||||||
import gallery.memories.service.DownloadService
|
import gallery.memories.service.DownloadService
|
||||||
|
import gallery.memories.service.HttpService
|
||||||
import gallery.memories.service.ImageService
|
import gallery.memories.service.ImageService
|
||||||
import gallery.memories.service.TimelineQuery
|
import gallery.memories.service.TimelineQuery
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
|
||||||
@UnstableApi class NativeX(private val mCtx: MainActivity) {
|
@UnstableApi
|
||||||
|
class NativeX(private val mCtx: MainActivity) {
|
||||||
val TAG = NativeX::class.java.simpleName
|
val TAG = NativeX::class.java.simpleName
|
||||||
|
|
||||||
private var themeStored = false
|
private var themeStored = false
|
||||||
val query = TimelineQuery(mCtx)
|
val query = TimelineQuery(mCtx)
|
||||||
val image = ImageService(mCtx, query)
|
val image = ImageService(mCtx, query)
|
||||||
val account = AccountService(mCtx)
|
val http = HttpService()
|
||||||
|
val account = AccountService(mCtx, http)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
dlService = DownloadService(mCtx, query)
|
dlService = DownloadService(mCtx, query)
|
||||||
|
@ -60,7 +63,7 @@ import java.net.URLDecoder
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun setThemeColor(color: String?, isDark: Boolean) {
|
fun setThemeColor(color: String?, isDark: Boolean) {
|
||||||
// Save for getting it back on next start
|
// Save for getting it back on next start
|
||||||
if (!themeStored && account.authHeader != null) {
|
if (!themeStored && http.isLoggedIn()) {
|
||||||
themeStored = true
|
themeStored = true
|
||||||
mCtx.storeTheme(color, isDark);
|
mCtx.storeTheme(color, isDark);
|
||||||
}
|
}
|
||||||
|
@ -162,9 +165,15 @@ import java.net.URLDecoder
|
||||||
"GET" -> {
|
"GET" -> {
|
||||||
routerGet(request)
|
routerGet(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
"OPTIONS" -> {
|
"OPTIONS" -> {
|
||||||
WebResourceResponse("text/plain", "UTF-8", ByteArrayInputStream("".toByteArray()))
|
WebResourceResponse(
|
||||||
|
"text/plain",
|
||||||
|
"UTF-8",
|
||||||
|
ByteArrayInputStream("".toByteArray())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw Exception("Method Not Allowed")
|
throw Exception("Method Not Allowed")
|
||||||
}
|
}
|
||||||
|
@ -200,7 +209,12 @@ import java.net.URLDecoder
|
||||||
} else if (path.matches(API.IMAGE_INFO)) {
|
} else if (path.matches(API.IMAGE_INFO)) {
|
||||||
makeResponse(query.getImageInfo(parts[4].toLong()))
|
makeResponse(query.getImageInfo(parts[4].toLong()))
|
||||||
} else if (path.matches(API.IMAGE_DELETE)) {
|
} else if (path.matches(API.IMAGE_DELETE)) {
|
||||||
makeResponse(query.delete(parseIds(parts[4]), request.url.getBooleanQueryParameter("dry", false)))
|
makeResponse(
|
||||||
|
query.delete(
|
||||||
|
parseIds(parts[4]),
|
||||||
|
request.url.getBooleanQueryParameter("dry", false)
|
||||||
|
)
|
||||||
|
)
|
||||||
} else if (path.matches(API.IMAGE_PREVIEW)) {
|
} else if (path.matches(API.IMAGE_PREVIEW)) {
|
||||||
makeResponse(image.getPreview(parts[3].toLong()), "image/jpeg")
|
makeResponse(image.getPreview(parts[3].toLong()), "image/jpeg")
|
||||||
} else if (path.matches(API.IMAGE_FULL)) {
|
} else if (path.matches(API.IMAGE_FULL)) {
|
||||||
|
@ -227,7 +241,11 @@ import java.net.URLDecoder
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makeErrorResponse(): WebResourceResponse {
|
private fun makeErrorResponse(): WebResourceResponse {
|
||||||
val response = WebResourceResponse("application/json", "UTF-8", ByteArrayInputStream("{}".toByteArray()))
|
val response = WebResourceResponse(
|
||||||
|
"application/json",
|
||||||
|
"UTF-8",
|
||||||
|
ByteArrayInputStream("{}".toByteArray())
|
||||||
|
)
|
||||||
response.setStatusCodeAndReasonPhrase(500, "Internal Server Error")
|
response.setStatusCodeAndReasonPhrase(500, "Internal Server Error")
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package gallery.memories.service
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Base64
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
@ -18,14 +17,11 @@ import org.json.JSONObject
|
||||||
import java.net.SocketTimeoutException
|
import java.net.SocketTimeoutException
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
class AccountService(private val mCtx: MainActivity) {
|
class AccountService(private val mCtx: MainActivity, private val mHttp: HttpService) {
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = AccountService::class.java.simpleName
|
val TAG = AccountService::class.java.simpleName
|
||||||
}
|
}
|
||||||
|
|
||||||
var authHeader: String? = null
|
|
||||||
var memoriesUrl: String? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login to a server
|
* Login to a server
|
||||||
* @param baseUrl The base URL of the server
|
* @param baseUrl The base URL of the server
|
||||||
|
@ -151,54 +147,45 @@ class AccountService(private val mCtx: MainActivity) {
|
||||||
* Makes a toast to the user if something is wrong
|
* Makes a toast to the user if something is wrong
|
||||||
*/
|
*/
|
||||||
fun checkCredentialsAndVersion() {
|
fun checkCredentialsAndVersion() {
|
||||||
if (memoriesUrl == null) return
|
if (mHttp.isLoggedIn()) return
|
||||||
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url(memoriesUrl + "api/describe")
|
|
||||||
.get()
|
|
||||||
.header("Authorization", authHeader ?: "")
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val response: Response
|
|
||||||
try {
|
try {
|
||||||
response = OkHttpClient().newCall(request).execute()
|
val response = mHttp.getApiDescription()
|
||||||
|
val body = mHttp.bodyJson(response)
|
||||||
|
|
||||||
|
// Check status code
|
||||||
|
if (response.code == 401) {
|
||||||
|
return loggedOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could not connect to memories
|
||||||
|
if (response.code == 404) {
|
||||||
|
return toast(mCtx.getString(R.string.err_no_ver))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check body
|
||||||
|
if (body == null || response.code != 200) {
|
||||||
|
toast(mCtx.getString(R.string.err_no_describe))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get body values
|
||||||
|
val uid = body.get("uid")
|
||||||
|
val version = body.getString("version")
|
||||||
|
|
||||||
|
// Check UID exists
|
||||||
|
if (uid.equals(null)) {
|
||||||
|
return loggedOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check minimum version
|
||||||
|
if (Version(version) < Version(mCtx.getString(R.string.min_server_version))) {
|
||||||
|
return toast(mCtx.getString(R.string.err_no_ver))
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(TAG, "checkCredentialsAndVersion: ", e)
|
Log.w(TAG, "checkCredentialsAndVersion: ", e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val body = response.body?.string()
|
|
||||||
response.body?.close()
|
|
||||||
|
|
||||||
// Check status code
|
|
||||||
if (response.code == 401) {
|
|
||||||
return loggedOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Could not connect to memories
|
|
||||||
if (response.code == 404) {
|
|
||||||
return toast(mCtx.getString(R.string.err_no_ver))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check body
|
|
||||||
if (body == null || response.code != 200) {
|
|
||||||
toast(mCtx.getString(R.string.err_no_describe))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val json = JSONObject(body)
|
|
||||||
val version = json.getString("version")
|
|
||||||
val uid = json.get("uid")
|
|
||||||
|
|
||||||
// Check UID exists
|
|
||||||
if (uid.equals(null) && authHeader != null) {
|
|
||||||
return loggedOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check minimum version
|
|
||||||
if (Version(version) < Version(mCtx.getString(R.string.min_server_version))) {
|
|
||||||
return toast(mCtx.getString(R.string.err_no_ver))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -224,8 +211,8 @@ class AccountService(private val mCtx: MainActivity) {
|
||||||
.putString("user", user)
|
.putString("user", user)
|
||||||
.putString("password", password)
|
.putString("password", password)
|
||||||
.apply()
|
.apply()
|
||||||
memoriesUrl = url
|
mHttp.setBaseUrl(url)
|
||||||
setAuthHeader(Pair(user, password))
|
mHttp.setAuthHeader(Pair(user, password))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -234,7 +221,7 @@ class AccountService(private val mCtx: MainActivity) {
|
||||||
*/
|
*/
|
||||||
fun getCredentials(): Pair<String, String>? {
|
fun getCredentials(): Pair<String, String>? {
|
||||||
val prefs = mCtx.getSharedPreferences("credentials", 0)
|
val prefs = mCtx.getSharedPreferences("credentials", 0)
|
||||||
memoriesUrl = prefs.getString("memoriesUrl", null)
|
mHttp.setBaseUrl(prefs.getString("memoriesUrl", null))
|
||||||
val user = prefs.getString("user", null)
|
val user = prefs.getString("user", null)
|
||||||
val password = prefs.getString("password", null)
|
val password = prefs.getString("password", null)
|
||||||
if (user == null || password == null) return null
|
if (user == null || password == null) return null
|
||||||
|
@ -245,8 +232,8 @@ class AccountService(private val mCtx: MainActivity) {
|
||||||
* Delete the stored credentials
|
* Delete the stored credentials
|
||||||
*/
|
*/
|
||||||
fun deleteCredentials() {
|
fun deleteCredentials() {
|
||||||
authHeader = null
|
mHttp.setAuthHeader(null)
|
||||||
memoriesUrl = null
|
mHttp.setBaseUrl(null)
|
||||||
mCtx.getSharedPreferences("credentials", 0).edit()
|
mCtx.getSharedPreferences("credentials", 0).edit()
|
||||||
.remove("memoriesUrl")
|
.remove("memoriesUrl")
|
||||||
.remove("user")
|
.remove("user")
|
||||||
|
@ -258,20 +245,7 @@ class AccountService(private val mCtx: MainActivity) {
|
||||||
* Refresh the authorization header
|
* Refresh the authorization header
|
||||||
*/
|
*/
|
||||||
fun refreshAuthHeader() {
|
fun refreshAuthHeader() {
|
||||||
setAuthHeader(getCredentials())
|
mHttp.setAuthHeader(getCredentials())
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the authorization header
|
|
||||||
* @param credentials The credentials to use
|
|
||||||
*/
|
|
||||||
private fun setAuthHeader(credentials: Pair<String, String>?) {
|
|
||||||
if (credentials != null) {
|
|
||||||
val auth = "${credentials.first}:${credentials.second}"
|
|
||||||
authHeader = "Basic ${Base64.encodeToString(auth.toByteArray(), Base64.NO_WRAP)}"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
authHeader = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue