fixed handling wallpaper intent without uri
#1052 handle secure review intent
This commit is contained in:
parent
0f1d8ec760
commit
27db528e67
6 changed files with 69 additions and 119 deletions
|
@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- switching to PiP when changing device orientation on Android >=13
|
- switching to PiP when changing device orientation on Android >=13
|
||||||
|
- handling wallpaper intent without URI
|
||||||
|
|
||||||
## <a id="v1.11.3"></a>[v1.11.3] - 2024-06-17
|
## <a id="v1.11.3"></a>[v1.11.3] - 2024-06-17
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:showWhenLocked="true"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
tools:targetApi="tiramisu">
|
tools:targetApi="tiramisu">
|
||||||
<activity
|
<activity
|
||||||
|
@ -143,6 +144,7 @@
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<action android:name="android.provider.action.REVIEW" />
|
<action android:name="android.provider.action.REVIEW" />
|
||||||
|
<action android:name="android.provider.action.REVIEW_SECURE" />
|
||||||
<action android:name="com.android.camera.action.REVIEW" />
|
<action android:name="com.android.camera.action.REVIEW" />
|
||||||
<action android:name="com.android.camera.action.SPLIT_SCREEN_REVIEW" />
|
<action android:name="com.android.camera.action.SPLIT_SCREEN_REVIEW" />
|
||||||
|
|
||||||
|
@ -163,6 +165,7 @@
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<action android:name="android.provider.action.REVIEW" />
|
<action android:name="android.provider.action.REVIEW" />
|
||||||
|
<action android:name="android.provider.action.REVIEW_SECURE" />
|
||||||
<action android:name="com.android.camera.action.REVIEW" />
|
<action android:name="com.android.camera.action.REVIEW" />
|
||||||
<action android:name="com.android.camera.action.SPLIT_SCREEN_REVIEW" />
|
<action android:name="com.android.camera.action.SPLIT_SCREEN_REVIEW" />
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import deckers.thibault.aves.channel.calls.MetadataEditHandler
|
||||||
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
||||||
import deckers.thibault.aves.channel.calls.SecurityHandler
|
import deckers.thibault.aves.channel.calls.SecurityHandler
|
||||||
import deckers.thibault.aves.channel.calls.StorageHandler
|
import deckers.thibault.aves.channel.calls.StorageHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.WallpaperHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
||||||
import deckers.thibault.aves.channel.streams.ActivityResultStreamHandler
|
import deckers.thibault.aves.channel.streams.ActivityResultStreamHandler
|
||||||
|
@ -135,6 +136,7 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
MethodChannel(messenger, AccessibilityHandler.CHANNEL).setMethodCallHandler(AccessibilityHandler(this))
|
MethodChannel(messenger, AccessibilityHandler.CHANNEL).setMethodCallHandler(AccessibilityHandler(this))
|
||||||
MethodChannel(messenger, MediaEditHandler.CHANNEL).setMethodCallHandler(MediaEditHandler(this))
|
MethodChannel(messenger, MediaEditHandler.CHANNEL).setMethodCallHandler(MediaEditHandler(this))
|
||||||
MethodChannel(messenger, MetadataEditHandler.CHANNEL).setMethodCallHandler(MetadataEditHandler(this))
|
MethodChannel(messenger, MetadataEditHandler.CHANNEL).setMethodCallHandler(MetadataEditHandler(this))
|
||||||
|
MethodChannel(messenger, WallpaperHandler.CHANNEL).setMethodCallHandler(WallpaperHandler(this))
|
||||||
// - need Activity
|
// - need Activity
|
||||||
MethodChannel(messenger, WindowHandler.CHANNEL).setMethodCallHandler(ActivityWindowHandler(this))
|
MethodChannel(messenger, WindowHandler.CHANNEL).setMethodCallHandler(ActivityWindowHandler(this))
|
||||||
|
|
||||||
|
@ -301,16 +303,32 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
Intent.ACTION_VIEW,
|
Intent.ACTION_VIEW,
|
||||||
Intent.ACTION_SEND,
|
Intent.ACTION_SEND,
|
||||||
MediaStore.ACTION_REVIEW,
|
MediaStore.ACTION_REVIEW,
|
||||||
|
MediaStore.ACTION_REVIEW_SECURE,
|
||||||
"com.android.camera.action.REVIEW",
|
"com.android.camera.action.REVIEW",
|
||||||
"com.android.camera.action.SPLIT_SCREEN_REVIEW" -> {
|
"com.android.camera.action.SPLIT_SCREEN_REVIEW" -> {
|
||||||
(intent.data ?: intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM))?.let { uri ->
|
(intent.data ?: intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM))?.let { uri ->
|
||||||
// MIME type is optional
|
// MIME type is optional
|
||||||
val type = intent.type ?: intent.resolveType(this)
|
val type = intent.type ?: intent.resolveType(this)
|
||||||
return hashMapOf(
|
val fields = hashMapOf<String, Any?>(
|
||||||
INTENT_DATA_KEY_ACTION to INTENT_ACTION_VIEW,
|
INTENT_DATA_KEY_ACTION to INTENT_ACTION_VIEW,
|
||||||
INTENT_DATA_KEY_MIME_TYPE to type,
|
INTENT_DATA_KEY_MIME_TYPE to type,
|
||||||
INTENT_DATA_KEY_URI to uri.toString(),
|
INTENT_DATA_KEY_URI to uri.toString(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (action == MediaStore.ACTION_REVIEW_SECURE) {
|
||||||
|
val uris = ArrayList<String>()
|
||||||
|
intent.clipData?.let { clipData ->
|
||||||
|
for (i in 0 until clipData.itemCount) {
|
||||||
|
clipData.getItemAt(i).uri?.let { uris.add(it.toString()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields[INTENT_DATA_KEY_SECURE_URIS] = uris
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && intent.hasExtra(MediaStore.EXTRA_BRIGHTNESS)) {
|
||||||
|
fields[INTENT_DATA_KEY_BRIGHTNESS] = intent.getFloatExtra(MediaStore.EXTRA_BRIGHTNESS, 0f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,7 +408,7 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun submitPickedItems(call: MethodCall) {
|
open fun submitPickedItems(call: MethodCall) {
|
||||||
val pickedUris = call.argument<List<String>>("uris")
|
val pickedUris = call.argument<List<String>>("uris")
|
||||||
if (!pickedUris.isNullOrEmpty()) {
|
if (!pickedUris.isNullOrEmpty()) {
|
||||||
val toUri = { uriString: String -> AppAdapterHandler.getShareableUri(this, Uri.parse(uriString)) }
|
val toUri = { uriString: String -> AppAdapterHandler.getShareableUri(this, Uri.parse(uriString)) }
|
||||||
|
@ -498,11 +516,13 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
|
|
||||||
const val INTENT_DATA_KEY_ACTION = "action"
|
const val INTENT_DATA_KEY_ACTION = "action"
|
||||||
const val INTENT_DATA_KEY_ALLOW_MULTIPLE = "allowMultiple"
|
const val INTENT_DATA_KEY_ALLOW_MULTIPLE = "allowMultiple"
|
||||||
|
const val INTENT_DATA_KEY_BRIGHTNESS = "brightness"
|
||||||
const val INTENT_DATA_KEY_FILTERS = "filters"
|
const val INTENT_DATA_KEY_FILTERS = "filters"
|
||||||
const val INTENT_DATA_KEY_MIME_TYPE = "mimeType"
|
const val INTENT_DATA_KEY_MIME_TYPE = "mimeType"
|
||||||
const val INTENT_DATA_KEY_PAGE = "page"
|
const val INTENT_DATA_KEY_PAGE = "page"
|
||||||
const val INTENT_DATA_KEY_QUERY = "query"
|
const val INTENT_DATA_KEY_QUERY = "query"
|
||||||
const val INTENT_DATA_KEY_SAFE_MODE = "safeMode"
|
const val INTENT_DATA_KEY_SAFE_MODE = "safeMode"
|
||||||
|
const val INTENT_DATA_KEY_SECURE_URIS = "secureUris"
|
||||||
const val INTENT_DATA_KEY_URI = "uri"
|
const val INTENT_DATA_KEY_URI = "uri"
|
||||||
const val INTENT_DATA_KEY_WIDGET_ID = "widgetId"
|
const val INTENT_DATA_KEY_WIDGET_ID = "widgetId"
|
||||||
|
|
||||||
|
|
|
@ -2,132 +2,53 @@ package deckers.thibault.aves
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import deckers.thibault.aves.channel.calls.AppAdapterHandler
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.util.Log
|
|
||||||
import app.loup.streams_channel.StreamsChannel
|
|
||||||
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
|
||||||
import deckers.thibault.aves.channel.calls.AccessibilityHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.DeviceHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.EmbeddedDataHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.MediaFetchBytesHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.MediaFetchObjectHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.MediaSessionHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.StorageHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.WallpaperHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
|
||||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
|
||||||
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
|
||||||
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
|
||||||
import deckers.thibault.aves.model.FieldMap
|
import deckers.thibault.aves.model.FieldMap
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
|
||||||
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
||||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
|
||||||
import io.flutter.plugin.common.EventChannel
|
|
||||||
import io.flutter.plugin.common.MethodCall
|
import io.flutter.plugin.common.MethodCall
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
|
|
||||||
class WallpaperActivity : FlutterFragmentActivity() {
|
class WallpaperActivity : MainActivity() {
|
||||||
private lateinit var intentDataMap: FieldMap
|
private var originalIntent: String? = null
|
||||||
private lateinit var mediaSessionHandler: MediaSessionHandler
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun extractIntentData(intent: Intent?): FieldMap {
|
||||||
super.onCreate(savedInstanceState)
|
if (intent != null) {
|
||||||
|
when (intent.action) {
|
||||||
Log.i(LOG_TAG, "onCreate intent=$intent")
|
|
||||||
intent.extras?.takeUnless { it.isEmpty }?.let {
|
|
||||||
Log.i(LOG_TAG, "onCreate intent extras=$it")
|
|
||||||
}
|
|
||||||
intentDataMap = extractIntentData(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
|
||||||
super.configureFlutterEngine(flutterEngine)
|
|
||||||
val messenger = flutterEngine.dartExecutor
|
|
||||||
|
|
||||||
// notification: platform -> dart
|
|
||||||
val mediaCommandStreamHandler = MediaCommandStreamHandler().apply {
|
|
||||||
EventChannel(messenger, MediaCommandStreamHandler.CHANNEL).setStreamHandler(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
// dart -> platform -> dart
|
|
||||||
// - need Context
|
|
||||||
mediaSessionHandler = MediaSessionHandler(this, mediaCommandStreamHandler)
|
|
||||||
MethodChannel(messenger, DeviceHandler.CHANNEL).setMethodCallHandler(DeviceHandler(this))
|
|
||||||
MethodChannel(messenger, EmbeddedDataHandler.CHANNEL).setMethodCallHandler(EmbeddedDataHandler(this))
|
|
||||||
MethodChannel(messenger, MediaFetchBytesHandler.CHANNEL, AvesByteSendingMethodCodec.INSTANCE).setMethodCallHandler(MediaFetchBytesHandler(this))
|
|
||||||
MethodChannel(messenger, MediaFetchObjectHandler.CHANNEL).setMethodCallHandler(MediaFetchObjectHandler(this))
|
|
||||||
MethodChannel(messenger, MediaSessionHandler.CHANNEL).setMethodCallHandler(mediaSessionHandler)
|
|
||||||
MethodChannel(messenger, MetadataFetchHandler.CHANNEL).setMethodCallHandler(MetadataFetchHandler(this))
|
|
||||||
MethodChannel(messenger, StorageHandler.CHANNEL).setMethodCallHandler(StorageHandler(this))
|
|
||||||
// - need ContextWrapper
|
|
||||||
MethodChannel(messenger, AccessibilityHandler.CHANNEL).setMethodCallHandler(AccessibilityHandler(this))
|
|
||||||
MethodChannel(messenger, WallpaperHandler.CHANNEL).setMethodCallHandler(WallpaperHandler(this))
|
|
||||||
// - need Activity
|
|
||||||
MethodChannel(messenger, WindowHandler.CHANNEL).setMethodCallHandler(ActivityWindowHandler(this))
|
|
||||||
|
|
||||||
// result streaming: dart -> platform ->->-> dart
|
|
||||||
// - need Context
|
|
||||||
StreamsChannel(messenger, ImageByteStreamHandler.CHANNEL).setStreamHandlerFactory { args -> ImageByteStreamHandler(this, args) }
|
|
||||||
|
|
||||||
// intent handling
|
|
||||||
// detail fetch: dart -> platform
|
|
||||||
MethodChannel(messenger, MainActivity.INTENT_CHANNEL).setMethodCallHandler { call, result -> onMethodCall(call, result) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
Log.i(LOG_TAG, "onStart")
|
|
||||||
super.onStart()
|
|
||||||
|
|
||||||
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
|
||||||
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
|
||||||
// so we manually request to apply the insets to update the window metrics
|
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
|
||||||
window.decorView.requestApplyInsets()
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
mediaSessionHandler.dispose()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
|
||||||
when (call.method) {
|
|
||||||
"getIntentData" -> {
|
|
||||||
result.success(intentDataMap)
|
|
||||||
intentDataMap.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extractIntentData(intent: Intent?): FieldMap {
|
|
||||||
when (intent?.action) {
|
|
||||||
Intent.ACTION_ATTACH_DATA, Intent.ACTION_SET_WALLPAPER -> {
|
Intent.ACTION_ATTACH_DATA, Intent.ACTION_SET_WALLPAPER -> {
|
||||||
(intent.data ?: intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM))?.let { uri ->
|
(intent.data ?: intent.getParcelableExtraCompat<Uri>(Intent.EXTRA_STREAM))?.let { uri ->
|
||||||
// MIME type is optional
|
// MIME type is optional
|
||||||
val type = intent.type ?: intent.resolveType(this)
|
val type = intent.type ?: intent.resolveType(this)
|
||||||
return hashMapOf(
|
return hashMapOf(
|
||||||
MainActivity.INTENT_DATA_KEY_ACTION to MainActivity.INTENT_ACTION_SET_WALLPAPER,
|
INTENT_DATA_KEY_ACTION to INTENT_ACTION_SET_WALLPAPER,
|
||||||
MainActivity.INTENT_DATA_KEY_MIME_TYPE to type,
|
INTENT_DATA_KEY_MIME_TYPE to type,
|
||||||
MainActivity.INTENT_DATA_KEY_URI to uri.toString(),
|
INTENT_DATA_KEY_URI to uri.toString(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Intent.ACTION_RUN -> {
|
// if the media URI is not provided we need to pick one first
|
||||||
// flutter run
|
originalIntent = intent.action
|
||||||
}
|
intent.action = Intent.ACTION_PICK
|
||||||
else -> {
|
|
||||||
Log.w(LOG_TAG, "unhandled intent action=${intent?.action}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return HashMap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
return super.extractIntentData(intent)
|
||||||
private val LOG_TAG = LogUtils.createTag<WallpaperActivity>()
|
}
|
||||||
|
|
||||||
|
override fun submitPickedItems(call: MethodCall) {
|
||||||
|
if (originalIntent != null) {
|
||||||
|
val pickedUris = call.argument<List<String>>("uris")
|
||||||
|
if (!pickedUris.isNullOrEmpty()) {
|
||||||
|
val toUri = { uriString: String -> AppAdapterHandler.getShareableUri(this, Uri.parse(uriString)) }
|
||||||
|
onNewIntent(Intent().apply {
|
||||||
|
action = originalIntent
|
||||||
|
data = toUri(pickedUris.first())
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
setResult(RESULT_CANCELED)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.submitPickedItems(call)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
int? _widgetId;
|
int? _widgetId;
|
||||||
String? _initialRouteName, _initialSearchQuery;
|
String? _initialRouteName, _initialSearchQuery;
|
||||||
Set<CollectionFilter>? _initialFilters;
|
Set<CollectionFilter>? _initialFilters;
|
||||||
|
List<String>? _secureUris;
|
||||||
|
|
||||||
static const allowedShortcutRoutes = [
|
static const allowedShortcutRoutes = [
|
||||||
CollectionPage.routeName,
|
CollectionPage.routeName,
|
||||||
|
@ -91,6 +92,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
final safeMode = intentData[IntentDataKeys.safeMode] ?? false;
|
final safeMode = intentData[IntentDataKeys.safeMode] ?? false;
|
||||||
final intentAction = intentData[IntentDataKeys.action];
|
final intentAction = intentData[IntentDataKeys.action];
|
||||||
_initialFilters = null;
|
_initialFilters = null;
|
||||||
|
_secureUris = null;
|
||||||
|
|
||||||
await androidFileUtils.init();
|
await androidFileUtils.init();
|
||||||
if (!{
|
if (!{
|
||||||
|
@ -127,6 +129,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
uri = intentData[IntentDataKeys.uri];
|
uri = intentData[IntentDataKeys.uri];
|
||||||
mimeType = intentData[IntentDataKeys.mimeType];
|
mimeType = intentData[IntentDataKeys.mimeType];
|
||||||
}
|
}
|
||||||
|
_secureUris = intentData[IntentDataKeys.secureUris];
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
_viewerEntry = await _initViewerEntry(
|
_viewerEntry = await _initViewerEntry(
|
||||||
uri: uri,
|
uri: uri,
|
||||||
|
@ -208,7 +211,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
canAnalyze: false,
|
canAnalyze: false,
|
||||||
);
|
);
|
||||||
case AppMode.view:
|
case AppMode.view:
|
||||||
if (_isViewerSourceable(_viewerEntry)) {
|
if (_isViewerSourceable(_viewerEntry) && _secureUris == null) {
|
||||||
final directory = _viewerEntry?.directory;
|
final directory = _viewerEntry?.directory;
|
||||||
if (directory != null) {
|
if (directory != null) {
|
||||||
unawaited(AnalysisService.registerCallback());
|
unawaited(AnalysisService.registerCallback());
|
||||||
|
|
|
@ -14,11 +14,13 @@ class IntentActions {
|
||||||
class IntentDataKeys {
|
class IntentDataKeys {
|
||||||
static const action = 'action';
|
static const action = 'action';
|
||||||
static const allowMultiple = 'allowMultiple';
|
static const allowMultiple = 'allowMultiple';
|
||||||
|
static const brightness = 'brightness';
|
||||||
static const filters = 'filters';
|
static const filters = 'filters';
|
||||||
static const mimeType = 'mimeType';
|
static const mimeType = 'mimeType';
|
||||||
static const page = 'page';
|
static const page = 'page';
|
||||||
static const query = 'query';
|
static const query = 'query';
|
||||||
static const safeMode = 'safeMode';
|
static const safeMode = 'safeMode';
|
||||||
|
static const secureUris = 'secureUris';
|
||||||
static const uri = 'uri';
|
static const uri = 'uri';
|
||||||
static const widgetId = 'widgetId';
|
static const widgetId = 'widgetId';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue