mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
Add input dialog
This commit is contained in:
@@ -1276,5 +1276,20 @@ let UI = {
|
|||||||
function: 'cancelLoading',
|
function: 'cancelLoading',
|
||||||
id: id
|
id: id
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show an input dialog
|
||||||
|
* @param title {string}
|
||||||
|
* @param validator {(string) => string | null | undefined} - A function that validates the input. If the function returns a string, the dialog will show the error message.
|
||||||
|
* @returns {string | null} - The input value. If the dialog is canceled, return null.
|
||||||
|
*/
|
||||||
|
showInputDialog: (title, validator) => {
|
||||||
|
return sendMessage({
|
||||||
|
method: 'UI',
|
||||||
|
function: 'showInputDialog',
|
||||||
|
title: title,
|
||||||
|
validator: validator
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -34,6 +34,12 @@ mixin class JsUiApi {
|
|||||||
if (id is int) {
|
if (id is int) {
|
||||||
cancelLoading(id);
|
cancelLoading(id);
|
||||||
}
|
}
|
||||||
|
case 'showInputDialog':
|
||||||
|
var title = message['title'];
|
||||||
|
var validator = message['validator'];
|
||||||
|
if (title is! String) return;
|
||||||
|
if (validator != null && validator is! JSInvokable) return;
|
||||||
|
return _showInputDialog(title, validator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,8 +53,6 @@ mixin class JsUiApi {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var callback = action['callback'] as JSInvokable;
|
var callback = action['callback'] as JSInvokable;
|
||||||
// [message] will be released after the method call, causing the action to be invalid, so we need to duplicate it
|
|
||||||
callback.dup();
|
|
||||||
var text = action['text'].toString();
|
var text = action['text'].toString();
|
||||||
var style = (action['style'] ?? 'text').toString();
|
var style = (action['style'] ?? 'text').toString();
|
||||||
actions.add(_JSCallbackButton(
|
actions.add(_JSCallbackButton(
|
||||||
@@ -84,15 +88,16 @@ mixin class JsUiApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int showLoading(JSInvokable? onCancel) {
|
int showLoading(JSInvokable? onCancel) {
|
||||||
onCancel?.dup();
|
|
||||||
var func = onCancel == null ? null : JSAutoFreeFunction(onCancel);
|
var func = onCancel == null ? null : JSAutoFreeFunction(onCancel);
|
||||||
var controller = showLoadingDialog(
|
var controller = showLoadingDialog(
|
||||||
App.rootContext,
|
App.rootContext,
|
||||||
barrierDismissible: onCancel != null,
|
barrierDismissible: onCancel != null,
|
||||||
allowCancel: onCancel != null,
|
allowCancel: onCancel != null,
|
||||||
onCancel: onCancel == null ? null : () {
|
onCancel: onCancel == null
|
||||||
func?.call([]);
|
? null
|
||||||
},
|
: () {
|
||||||
|
func?.call([]);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
var i = 0;
|
var i = 0;
|
||||||
while (_loadingDialogControllers.containsKey(i)) {
|
while (_loadingDialogControllers.containsKey(i)) {
|
||||||
@@ -106,6 +111,29 @@ mixin class JsUiApi {
|
|||||||
var controller = _loadingDialogControllers.remove(id);
|
var controller = _loadingDialogControllers.remove(id);
|
||||||
controller?.close();
|
controller?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String?> _showInputDialog(String title, JSInvokable? validator) async {
|
||||||
|
String? result;
|
||||||
|
var func = validator == null ? null : JSAutoFreeFunction(validator);
|
||||||
|
await showInputDialog(
|
||||||
|
context: App.rootContext,
|
||||||
|
title: title,
|
||||||
|
onConfirm: (v) {
|
||||||
|
if (func != null) {
|
||||||
|
var res = func.call([v]);
|
||||||
|
if (res != null) {
|
||||||
|
return res.toString();
|
||||||
|
} else {
|
||||||
|
result = v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = v;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _JSCallbackButton extends StatefulWidget {
|
class _JSCallbackButton extends StatefulWidget {
|
||||||
|
@@ -63,7 +63,8 @@ class ReaderImageProvider
|
|||||||
})()
|
})()
|
||||||
''');
|
''');
|
||||||
if (func is JSInvokable) {
|
if (func is JSInvokable) {
|
||||||
var result = func.invoke([imageBytes, cid, eid, page, sourceKey]);
|
var autoFreeFunc = JSAutoFreeFunction(func);
|
||||||
|
var result = autoFreeFunc([imageBytes, cid, eid, page, sourceKey]);
|
||||||
if (result is Uint8List) {
|
if (result is Uint8List) {
|
||||||
imageBytes = result;
|
imageBytes = result;
|
||||||
} else if (result is Future) {
|
} else if (result is Future) {
|
||||||
@@ -76,9 +77,9 @@ class ReaderImageProvider
|
|||||||
if (image is Uint8List) {
|
if (image is Uint8List) {
|
||||||
imageBytes = image;
|
imageBytes = image;
|
||||||
} else if (image is Future) {
|
} else if (image is Future) {
|
||||||
JSInvokable? onCancel;
|
JSAutoFreeFunction? onCancel;
|
||||||
if (result['onCancel'] is JSInvokable) {
|
if (result['onCancel'] is JSInvokable) {
|
||||||
onCancel = result['onCancel'];
|
onCancel = JSAutoFreeFunction(result['onCancel']);
|
||||||
}
|
}
|
||||||
if (onCancel == null) {
|
if (onCancel == null) {
|
||||||
var futureImage = await image;
|
var futureImage = await image;
|
||||||
@@ -96,9 +97,7 @@ class ReaderImageProvider
|
|||||||
checkStop();
|
checkStop();
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
onCancel.invoke([]);
|
onCancel([]);
|
||||||
onCancel.free();
|
|
||||||
func.free();
|
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
await Future.delayed(Duration(milliseconds: 50));
|
await Future.delayed(Duration(milliseconds: 50));
|
||||||
@@ -107,10 +106,8 @@ class ReaderImageProvider
|
|||||||
imageBytes = futureImage;
|
imageBytes = futureImage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onCancel?.free();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func.free();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return imageBytes!;
|
return imageBytes!;
|
||||||
|
@@ -677,6 +677,7 @@ class JSAutoFreeFunction {
|
|||||||
|
|
||||||
/// Automatically free the function when it's not used anymore
|
/// Automatically free the function when it's not used anymore
|
||||||
JSAutoFreeFunction(this.func) {
|
JSAutoFreeFunction(this.func) {
|
||||||
|
func.dup();
|
||||||
finalizer.attach(this, func);
|
finalizer.attach(this, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,6 +686,6 @@ class JSAutoFreeFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static final finalizer = Finalizer<JSInvokable>((func) {
|
static final finalizer = Finalizer<JSInvokable>((func) {
|
||||||
func.free();
|
func.destroy();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user