xfer
This commit is contained in:
parent
78d06fb187
commit
f0674e46d1
@ -101,9 +101,11 @@ impl TableStore {
|
|||||||
let db = Database::open(table_name.clone(), column_count)
|
let db = Database::open(table_name.clone(), column_count)
|
||||||
.await
|
.await
|
||||||
.wrap_err("failed to open tabledb")?;
|
.wrap_err("failed to open tabledb")?;
|
||||||
info!(
|
trace!(
|
||||||
"opened table store '{}' with table name '{:?}' with {} columns",
|
"opened table store '{}' with table name '{:?}' with {} columns",
|
||||||
name, table_name, column_count
|
name,
|
||||||
|
table_name,
|
||||||
|
column_count
|
||||||
);
|
);
|
||||||
|
|
||||||
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
|
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
|
||||||
|
@ -445,6 +445,10 @@ impl VeilidAPI {
|
|||||||
Ok("Connections purged".to_owned())
|
Ok("Connections purged".to_owned())
|
||||||
} else if args[0] == "routes" {
|
} else if args[0] == "routes" {
|
||||||
// Purge route spec store
|
// Purge route spec store
|
||||||
|
{
|
||||||
|
let mut dc = DEBUG_CACHE.lock();
|
||||||
|
dc.imported_routes.clear();
|
||||||
|
}
|
||||||
let rss = self.network_manager()?.routing_table().route_spec_store();
|
let rss = self.network_manager()?.routing_table().route_spec_store();
|
||||||
match rss.purge().await {
|
match rss.purge().await {
|
||||||
Ok(_) => Ok("Routes purged".to_owned()),
|
Ok(_) => Ok("Routes purged".to_owned()),
|
||||||
@ -865,12 +869,9 @@ impl VeilidAPI {
|
|||||||
} else if arg == "route" {
|
} else if arg == "route" {
|
||||||
self.debug_route(rest).await
|
self.debug_route(rest).await
|
||||||
} else {
|
} else {
|
||||||
Ok(">>> Unknown command\n".to_owned())
|
Err(VeilidAPIError::generic("Unknown debug command"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// if let Ok(res) = &res {
|
|
||||||
// debug!("{}", res);
|
|
||||||
// }
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:veilid/veilid.dart';
|
import 'package:veilid/veilid.dart';
|
||||||
import 'package:loggy/loggy.dart';
|
import 'package:loggy/loggy.dart';
|
||||||
import 'package:veilid_example/veilid_theme.dart';
|
import 'package:veilid_example/veilid_theme.dart';
|
||||||
@ -8,6 +9,7 @@ import 'package:veilid_example/veilid_theme.dart';
|
|||||||
import 'log_terminal.dart';
|
import 'log_terminal.dart';
|
||||||
import 'config.dart';
|
import 'config.dart';
|
||||||
import 'log.dart';
|
import 'log.dart';
|
||||||
|
import 'history_wrapper.dart';
|
||||||
|
|
||||||
// Main App
|
// Main App
|
||||||
class MyApp extends StatefulWidget {
|
class MyApp extends StatefulWidget {
|
||||||
@ -22,6 +24,8 @@ class _MyAppState extends State<MyApp> with UiLoggy {
|
|||||||
bool _startedUp = false;
|
bool _startedUp = false;
|
||||||
Stream<VeilidUpdate>? _updateStream;
|
Stream<VeilidUpdate>? _updateStream;
|
||||||
Future<void>? _updateProcessor;
|
Future<void>? _updateProcessor;
|
||||||
|
final _debugHistoryWrapper = HistoryWrapper();
|
||||||
|
String? _errorText;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -136,51 +140,79 @@ class _MyAppState extends State<MyApp> with UiLoggy {
|
|||||||
body: Column(children: [
|
body: Column(children: [
|
||||||
const Expanded(child: LogTerminal()),
|
const Expanded(child: LogTerminal()),
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(color: materialPrimaryColor, boxShadow: [
|
decoration: BoxDecoration(
|
||||||
BoxShadow(
|
color: materialBackgroundColor.shade100,
|
||||||
color: Colors.black.withOpacity(0.15),
|
boxShadow: [
|
||||||
spreadRadius: 4,
|
BoxShadow(
|
||||||
blurRadius: 4,
|
color: Colors.black.withOpacity(0.15),
|
||||||
)
|
spreadRadius: 4,
|
||||||
]),
|
blurRadius: 4,
|
||||||
|
)
|
||||||
|
]),
|
||||||
padding: const EdgeInsets.all(5.0),
|
padding: const EdgeInsets.all(5.0),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: pad(TextField(
|
child: pad(_debugHistoryWrapper.wrap(
|
||||||
decoration:
|
setState,
|
||||||
newInputDecoration('Debug Command', _startedUp),
|
TextField(
|
||||||
textInputAction: TextInputAction.send,
|
controller: _debugHistoryWrapper.controller,
|
||||||
enabled: _startedUp,
|
decoration: newInputDecoration(
|
||||||
onSubmitted: (String v) async {
|
'Debug Command', _errorText, _startedUp),
|
||||||
loggy.info(await Veilid.instance.debug(v));
|
textInputAction: TextInputAction.unspecified,
|
||||||
}))),
|
enabled: _startedUp,
|
||||||
pad(const Text('Startup')),
|
onChanged: (v) {
|
||||||
pad(Switch(
|
setState(() {
|
||||||
value: _startedUp,
|
_errorText = null;
|
||||||
onChanged: (bool value) async {
|
});
|
||||||
await toggleStartup(value);
|
},
|
||||||
})),
|
onSubmitted: (String v) async {
|
||||||
pad(DropdownButton<LogLevel>(
|
try {
|
||||||
value: loggy.level.logLevel,
|
var res = await Veilid.instance.debug(v);
|
||||||
onChanged: (LogLevel? newLevel) {
|
loggy.info(res);
|
||||||
setState(() {
|
setState(() {
|
||||||
setRootLogLevel(newLevel);
|
_debugHistoryWrapper.submit(v);
|
||||||
});
|
});
|
||||||
},
|
} on VeilidAPIException catch (e) {
|
||||||
items: const [
|
setState(() {
|
||||||
DropdownMenuItem<LogLevel>(
|
_errorText = e.toDisplayError();
|
||||||
value: LogLevel.error, child: Text("Error")),
|
});
|
||||||
DropdownMenuItem<LogLevel>(
|
}
|
||||||
value: LogLevel.warning, child: Text("Warning")),
|
}),
|
||||||
DropdownMenuItem<LogLevel>(
|
))),
|
||||||
value: LogLevel.info, child: Text("Info")),
|
pad(
|
||||||
DropdownMenuItem<LogLevel>(
|
Column(children: [
|
||||||
value: LogLevel.debug, child: Text("Debug")),
|
const Text('Startup'),
|
||||||
DropdownMenuItem<LogLevel>(
|
Switch(
|
||||||
value: traceLevel, child: Text("Trace")),
|
value: _startedUp,
|
||||||
DropdownMenuItem<LogLevel>(
|
onChanged: (bool value) async {
|
||||||
value: LogLevel.all, child: Text("All")),
|
await toggleStartup(value);
|
||||||
])),
|
}),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
pad(Column(children: [
|
||||||
|
const Text('Log Level'),
|
||||||
|
DropdownButton<LogLevel>(
|
||||||
|
value: loggy.level.logLevel,
|
||||||
|
onChanged: (LogLevel? newLevel) {
|
||||||
|
setState(() {
|
||||||
|
setRootLogLevel(newLevel);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
items: const [
|
||||||
|
DropdownMenuItem<LogLevel>(
|
||||||
|
value: LogLevel.error, child: Text("Error")),
|
||||||
|
DropdownMenuItem<LogLevel>(
|
||||||
|
value: LogLevel.warning, child: Text("Warning")),
|
||||||
|
DropdownMenuItem<LogLevel>(
|
||||||
|
value: LogLevel.info, child: Text("Info")),
|
||||||
|
DropdownMenuItem<LogLevel>(
|
||||||
|
value: LogLevel.debug, child: Text("Debug")),
|
||||||
|
DropdownMenuItem<LogLevel>(
|
||||||
|
value: traceLevel, child: Text("Trace")),
|
||||||
|
DropdownMenuItem<LogLevel>(
|
||||||
|
value: LogLevel.all, child: Text("All")),
|
||||||
|
]),
|
||||||
|
])),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]));
|
]));
|
||||||
|
68
veilid-flutter/example/lib/history_wrapper.dart
Normal file
68
veilid-flutter/example/lib/history_wrapper.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
// TextField History Wrapper
|
||||||
|
class HistoryWrapper {
|
||||||
|
final List<String> _history = [];
|
||||||
|
int _historyPosition = 0;
|
||||||
|
final _historyTextEditingController = TextEditingController();
|
||||||
|
String _historyCurrentEdit = "";
|
||||||
|
|
||||||
|
TextEditingController get controller {
|
||||||
|
return _historyTextEditingController;
|
||||||
|
}
|
||||||
|
|
||||||
|
void submit(String v) {
|
||||||
|
// add to history
|
||||||
|
if (_history.isEmpty || _history.last != v) {
|
||||||
|
_history.add(v);
|
||||||
|
if (_history.length > 100) {
|
||||||
|
_history.removeAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_historyPosition = _history.length;
|
||||||
|
_historyTextEditingController.text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget wrap(
|
||||||
|
void Function(void Function())? stateSetter, TextField textField) {
|
||||||
|
void Function(void Function()) setState = stateSetter ?? (x) => x();
|
||||||
|
return KeyboardListener(
|
||||||
|
onKeyEvent: (KeyEvent event) {
|
||||||
|
setState(() {
|
||||||
|
if (event.runtimeType == KeyDownEvent &&
|
||||||
|
event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||||
|
if (_historyPosition > 0) {
|
||||||
|
if (_historyPosition == _history.length) {
|
||||||
|
_historyCurrentEdit = _historyTextEditingController.text;
|
||||||
|
}
|
||||||
|
_historyPosition -= 1;
|
||||||
|
_historyTextEditingController.text = _history[_historyPosition];
|
||||||
|
}
|
||||||
|
} else if (event.runtimeType == KeyDownEvent &&
|
||||||
|
event.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||||
|
if (_historyPosition < _history.length) {
|
||||||
|
_historyPosition += 1;
|
||||||
|
if (_historyPosition == _history.length) {
|
||||||
|
_historyTextEditingController.text = _historyCurrentEdit;
|
||||||
|
} else {
|
||||||
|
_historyTextEditingController.text = _history[_historyPosition];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (event.runtimeType == KeyDownEvent) {
|
||||||
|
_historyPosition = _history.length;
|
||||||
|
_historyCurrentEdit = _historyTextEditingController.text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
focusNode: FocusNode(onKey: (FocusNode node, RawKeyEvent event) {
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowDown ||
|
||||||
|
event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
return KeyEventResult.ignored;
|
||||||
|
}),
|
||||||
|
child: textField,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -257,29 +257,38 @@ Padding pad(Widget child) {
|
|||||||
/////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////
|
||||||
// Theme
|
// Theme
|
||||||
|
|
||||||
InputDecoration newInputDecoration(String labelText, bool enabled) {
|
InputDecoration newInputDecoration(
|
||||||
|
String labelText, String? errorText, bool enabled) {
|
||||||
return InputDecoration(
|
return InputDecoration(
|
||||||
labelText: labelText,
|
labelText: labelText,
|
||||||
fillColor: enabled
|
errorText: errorText,
|
||||||
? materialPrimaryColor.shade200
|
filled: !enabled,
|
||||||
: materialPrimaryColor.shade200.withOpacity(0.5));
|
fillColor: materialPrimaryColor.shade300.withOpacity(0.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
InputDecorationTheme newInputDecorationTheme() {
|
InputDecorationTheme newInputDecorationTheme() {
|
||||||
return InputDecorationTheme(
|
return InputDecorationTheme(
|
||||||
border: const OutlineInputBorder(),
|
border: OutlineInputBorder(
|
||||||
filled: true,
|
|
||||||
fillColor: materialPrimaryColor.shade200,
|
|
||||||
disabledBorder: const OutlineInputBorder(
|
|
||||||
borderSide:
|
borderSide:
|
||||||
BorderSide(color: Color.fromARGB(0, 0, 0, 0), width: 0.0)),
|
BorderSide(color: materialPrimaryColor.shade300, width: 1.0)),
|
||||||
|
disabledBorder: OutlineInputBorder(
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: materialPrimaryColor.shade600, width: 1.0)),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide:
|
borderSide:
|
||||||
BorderSide(color: materialPrimaryColor.shade900, width: 0.0)),
|
BorderSide(color: materialPrimaryColor.shade900, width: 1.0)),
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
errorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: materialPopColor.shade800, width: 1.0)),
|
||||||
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: materialPopColor.shade600, width: 1.0)),
|
||||||
|
errorStyle: TextStyle(
|
||||||
|
color: materialPopColor.shade600,
|
||||||
|
letterSpacing: 1.1,
|
||||||
|
),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.auto,
|
||||||
floatingLabelStyle: TextStyle(
|
floatingLabelStyle: TextStyle(
|
||||||
color: materialPrimaryColor.shade900,
|
color: materialPrimaryColor.shade900,
|
||||||
letterSpacing: 1.2,
|
letterSpacing: 1.1,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:html';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
@ -1571,6 +1572,8 @@ abstract class VeilidAPIException implements Exception {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String toDisplayError();
|
||||||
}
|
}
|
||||||
|
|
||||||
class VeilidAPIExceptionNotInitialized implements VeilidAPIException {
|
class VeilidAPIExceptionNotInitialized implements VeilidAPIException {
|
||||||
@ -1578,6 +1581,11 @@ class VeilidAPIExceptionNotInitialized implements VeilidAPIException {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return "VeilidAPIException: NotInitialized";
|
return "VeilidAPIException: NotInitialized";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Not initialized";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VeilidAPIExceptionAlreadyInitialized implements VeilidAPIException {
|
class VeilidAPIExceptionAlreadyInitialized implements VeilidAPIException {
|
||||||
@ -1585,6 +1593,11 @@ class VeilidAPIExceptionAlreadyInitialized implements VeilidAPIException {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return "VeilidAPIException: AlreadyInitialized";
|
return "VeilidAPIException: AlreadyInitialized";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Already initialized";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VeilidAPIExceptionTimeout implements VeilidAPIException {
|
class VeilidAPIExceptionTimeout implements VeilidAPIException {
|
||||||
@ -1592,6 +1605,11 @@ class VeilidAPIExceptionTimeout implements VeilidAPIException {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return "VeilidAPIException: Timeout";
|
return "VeilidAPIException: Timeout";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Timeout";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VeilidAPIExceptionShutdown implements VeilidAPIException {
|
class VeilidAPIExceptionShutdown implements VeilidAPIException {
|
||||||
@ -1599,6 +1617,11 @@ class VeilidAPIExceptionShutdown implements VeilidAPIException {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return "VeilidAPIException: Shutdown";
|
return "VeilidAPIException: Shutdown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Currently shut down";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VeilidAPIExceptionNodeNotFound implements VeilidAPIException {
|
class VeilidAPIExceptionNodeNotFound implements VeilidAPIException {
|
||||||
@ -1609,6 +1632,11 @@ class VeilidAPIExceptionNodeNotFound implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: NodeNotFound (nodeId: $nodeId)";
|
return "VeilidAPIException: NodeNotFound (nodeId: $nodeId)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Node node found: $nodeId";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionNodeNotFound(this.nodeId);
|
VeilidAPIExceptionNodeNotFound(this.nodeId);
|
||||||
}
|
}
|
||||||
@ -1621,6 +1649,11 @@ class VeilidAPIExceptionNoDialInfo implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: NoDialInfo (nodeId: $nodeId)";
|
return "VeilidAPIException: NoDialInfo (nodeId: $nodeId)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "No dial info: $nodeId";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionNoDialInfo(this.nodeId);
|
VeilidAPIExceptionNoDialInfo(this.nodeId);
|
||||||
}
|
}
|
||||||
@ -1633,6 +1666,11 @@ class VeilidAPIExceptionInternal implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: Internal ($message)";
|
return "VeilidAPIException: Internal ($message)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Internal error: $message";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionInternal(this.message);
|
VeilidAPIExceptionInternal(this.message);
|
||||||
}
|
}
|
||||||
@ -1645,6 +1683,11 @@ class VeilidAPIExceptionUnimplemented implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: Unimplemented ($message)";
|
return "VeilidAPIException: Unimplemented ($message)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Unimplemented: $message";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionUnimplemented(this.message);
|
VeilidAPIExceptionUnimplemented(this.message);
|
||||||
}
|
}
|
||||||
@ -1658,6 +1701,11 @@ class VeilidAPIExceptionParseError implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: ParseError ($message)\n value: $value";
|
return "VeilidAPIException: ParseError ($message)\n value: $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Parse error: $message";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionParseError(this.message, this.value);
|
VeilidAPIExceptionParseError(this.message, this.value);
|
||||||
}
|
}
|
||||||
@ -1672,6 +1720,11 @@ class VeilidAPIExceptionInvalidArgument implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: InvalidArgument ($context:$argument)\n value: $value";
|
return "VeilidAPIException: InvalidArgument ($context:$argument)\n value: $value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Invalid argument for $context: $argument";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionInvalidArgument(this.context, this.argument, this.value);
|
VeilidAPIExceptionInvalidArgument(this.context, this.argument, this.value);
|
||||||
}
|
}
|
||||||
@ -1685,6 +1738,11 @@ class VeilidAPIExceptionMissingArgument implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: MissingArgument ($context:$argument)";
|
return "VeilidAPIException: MissingArgument ($context:$argument)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return "Missing argument for $context: $argument";
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionMissingArgument(this.context, this.argument);
|
VeilidAPIExceptionMissingArgument(this.context, this.argument);
|
||||||
}
|
}
|
||||||
@ -1697,6 +1755,11 @@ class VeilidAPIExceptionGeneric implements VeilidAPIException {
|
|||||||
return "VeilidAPIException: Generic (message: $message)";
|
return "VeilidAPIException: Generic (message: $message)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toDisplayError() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
VeilidAPIExceptionGeneric(this.message);
|
VeilidAPIExceptionGeneric(this.message);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user