mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-21 17:05:39 +03:00
Try to communicate with WidgetPostAPI
This commit is contained in:
parent
01d6b52a60
commit
91301197ea
14 changed files with 516 additions and 9 deletions
|
@ -1,6 +1,9 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="RIGHT_MARGIN" value="160" />
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
|
|
54
matrix-sdk-android/src/main/assets/postMessageAPI.js
Executable file
54
matrix-sdk-android/src/main/assets/postMessageAPI.js
Executable file
|
@ -0,0 +1,54 @@
|
|||
var android_widget_events = {};
|
||||
|
||||
var sendObjectMessageToRiotAndroid = function(parameters) {
|
||||
Android.onWidgetEvent(JSON.stringify(parameters));
|
||||
};
|
||||
|
||||
var onWidgetMessageToRiotAndroid = function(event) {
|
||||
/* Use an internal "_id" field for matching onMessage events and requests
|
||||
_id was originally used by the Modular API. Keep it */
|
||||
if (!event.data._id) {
|
||||
/* The Matrix Widget API v2 spec says:
|
||||
"The requestId field should be unique and included in all requests" */
|
||||
event.data._id = event.data.requestId;
|
||||
}
|
||||
/* Make sure to have one id */
|
||||
if (!event.data._id) {
|
||||
event.data._id = Date.now() + "-" + Math.random().toString(36);
|
||||
}
|
||||
|
||||
console.log("onWidgetMessageToRiotAndroid " + event.data._id);
|
||||
|
||||
if (android_widget_events[event.data._id]) {
|
||||
console.log("onWidgetMessageToRiotAndroid : already managed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.origin) {
|
||||
event.origin = event.originalEvent.origin;
|
||||
}
|
||||
|
||||
android_widget_events[event.data._id] = event;
|
||||
|
||||
console.log("onWidgetMessageToRiotAndroid : manage " + event.data);
|
||||
sendObjectMessageToRiotAndroid({'event.data': event.data});
|
||||
};
|
||||
|
||||
var sendResponseFromRiotAndroid = function(eventId, res) {
|
||||
var event = android_widget_events[eventId];
|
||||
|
||||
console.log("sendResponseFromRiotAndroid to " + event.data.action + " for "+ eventId + ": " + JSON.stringify(res));
|
||||
|
||||
var data = JSON.parse(JSON.stringify(event.data));
|
||||
|
||||
data.response = res;
|
||||
|
||||
console.log("sendResponseFromRiotAndroid ---> " + data);
|
||||
|
||||
event.source.postMessage(data, event.origin);
|
||||
android_widget_events[eventId] = true;
|
||||
|
||||
console.log("sendResponseFromRiotAndroid to done");
|
||||
};
|
||||
|
||||
window.addEventListener('message', onWidgetMessageToRiotAndroid, false);
|
|
@ -40,6 +40,7 @@ import im.vector.matrix.android.api.session.signout.SignOutService
|
|||
import im.vector.matrix.android.api.session.sync.FilterService
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.session.user.UserService
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetService
|
||||
|
||||
/**
|
||||
* This interface defines interactions with a session.
|
||||
|
@ -61,7 +62,8 @@ interface Session :
|
|||
HomeServerCapabilitiesService,
|
||||
SecureStorageService,
|
||||
AccountDataService,
|
||||
AccountService {
|
||||
AccountService,
|
||||
WidgetService {
|
||||
|
||||
/**
|
||||
* The params associated to the session
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.widgets
|
||||
|
||||
import android.webkit.WebView
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
|
||||
interface WidgetPostAPIMediator {
|
||||
|
||||
/**
|
||||
* This initialize the mediator and configure the webview.
|
||||
* It will add a JavaScript Interface.
|
||||
* Please call [clear] method when finished to clean the provided webview
|
||||
*/
|
||||
fun initialize(webView: WebView, handler: Handler)
|
||||
|
||||
/**
|
||||
* This clear the mediator by removing the JavaScript Interface and cleaning references.
|
||||
*/
|
||||
fun clear()
|
||||
|
||||
/**
|
||||
* Inject the necessary javascript into the configured WebView.
|
||||
* Should be called after a web page has been loaded.
|
||||
*/
|
||||
fun injectAPI()
|
||||
|
||||
/**
|
||||
* Send a boolean response
|
||||
*
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendBoolResponse(response: Boolean, eventData: JsonDict)
|
||||
|
||||
/**
|
||||
* Send an integer response
|
||||
*
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendIntegerResponse(response: Int, eventData: JsonDict)
|
||||
|
||||
/**
|
||||
* Send an object response
|
||||
*
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendObjectResponse(response: JsonDict?, eventData: JsonDict)
|
||||
|
||||
/**
|
||||
* Send success
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendSuccess(eventData: JsonDict)
|
||||
|
||||
/**
|
||||
* Send an error
|
||||
*
|
||||
* @param message the error message
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendError(message: String, eventData: JsonDict)
|
||||
|
||||
interface Handler {
|
||||
/**
|
||||
* Triggered when a widget is posting
|
||||
*/
|
||||
fun handleWidgetRequest(data: JsonDict): Boolean
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.api.session.widgets
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.events.model.Content
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.internal.session.widgets.Widget
|
||||
|
||||
interface WidgetService {
|
||||
|
||||
fun getWidgetPostAPIMediator(): WidgetPostAPIMediator
|
||||
|
||||
fun getRoomWidgets(
|
||||
roomId: String,
|
||||
widgetId: QueryStringValue = QueryStringValue.NoCondition,
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): List<Widget>
|
||||
|
||||
fun createRoomWidget(roomId: String, widgetId: String, content: Content, callback: MatrixCallback<Widget>): Cancelable
|
||||
|
||||
fun destroyRoomWidget(roomId: String, widgetId: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun hasPermissionsToHandleWidgets(roomId: String): Boolean
|
||||
}
|
|
@ -29,4 +29,28 @@ data class WidgetContent(
|
|||
@Json(name = "name") val name: String? = null,
|
||||
@Json(name = "data") val data: JsonDict = emptyMap(),
|
||||
@Json(name = "waitForIframeLoad") val waitForIframeLoad: Boolean = false
|
||||
)
|
||||
) {
|
||||
|
||||
/**
|
||||
* @return the human name
|
||||
*/
|
||||
fun getHumanName(): String {
|
||||
return if (!name.isNullOrBlank()) {
|
||||
"$name widget"
|
||||
} else if (!type.isNullOrBlank()) {
|
||||
when {
|
||||
type.contains("widget") -> {
|
||||
type
|
||||
}
|
||||
id != null -> {
|
||||
"$type $id"
|
||||
}
|
||||
else -> {
|
||||
"$type widget"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"Widget $id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import im.vector.matrix.android.api.session.signout.SignOutService
|
|||
import im.vector.matrix.android.api.session.sync.FilterService
|
||||
import im.vector.matrix.android.api.session.sync.SyncState
|
||||
import im.vector.matrix.android.api.session.user.UserService
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetService
|
||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater
|
||||
|
@ -88,6 +89,7 @@ internal class DefaultSession @Inject constructor(
|
|||
private val fileService: Lazy<FileService>,
|
||||
private val secureStorageService: Lazy<SecureStorageService>,
|
||||
private val profileService: Lazy<ProfileService>,
|
||||
private val widgetService: Lazy<WidgetService>,
|
||||
private val syncThreadProvider: Provider<SyncThread>,
|
||||
private val contentUrlResolver: ContentUrlResolver,
|
||||
private val syncTokenStore: SyncTokenStore,
|
||||
|
@ -117,7 +119,8 @@ internal class DefaultSession @Inject constructor(
|
|||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
||||
ProfileService by profileService.get(),
|
||||
AccountDataService by accountDataService.get(),
|
||||
AccountService by accountService.get() {
|
||||
AccountService by accountService.get(),
|
||||
WidgetService by widgetService.get() {
|
||||
|
||||
override val sharedSecretStorageService: SharedSecretStorageService
|
||||
get() = _sharedSecretStorageService.get()
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.widgets
|
||||
|
||||
import android.os.Build
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import com.squareup.moshi.Moshi
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetPostAPIMediator
|
||||
import im.vector.matrix.android.api.util.JSON_DICT_PARAMETERIZED_TYPE
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import timber.log.Timber
|
||||
import java.util.HashMap
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultWidgetPostAPIMediator @Inject constructor(moshi: Moshi,
|
||||
private val widgetPostMessageAPIProvider: WidgetPostMessageAPIProvider) : WidgetPostAPIMediator {
|
||||
|
||||
private val adapter = moshi.adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
|
||||
private var handler: WidgetPostAPIMediator.Handler? = null
|
||||
private var webView: WebView? = null
|
||||
|
||||
override fun initialize(webView: WebView, handler: WidgetPostAPIMediator.Handler) {
|
||||
this.webView = webView
|
||||
this.handler = handler
|
||||
webView.addJavascriptInterface(this, "WidgetPostAPIMediator")
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
handler = null
|
||||
webView?.removeJavascriptInterface("WidgetPostAPIMediator")
|
||||
webView = null
|
||||
}
|
||||
|
||||
override fun injectAPI() {
|
||||
val js = widgetPostMessageAPIProvider.get()
|
||||
if (null != js) {
|
||||
webView?.loadUrl("javascript:$js")
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun onWidgetEvent(jsonEventData: String) {
|
||||
Timber.d("BRIDGE onWidgetEvent : $jsonEventData")
|
||||
try {
|
||||
val dataAsDict = adapter.fromJson(jsonEventData)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val eventData = (dataAsDict?.get("event.data") as? JsonDict) ?: return
|
||||
onWidgetMessage(eventData)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## onWidgetEvent() failed")
|
||||
}
|
||||
}
|
||||
|
||||
private fun onWidgetMessage(eventData: JsonDict) {
|
||||
try {
|
||||
if (handler?.handleWidgetRequest(eventData) == false) {
|
||||
sendError("", eventData)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## onWidgetMessage() : failed")
|
||||
sendError("", eventData)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* *********************************************************************************************
|
||||
* Message sending methods
|
||||
* *********************************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a boolean response
|
||||
*
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
override fun sendBoolResponse(response: Boolean, eventData: JsonDict) {
|
||||
val jsString = if (response) "true" else "false"
|
||||
sendResponse(jsString, eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an integer response
|
||||
*
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
override fun sendIntegerResponse(response: Int, eventData: JsonDict) {
|
||||
sendResponse(response.toString() + "", eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an object response
|
||||
*
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
override fun sendObjectResponse(response: JsonDict?, eventData: JsonDict) {
|
||||
var jsString: String? = null
|
||||
if (response != null) {
|
||||
try {
|
||||
jsString = "JSON.parse('${adapter.toJson(response)}')"
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## sendObjectResponse() : toJson failed ")
|
||||
}
|
||||
}
|
||||
sendResponse(jsString ?: "null", eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send success
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
override fun sendSuccess(eventData: JsonDict) {
|
||||
val successResponse = mapOf("success" to true)
|
||||
sendObjectResponse(successResponse, eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an error
|
||||
*
|
||||
* @param message the error message
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
override fun sendError(message: String, eventData: JsonDict) {
|
||||
Timber.e("## sendError() : eventData $eventData failed $message")
|
||||
|
||||
// TODO: JS has an additional optional parameter: nestedError
|
||||
val params = HashMap<String, Map<String, String>>()
|
||||
val subMap = HashMap<String, String>()
|
||||
subMap["message"] = message
|
||||
params["error"] = subMap
|
||||
sendObjectResponse(params, eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the response to the javascript
|
||||
*
|
||||
* @param jsString the response data
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun sendResponse(jsString: String, eventData: JsonDict) {
|
||||
try {
|
||||
val functionLine = "sendResponseFromRiotAndroid('" + eventData["_id"] + "' , " + jsString + ");"
|
||||
Timber.v("BRIDGE sendResponse: $functionLine")
|
||||
// call the javascript method
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
webView?.loadUrl("javascript:$functionLine")
|
||||
} else {
|
||||
webView?.evaluateJavascript(functionLine, null)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## sendResponse() failed ")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.widgets
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.events.model.Content
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetPostAPIMediator
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetService
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
internal class DefaultWidgetService @Inject constructor(private val widgetManager: WidgetManager,
|
||||
private val widgetPostAPIMediator: Provider<WidgetPostAPIMediator>) : WidgetService {
|
||||
|
||||
override fun getWidgetPostAPIMediator(): WidgetPostAPIMediator {
|
||||
return widgetPostAPIMediator.get()
|
||||
}
|
||||
|
||||
override fun getRoomWidgets(roomId: String, widgetId: QueryStringValue, widgetTypes: Set<String>?, excludedTypes: Set<String>?): List<Widget> {
|
||||
return widgetManager.getRoomWidgets(roomId, widgetId, widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
override fun createRoomWidget(roomId: String, widgetId: String, content: Content, callback: MatrixCallback<Widget>): Cancelable {
|
||||
return widgetManager.createWidget(roomId, widgetId, content, callback)
|
||||
}
|
||||
|
||||
override fun destroyRoomWidget(roomId: String, widgetId: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return widgetManager.destroyWidget(roomId, widgetId, callback)
|
||||
}
|
||||
|
||||
override fun hasPermissionsToHandleWidgets(roomId: String): Boolean {
|
||||
return widgetManager.hasPermissionsToHandleWidgets(roomId)
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ package im.vector.matrix.android.internal.session.widgets
|
|||
|
||||
import im.vector.matrix.android.api.failure.Failure
|
||||
|
||||
sealed class CreateWidgetFailure : Failure.FeatureFailure() {
|
||||
object NotEnoughtPower : CreateWidgetFailure()
|
||||
object CreationFailed : CreateWidgetFailure()
|
||||
sealed class WidgetManagementFailure : Failure.FeatureFailure() {
|
||||
object NotEnoughPower : WidgetManagementFailure()
|
||||
object CreationFailed : WidgetManagementFailure()
|
||||
}
|
|
@ -101,7 +101,7 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
|||
fun createWidget(roomId: String, widgetId: String, content: Content, callback: MatrixCallback<Widget>): Cancelable {
|
||||
return taskExecutor.executorScope.launchToCallback(callback = callback) {
|
||||
if (!hasPermissionsToHandleWidgets(roomId)) {
|
||||
throw CreateWidgetFailure.NotEnoughtPower
|
||||
throw WidgetManagementFailure.NotEnoughPower
|
||||
}
|
||||
val params = CreateWidgetTask.Params(
|
||||
roomId = roomId,
|
||||
|
@ -112,11 +112,25 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
|||
try {
|
||||
getRoomWidgets(roomId, widgetId = QueryStringValue.Equals(widgetId, QueryStringValue.Case.INSENSITIVE)).first()
|
||||
} catch (failure: Throwable) {
|
||||
throw CreateWidgetFailure.CreationFailed
|
||||
throw WidgetManagementFailure.CreationFailed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun destroyWidget(roomId: String, widgetId: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return taskExecutor.executorScope.launchToCallback(callback = callback) {
|
||||
if (!hasPermissionsToHandleWidgets(roomId)) {
|
||||
throw WidgetManagementFailure.NotEnoughPower
|
||||
}
|
||||
val params = CreateWidgetTask.Params(
|
||||
roomId = roomId,
|
||||
widgetId = widgetId,
|
||||
content = emptyMap()
|
||||
)
|
||||
createWidgetTask.execute(params)
|
||||
}
|
||||
}
|
||||
|
||||
fun hasPermissionsToHandleWidgets(roomId: String): Boolean {
|
||||
val powerLevelsEvent = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)
|
||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() ?: return false
|
||||
|
|
|
@ -19,6 +19,8 @@ package im.vector.matrix.android.internal.session.widgets
|
|||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetPostAPIMediator
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetService
|
||||
import im.vector.matrix.android.internal.session.widgets.token.DefaultGetScalarTokenTask
|
||||
import im.vector.matrix.android.internal.session.widgets.token.GetScalarTokenTask
|
||||
import retrofit2.Retrofit
|
||||
|
@ -35,6 +37,12 @@ internal abstract class WidgetModule {
|
|||
}
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract fun bindWidgetService(widgetService: DefaultWidgetService): WidgetService
|
||||
|
||||
@Binds
|
||||
abstract fun bindWidgetPostAPIMediator(widgetPostMessageAPIProvider: DefaultWidgetPostAPIMediator): WidgetPostAPIMediator
|
||||
|
||||
@Binds
|
||||
abstract fun bindCreateWidgetTask(task: DefaultCreateWidgetTask): CreateWidgetTask
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.matrix.android.internal.session.widgets
|
||||
|
||||
import android.content.Context
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class WidgetPostMessageAPIProvider @Inject constructor(private val context: Context) {
|
||||
|
||||
private var postMessageAPIString: String? = null
|
||||
|
||||
fun get(): String? {
|
||||
if (postMessageAPIString == null) {
|
||||
postMessageAPIString = readFromAsset(context)
|
||||
}
|
||||
return postMessageAPIString
|
||||
}
|
||||
|
||||
private fun readFromAsset(context: Context): String? {
|
||||
return try {
|
||||
context.assets.open("postMessageAPI.js").bufferedReader().use {
|
||||
it.readText()
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "Reading postMessageAPI.js asset failed")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,9 @@ import im.vector.matrix.android.internal.extensions.foldToCallback
|
|||
import im.vector.matrix.android.internal.util.toCancelable
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
|
@ -34,5 +36,7 @@ internal fun <T> CoroutineScope.launchToCallback(
|
|||
val result = runCatching {
|
||||
block()
|
||||
}
|
||||
result.foldToCallback(callback)
|
||||
withContext(Dispatchers.Main) {
|
||||
result.foldToCallback(callback)
|
||||
}
|
||||
}.toCancelable()
|
||||
|
|
Loading…
Reference in a new issue