Compare commits
No commits in common. "784879393f6f7bcab886d36fa32d4bb78caff444" and "72e0e2a912937f2c379bb3dcfa15565e2c32235f" have entirely different histories.
784879393f
...
72e0e2a912
9 changed files with 24 additions and 202 deletions
|
@ -49,7 +49,7 @@ fun InstancesScreen(dashboardViewModel: DashboardViewModel) {
|
||||||
|
|
||||||
// TODO actually get instances
|
// TODO actually get instances
|
||||||
|
|
||||||
if (rentedInstances.isNotEmpty()) {
|
if (rentedInstances.size > 0) {
|
||||||
ContextualFlowRow(
|
ContextualFlowRow(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -66,12 +66,6 @@ fun InstancesScreen(dashboardViewModel: DashboardViewModel) {
|
||||||
sshButtonClick = {
|
sshButtonClick = {
|
||||||
dashboardViewModel.sshButtonClick(activity, it)
|
dashboardViewModel.sshButtonClick(activity, it)
|
||||||
},
|
},
|
||||||
actionButtonClick = {
|
|
||||||
dashboardViewModel.toggleInstance(it)
|
|
||||||
},
|
|
||||||
deleteButtonClick = {
|
|
||||||
dashboardViewModel.deleteInstance(it)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,8 +89,6 @@ fun RentedInstanceCard(
|
||||||
rentedInstance: RentedInstance,
|
rentedInstance: RentedInstance,
|
||||||
termuxAvailable: Int,
|
termuxAvailable: Int,
|
||||||
sshButtonClick: (RentedInstance) -> Unit,
|
sshButtonClick: (RentedInstance) -> Unit,
|
||||||
actionButtonClick: (RentedInstance) -> Unit,
|
|
||||||
deleteButtonClick: (RentedInstance) -> Unit,
|
|
||||||
) {
|
) {
|
||||||
val instance by remember(rentedInstance) { derivedStateOf { rentedInstance.instance } }
|
val instance by remember(rentedInstance) { derivedStateOf { rentedInstance.instance } }
|
||||||
val label by remember(instance) { derivedStateOf {
|
val label by remember(instance) { derivedStateOf {
|
||||||
|
@ -111,66 +103,27 @@ fun RentedInstanceCard(
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.End
|
horizontalAlignment = Alignment.End
|
||||||
) {
|
) {
|
||||||
Row {
|
Button( // TODO consider other buttons
|
||||||
Button(
|
modifier = Modifier.height(24.dp),
|
||||||
modifier = Modifier.size(24.dp),
|
contentPadding = PaddingValues(0.dp),
|
||||||
contentPadding = PaddingValues(0.dp),
|
onClick = { sshButtonClick(rentedInstance) }
|
||||||
onClick = { deleteButtonClick(rentedInstance) },
|
) {
|
||||||
) {
|
if (termuxAvailable > -1) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(16.dp),
|
painter = painterResource(id = R.drawable.termux_icon),
|
||||||
painter = painterResource(id = R.drawable.baseline_delete_24),
|
contentDescription = "Run in Termux"
|
||||||
contentDescription = "Delete instance"
|
|
||||||
)
|
)
|
||||||
}
|
Text("ssh")
|
||||||
|
Spacer(modifier = Modifier.size(4.dp)) // necessary because TODO the termux icon has padding
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
} else {
|
||||||
|
Spacer(modifier = Modifier.size(1.dp)) // TODO make this not needed?
|
||||||
Button(
|
Icon(
|
||||||
modifier = Modifier.size(24.dp),
|
modifier = Modifier.size(12.dp),
|
||||||
contentPadding = PaddingValues(0.dp),
|
painter = painterResource(id = R.drawable.copy_regular), // TODO copy icon here
|
||||||
onClick = { actionButtonClick(rentedInstance) },
|
contentDescription = "Copy command"
|
||||||
enabled = rentedInstance.status == rentedInstance.targetStatus
|
)
|
||||||
) {
|
Spacer(modifier = Modifier.size(6.dp))
|
||||||
if (rentedInstance.status == "running") {
|
Text("ssh")
|
||||||
Icon(
|
|
||||||
modifier = Modifier.size(16.dp),
|
|
||||||
painter = painterResource(id = R.drawable.baseline_stop_24),
|
|
||||||
contentDescription = "Stop instance"
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Icon(
|
|
||||||
modifier = Modifier.size(16.dp),
|
|
||||||
painter = painterResource(id = R.drawable.baseline_play_arrow_24),
|
|
||||||
contentDescription = "Start instance"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
|
||||||
|
|
||||||
Button(
|
|
||||||
modifier = Modifier.height(24.dp),
|
|
||||||
contentPadding = PaddingValues(0.dp),
|
|
||||||
onClick = { sshButtonClick(rentedInstance) }
|
|
||||||
) {
|
|
||||||
if (termuxAvailable > -1) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.termux_icon),
|
|
||||||
contentDescription = "Run in Termux"
|
|
||||||
)
|
|
||||||
Text("ssh")
|
|
||||||
Spacer(modifier = Modifier.size(4.dp)) // necessary because TODO the termux icon has padding
|
|
||||||
} else {
|
|
||||||
Spacer(modifier = Modifier.size(1.dp)) // TODO make this not needed?
|
|
||||||
Icon(
|
|
||||||
modifier = Modifier.size(12.dp),
|
|
||||||
painter = painterResource(id = R.drawable.copy_regular), // TODO copy icon here
|
|
||||||
contentDescription = "Copy command"
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.size(6.dp))
|
|
||||||
Text("ssh")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package eu.m724.vastapp.vastai
|
||||||
|
|
||||||
import eu.m724.vastapp.BuildConfig
|
import eu.m724.vastapp.BuildConfig
|
||||||
import org.chromium.net.CronetEngine
|
import org.chromium.net.CronetEngine
|
||||||
import org.chromium.net.UploadDataProvider
|
|
||||||
import org.chromium.net.UrlRequest
|
import org.chromium.net.UrlRequest
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
|
|
||||||
|
@ -17,28 +16,15 @@ class VastApi(
|
||||||
*
|
*
|
||||||
* @param endpoint the endpoint path starting with a slash like /users/current
|
* @param endpoint the endpoint path starting with a slash like /users/current
|
||||||
* @param callback any callback for example [UserUrlRequestCallback]
|
* @param callback any callback for example [UserUrlRequestCallback]
|
||||||
* @param method request method, default GET
|
|
||||||
* @param uploadDataProvider [UploadDataProvider] if request sends data
|
|
||||||
* @return an [UrlRequest] you must .start() yourself
|
* @return an [UrlRequest] you must .start() yourself
|
||||||
*/
|
*/
|
||||||
fun buildRequest(
|
fun buildRequest(endpoint: String, callback: UrlRequest.Callback): UrlRequest {
|
||||||
endpoint: String,
|
val requestBuilder = cronetEngine.newUrlRequestBuilder(
|
||||||
callback: UrlRequest.Callback,
|
|
||||||
method: String = "GET",
|
|
||||||
uploadDataProvider: UploadDataProvider?
|
|
||||||
): UrlRequest {
|
|
||||||
var requestBuilder = cronetEngine.newUrlRequestBuilder(
|
|
||||||
BuildConfig.VASIAI_API_ENDPOINT + endpoint,
|
BuildConfig.VASIAI_API_ENDPOINT + endpoint,
|
||||||
callback,
|
callback,
|
||||||
executor
|
executor
|
||||||
).addHeader("Authorization", "Bearer $apiKey")
|
).addHeader("Authorization", "Bearer $apiKey")
|
||||||
|
|
||||||
requestBuilder = requestBuilder.setHttpMethod(method)
|
|
||||||
|
|
||||||
if (uploadDataProvider != null) {
|
|
||||||
requestBuilder = requestBuilder.setUploadDataProvider(uploadDataProvider, executor)
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestBuilder.build()
|
return requestBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +34,9 @@ class VastApi(
|
||||||
*
|
*
|
||||||
* @param apiRoute the api route
|
* @param apiRoute the api route
|
||||||
* @param callback any callback for example [UserUrlRequestCallback]
|
* @param callback any callback for example [UserUrlRequestCallback]
|
||||||
* @param uploadDataProvider [UploadDataProvider] if request sends data
|
|
||||||
* @return an [UrlRequest] you must .start() yourself
|
* @return an [UrlRequest] you must .start() yourself
|
||||||
*/
|
*/
|
||||||
fun buildRequest(apiRoute: ApiRoute, callback: UrlRequest.Callback, uploadDataProvider: UploadDataProvider? = null): UrlRequest {
|
fun buildRequest(apiRoute: ApiRoute, callback: UrlRequest.Callback): UrlRequest {
|
||||||
return buildRequest(apiRoute.path, callback, apiRoute.method, uploadDataProvider)
|
return buildRequest(apiRoute.path, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
package eu.m724.vastapp.vastai.api
|
|
||||||
|
|
||||||
import eu.m724.vastapp.vastai.ApiFailure
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
class JsonUrlRequestCallback(
|
|
||||||
onSuccess: (JSONObject) -> Unit,
|
|
||||||
onFailure: (ApiFailure) -> Unit
|
|
||||||
) : StringUrlRequestCallback({ stringResponse ->
|
|
||||||
try {
|
|
||||||
val jsonResponse = JSONObject(stringResponse)
|
|
||||||
onSuccess(jsonResponse)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
onFailure(ApiFailure(e.message))
|
|
||||||
}
|
|
||||||
}, onFailure)
|
|
|
@ -1,51 +0,0 @@
|
||||||
package eu.m724.vastapp.vastai.api
|
|
||||||
|
|
||||||
import eu.m724.vastapp.vastai.ApiFailure
|
|
||||||
import org.chromium.net.CronetException
|
|
||||||
import org.chromium.net.UrlRequest
|
|
||||||
import org.chromium.net.UrlResponseInfo
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.charset.CodingErrorAction
|
|
||||||
|
|
||||||
open class StringUrlRequestCallback(
|
|
||||||
val onSuccess: (String) -> Unit,
|
|
||||||
val onFailure: (ApiFailure) -> Unit
|
|
||||||
) : UrlRequest.Callback() {
|
|
||||||
protected val stringResponse = StringBuilder()
|
|
||||||
|
|
||||||
override fun onRedirectReceived(
|
|
||||||
request: UrlRequest?,
|
|
||||||
info: UrlResponseInfo?,
|
|
||||||
newLocationUrl: String?
|
|
||||||
) {
|
|
||||||
request?.followRedirect()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResponseStarted(request: UrlRequest?, info: UrlResponseInfo?) {
|
|
||||||
request?.read(ByteBuffer.allocateDirect(102400))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReadCompleted(
|
|
||||||
request: UrlRequest?,
|
|
||||||
info: UrlResponseInfo?,
|
|
||||||
byteBuffer: ByteBuffer?
|
|
||||||
) {
|
|
||||||
byteBuffer?.clear()
|
|
||||||
request?.read(byteBuffer)
|
|
||||||
|
|
||||||
stringResponse.append(Charsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.IGNORE).decode(byteBuffer))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) {
|
|
||||||
if (info?.httpStatusCode == 200) {
|
|
||||||
onSuccess(stringResponse.toString())
|
|
||||||
} else {
|
|
||||||
onFailure(ApiFailure("${info?.httpStatusCode} ${info?.httpStatusText}"))
|
|
||||||
println("API error: ${stringResponse.toString()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailed(request: UrlRequest?, info: UrlResponseInfo?, error: CronetException?) {
|
|
||||||
onFailure(ApiFailure("Network error: ${error?.message ?: "Unknown"}"))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package eu.m724.vastapp.vastai.api.upload
|
|
||||||
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
class JsonUploadDataProvider(
|
|
||||||
jsonObject: JSONObject
|
|
||||||
) : StringUploadDataProvider(
|
|
||||||
jsonObject.toString()
|
|
||||||
)
|
|
|
@ -1,25 +0,0 @@
|
||||||
package eu.m724.vastapp.vastai.api.upload
|
|
||||||
|
|
||||||
import org.chromium.net.UploadDataProvider
|
|
||||||
import org.chromium.net.UploadDataSink
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.charset.StandardCharsets
|
|
||||||
|
|
||||||
open class StringUploadDataProvider(
|
|
||||||
val data: String
|
|
||||||
) : UploadDataProvider() {
|
|
||||||
override fun getLength(): Long {
|
|
||||||
return data.length.toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun read(uploadDataSink: UploadDataSink?, byteBuffer: ByteBuffer?) {
|
|
||||||
byteBuffer!!.put(data.toByteArray(StandardCharsets.UTF_8))
|
|
||||||
uploadDataSink!!.onReadSucceeded(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun rewind(uploadDataSink: UploadDataSink?) {
|
|
||||||
// TODO look into it
|
|
||||||
uploadDataSink!!.onRewindSucceeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M8,5v14l11,-7z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M6,6h12v12H6z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
Loading…
Reference in a new issue