pull/653/merge
Varun Patil 2023-10-01 20:19:24 -07:00
parent 44da3fc059
commit 882a03312f
4 changed files with 78 additions and 103 deletions

View File

@ -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");

View File

@ -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");

View File

@ -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
} }

View File

@ -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
} }
/** /**