upgrade null-safe
This commit is contained in:
parent
f5f496f1cf
commit
b4ed72435c
123
lib/common.dart
123
lib/common.dart
@ -7,7 +7,7 @@ typedef F = String Function(String);
|
||||
typedef FMethod = String Function(String, dynamic);
|
||||
|
||||
class Translator {
|
||||
static F call;
|
||||
static late F call;
|
||||
}
|
||||
|
||||
class MyTheme {
|
||||
@ -32,8 +32,8 @@ final ButtonStyle flatButtonStyle = TextButton.styleFrom(
|
||||
),
|
||||
);
|
||||
|
||||
void Function() loadingCancelCallback;
|
||||
void showLoading(String text, BuildContext context) {
|
||||
void Function()? loadingCancelCallback;
|
||||
void showLoading(String text, BuildContext? context) {
|
||||
if (_hasDialog && context != null) {
|
||||
Navigator.pop(context);
|
||||
_hasDialog = false;
|
||||
@ -43,34 +43,34 @@ void showLoading(String text, BuildContext context) {
|
||||
EasyLoading.show(status: text, maskType: EasyLoadingMaskType.black);
|
||||
return;
|
||||
}
|
||||
EasyLoading.showWidget(
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: 300),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(child: CircularProgressIndicator()),
|
||||
SizedBox(height: 20),
|
||||
Center(
|
||||
child: Text(Translator.call(text),
|
||||
style: TextStyle(fontSize: 15))),
|
||||
SizedBox(height: 20),
|
||||
Center(
|
||||
child: TextButton(
|
||||
style: flatButtonStyle,
|
||||
onPressed: () {
|
||||
// with out loadingCancelCallback, we can see unexpected input password
|
||||
// dialog shown in home, no clue why, so use this as workaround
|
||||
// why no such issue on android?
|
||||
if (loadingCancelCallback != null)
|
||||
loadingCancelCallback();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(Translator.call('Cancel'),
|
||||
style: TextStyle(color: MyTheme.accent))))
|
||||
],
|
||||
)),
|
||||
maskType: EasyLoadingMaskType.black);
|
||||
// EasyLoading.showWidget(
|
||||
// Container(
|
||||
// constraints: BoxConstraints(maxWidth: 300),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Center(child: CircularProgressIndicator()),
|
||||
// SizedBox(height: 20),
|
||||
// Center(
|
||||
// child: Text(Translator.call(text),
|
||||
// style: TextStyle(fontSize: 15))),
|
||||
// SizedBox(height: 20),
|
||||
// Center(
|
||||
// child: TextButton(
|
||||
// style: flatButtonStyle,
|
||||
// onPressed: () {
|
||||
// // with out loadingCancelCallback, we can see unexpected input password
|
||||
// // dialog shown in home, no clue why, so use this as workaround
|
||||
// // why no such issue on android?
|
||||
// if (loadingCancelCallback != null)
|
||||
// loadingCancelCallback();
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// child: Text(Translator.call('Cancel'),
|
||||
// style: TextStyle(color: MyTheme.accent))))
|
||||
// ],
|
||||
// )),
|
||||
// maskType: EasyLoadingMaskType.black);
|
||||
}
|
||||
|
||||
void dismissLoading() {
|
||||
@ -82,8 +82,9 @@ bool _hasDialog = false;
|
||||
typedef BuildAlertDailog = Tuple3<Widget, Widget, List<Widget>> Function(
|
||||
void Function(void Function()));
|
||||
|
||||
Future<T> showAlertDialog<T>(BuildContext context, BuildAlertDailog build,
|
||||
[WillPopCallback onWillPop,
|
||||
// ??
|
||||
Future<T?> showAlertDialog<T>(BuildContext context, BuildAlertDailog build,
|
||||
[WillPopCallback? onWillPop,
|
||||
bool barrierDismissible = false,
|
||||
double contentPadding = 20]) async {
|
||||
dismissLoading();
|
||||
@ -112,7 +113,7 @@ Future<T> showAlertDialog<T>(BuildContext context, BuildAlertDailog build,
|
||||
}
|
||||
|
||||
void msgbox(String type, String title, String text, BuildContext context,
|
||||
[bool hasCancel]) {
|
||||
{bool? hasCancel}) {
|
||||
var wrap = (String text, void Function() onPressed) => ButtonTheme(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
@ -148,26 +149,44 @@ void msgbox(String type, String title, String text, BuildContext context,
|
||||
dismissLoading();
|
||||
}));
|
||||
}
|
||||
EasyLoading.showWidget(
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: 300),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(Translator.call(title), style: TextStyle(fontSize: 21)),
|
||||
SizedBox(height: 20),
|
||||
Text(Translator.call(text), style: TextStyle(fontSize: 15)),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
children: buttons,
|
||||
)
|
||||
],
|
||||
)),
|
||||
maskType: EasyLoadingMaskType.black);
|
||||
EasyLoading.show(
|
||||
status: "",
|
||||
maskType: EasyLoadingMaskType.black,
|
||||
indicator: Container(
|
||||
constraints: BoxConstraints(maxWidth: 300),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(Translator.call(title), style: TextStyle(fontSize: 21)),
|
||||
SizedBox(height: 20),
|
||||
Text(Translator.call(text), style: TextStyle(fontSize: 15)),
|
||||
SizedBox(height: 20),
|
||||
Row(
|
||||
children: buttons,
|
||||
)
|
||||
],
|
||||
))
|
||||
);
|
||||
// EasyLoading.showWidget(
|
||||
// Container(
|
||||
// constraints: BoxConstraints(maxWidth: 300),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(Translator.call(title), style: TextStyle(fontSize: 21)),
|
||||
// SizedBox(height: 20),
|
||||
// Text(Translator.call(text), style: TextStyle(fontSize: 15)),
|
||||
// SizedBox(height: 20),
|
||||
// Row(
|
||||
// children: buttons,
|
||||
// )
|
||||
// ],
|
||||
// )),
|
||||
// maskType: EasyLoadingMaskType.black);
|
||||
}
|
||||
|
||||
class PasswordWidget extends StatefulWidget {
|
||||
PasswordWidget({Key key, this.controller}) : super(key: key);
|
||||
PasswordWidget({Key? key, required this.controller}) : super(key: key);
|
||||
|
||||
final TextEditingController controller;
|
||||
|
||||
@ -221,4 +240,4 @@ bool isAndroid = false;
|
||||
bool isIOS = false;
|
||||
bool isWeb = false;
|
||||
bool isDesktop = false;
|
||||
BuildContext nowCtx;
|
||||
BuildContext? currentCtx;
|
||||
|
@ -14,8 +14,8 @@ const kScaleSlop = kPrecisePointerPanSlop / 10;
|
||||
|
||||
class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
CustomTouchGestureRecognizer({
|
||||
Object debugOwner,
|
||||
Set<PointerDeviceKind> supportedDevices,
|
||||
Object? debugOwner,
|
||||
Set<PointerDeviceKind>? supportedDevices,
|
||||
}) : super(
|
||||
debugOwner: debugOwner,
|
||||
supportedDevices: supportedDevices,
|
||||
@ -24,24 +24,24 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
}
|
||||
|
||||
// oneFingerPan
|
||||
GestureDragStartCallback onOneFingerPanStart;
|
||||
GestureDragUpdateCallback onOneFingerPanUpdate;
|
||||
GestureDragEndCallback onOneFingerPanEnd;
|
||||
GestureDragStartCallback? onOneFingerPanStart;
|
||||
GestureDragUpdateCallback? onOneFingerPanUpdate;
|
||||
GestureDragEndCallback? onOneFingerPanEnd;
|
||||
|
||||
// twoFingerScale
|
||||
GestureScaleStartCallback onTwoFingerScaleStart;
|
||||
GestureScaleUpdateCallback onTwoFingerScaleUpdate;
|
||||
GestureScaleEndCallback onTwoFingerScaleEnd;
|
||||
GestureScaleStartCallback? onTwoFingerScaleStart;
|
||||
GestureScaleUpdateCallback? onTwoFingerScaleUpdate;
|
||||
GestureScaleEndCallback? onTwoFingerScaleEnd;
|
||||
|
||||
// twoFingerVerticalDrag
|
||||
GestureDragStartCallback onTwoFingerVerticalDragStart;
|
||||
GestureDragUpdateCallback onTwoFingerVerticalDragUpdate;
|
||||
GestureDragEndCallback onTwoFingerVerticalDragEnd;
|
||||
GestureDragStartCallback? onTwoFingerVerticalDragStart;
|
||||
GestureDragUpdateCallback? onTwoFingerVerticalDragUpdate;
|
||||
GestureDragEndCallback? onTwoFingerVerticalDragEnd;
|
||||
|
||||
// twoFingerHorizontalDrag
|
||||
GestureDragStartCallback onTwoFingerHorizontalDragStart;
|
||||
GestureDragUpdateCallback onTwoFingerHorizontalDragUpdate;
|
||||
GestureDragEndCallback onTwoFingerHorizontalDragEnd;
|
||||
GestureDragStartCallback? onTwoFingerHorizontalDragStart;
|
||||
GestureDragUpdateCallback? onTwoFingerHorizontalDragUpdate;
|
||||
GestureDragEndCallback? onTwoFingerHorizontalDragEnd;
|
||||
|
||||
void _init() {
|
||||
debugPrint("CustomTouchGestureRecognizer init");
|
||||
@ -66,22 +66,22 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
switch (_currentState) {
|
||||
case CustomTouchGestureState.oneFingerPan:
|
||||
if (onOneFingerPanUpdate != null) {
|
||||
onOneFingerPanUpdate(_getDragUpdateDetails(d));
|
||||
onOneFingerPanUpdate!(_getDragUpdateDetails(d));
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerScale:
|
||||
if (onTwoFingerScaleUpdate != null) {
|
||||
onTwoFingerScaleUpdate(d);
|
||||
onTwoFingerScaleUpdate!(d);
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerHorizontalDrag:
|
||||
if (onTwoFingerHorizontalDragUpdate != null) {
|
||||
onTwoFingerHorizontalDragUpdate(_getDragUpdateDetails(d));
|
||||
onTwoFingerHorizontalDragUpdate!(_getDragUpdateDetails(d));
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerVerticalDrag:
|
||||
if (onTwoFingerVerticalDragUpdate != null) {
|
||||
onTwoFingerVerticalDragUpdate(_getDragUpdateDetails(d));
|
||||
onTwoFingerVerticalDragUpdate!(_getDragUpdateDetails(d));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -97,25 +97,25 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
case CustomTouchGestureState.oneFingerPan:
|
||||
debugPrint("TwoFingerState.pan onEnd");
|
||||
if (onOneFingerPanEnd != null) {
|
||||
onOneFingerPanEnd(_getDragEndDetails(d));
|
||||
onOneFingerPanEnd!(_getDragEndDetails(d));
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerScale:
|
||||
debugPrint("TwoFingerState.scale onEnd");
|
||||
if (onTwoFingerScaleEnd != null) {
|
||||
onTwoFingerScaleEnd(d);
|
||||
onTwoFingerScaleEnd!(d);
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerHorizontalDrag:
|
||||
debugPrint("TwoFingerState.horizontal onEnd");
|
||||
if (onTwoFingerHorizontalDragEnd != null) {
|
||||
onTwoFingerHorizontalDragEnd(_getDragEndDetails(d));
|
||||
onTwoFingerHorizontalDragEnd!(_getDragEndDetails(d));
|
||||
}
|
||||
break;
|
||||
case CustomTouchGestureState.twoFingerVerticalDrag:
|
||||
debugPrint("TwoFingerState.vertical onEnd");
|
||||
if (onTwoFingerVerticalDragEnd != null) {
|
||||
onTwoFingerVerticalDragEnd(_getDragEndDetails(d));
|
||||
onTwoFingerVerticalDragEnd!(_getDragEndDetails(d));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -129,7 +129,7 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
var _currentState = CustomTouchGestureState.none;
|
||||
var _isWatch = false;
|
||||
|
||||
Timer _timer;
|
||||
Timer? _timer;
|
||||
double _sumScale = 0;
|
||||
double _sumVertical = 0;
|
||||
double _sumHorizontal = 0;
|
||||
@ -143,7 +143,7 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
void _reset() {
|
||||
_isWatch = false;
|
||||
_clearSum();
|
||||
if (_timer != null) _timer.cancel();
|
||||
if (_timer != null) _timer!.cancel();
|
||||
}
|
||||
|
||||
void _updateCompute(ScaleUpdateDetails d) {
|
||||
@ -155,14 +155,14 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
debugPrint("start Scale");
|
||||
_currentState = CustomTouchGestureState.twoFingerScale;
|
||||
if (onOneFingerPanStart != null) {
|
||||
onOneFingerPanStart(_getDragStartDetails(d));
|
||||
onOneFingerPanStart!(_getDragStartDetails(d));
|
||||
}
|
||||
_reset();
|
||||
} else if (_sumHorizontal.abs() > kPrecisePointerPanSlop) {
|
||||
debugPrint("start Horizontal");
|
||||
_currentState = CustomTouchGestureState.twoFingerHorizontalDrag;
|
||||
if (onTwoFingerHorizontalDragUpdate != null) {
|
||||
onTwoFingerHorizontalDragUpdate(_getDragUpdateDetails(d));
|
||||
onTwoFingerHorizontalDragUpdate!(_getDragUpdateDetails(d));
|
||||
}
|
||||
_reset();
|
||||
} else if (_sumVertical.abs() > kPrecisePointerPanSlop) {
|
||||
@ -179,7 +179,7 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
debugPrint("startWatchTimer");
|
||||
_isWatch = true;
|
||||
_clearSum();
|
||||
if (_timer != null) _timer.cancel();
|
||||
if (_timer != null) _timer!.cancel();
|
||||
_timer = Timer(const Duration(milliseconds: 200), _reset);
|
||||
}
|
||||
|
||||
@ -201,24 +201,24 @@ class CustomTouchGestureRecognizer extends ScaleGestureRecognizer {
|
||||
|
||||
class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
HoldTapMoveGestureRecognizer({
|
||||
Object debugOwner,
|
||||
Set<PointerDeviceKind> supportedDevices,
|
||||
Object? debugOwner,
|
||||
Set<PointerDeviceKind>? supportedDevices,
|
||||
}) : super(
|
||||
debugOwner: debugOwner,
|
||||
supportedDevices: supportedDevices,
|
||||
);
|
||||
|
||||
GestureDragStartCallback onHoldDragStart;
|
||||
GestureDragUpdateCallback onHoldDragUpdate;
|
||||
GestureDragDownCallback onHoldDragDown;
|
||||
GestureDragCancelCallback onHoldDragCancel;
|
||||
GestureDragStartCallback? onHoldDragStart;
|
||||
GestureDragUpdateCallback? onHoldDragUpdate;
|
||||
GestureDragDownCallback? onHoldDragDown;
|
||||
GestureDragCancelCallback? onHoldDragCancel;
|
||||
|
||||
bool _isStart = false;
|
||||
|
||||
Timer _firstTapUpTimer; // 第一次点击后的计时 超时未等到第二次操作则reject
|
||||
Timer _secondTapDownTimer; // 第二次点击后的计时 期间内有其他的操作则reject 超时则判定成功 drag update
|
||||
_TapTracker _firstTap;
|
||||
_TapTracker _secondTap;
|
||||
Timer? _firstTapUpTimer; // 第一次点击后的计时 超时未等到第二次操作则reject
|
||||
Timer? _secondTapDownTimer; // 第二次点击后的计时 期间内有其他的操作则reject 超时则判定成功 drag update
|
||||
_TapTracker? _firstTap;
|
||||
_TapTracker? _secondTap;
|
||||
|
||||
final Map<int, _TapTracker> _trackers = <int, _TapTracker>{};
|
||||
|
||||
@ -244,11 +244,11 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
void addAllowedPointer(PointerDownEvent event) {
|
||||
// 检测按下事件
|
||||
if (_firstTap != null) {
|
||||
if (!_firstTap.isWithinGlobalTolerance(event, kDoubleTapSlop)) {
|
||||
if (!_firstTap!.isWithinGlobalTolerance(event, kDoubleTapSlop)) {
|
||||
// Ignore out-of-bounds second taps.
|
||||
return;
|
||||
} else if (!_firstTap.hasElapsedMinTime() ||
|
||||
!_firstTap.hasSameButton(event)) {
|
||||
} else if (!_firstTap!.hasElapsedMinTime() ||
|
||||
!_firstTap!.hasSameButton(event)) {
|
||||
// Restart when the second tap is too close to the first (touch screens
|
||||
// often detect touches intermittently), or when buttons mismatch.
|
||||
_reset();
|
||||
@ -256,7 +256,7 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
} else if (onHoldDragDown != null) {
|
||||
invokeCallback<void>(
|
||||
'onHoldDragDown',
|
||||
() => onHoldDragDown(DragDownDetails(
|
||||
() => onHoldDragDown!(DragDownDetails(
|
||||
globalPosition: event.position,
|
||||
localPosition: event.localPosition)));
|
||||
}
|
||||
@ -269,7 +269,7 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
_stopSecondTapDownTimer();
|
||||
final _TapTracker tracker = _TapTracker(
|
||||
event: event,
|
||||
entry: GestureBinding.instance.gestureArena.add(event.pointer, this),
|
||||
entry: GestureBinding.instance!.gestureArena.add(event.pointer, this),
|
||||
doubleTapMinTime: kDoubleTapMinTime,
|
||||
gestureSettings: gestureSettings,
|
||||
);
|
||||
@ -279,7 +279,7 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
// 实际的逻辑应该是第二次down后一段时间没有抬起则表示start 刚好是双击取反
|
||||
void _handleEvent(PointerEvent event) {
|
||||
final _TapTracker tracker = _trackers[event.pointer];
|
||||
final _TapTracker tracker = _trackers[event.pointer]!;
|
||||
if (event is PointerUpEvent) {
|
||||
if (_firstTap == null && _secondTap == null) {
|
||||
_registerFirstTap(tracker);
|
||||
@ -294,17 +294,17 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
} else if (event is PointerMoveEvent) {
|
||||
// 检测到first tap move 则取消,检测到second tap move且已经通过竞技场则update
|
||||
if (!tracker.isWithinGlobalTolerance(event, kDoubleTapTouchSlop)) {
|
||||
if (_firstTap != null && _firstTap.pointer == event.pointer) {
|
||||
if (_firstTap != null && _firstTap!.pointer == event.pointer) {
|
||||
// first tap move
|
||||
_reject(tracker);
|
||||
} else if (_secondTap != null && _secondTap.pointer == event.pointer) {
|
||||
} else if (_secondTap != null && _secondTap!.pointer == event.pointer) {
|
||||
// debugPrint("_secondTap move");
|
||||
// second tap move
|
||||
if (!_isStart) {
|
||||
_resolve();
|
||||
}
|
||||
if (onHoldDragUpdate != null)
|
||||
onHoldDragUpdate(DragUpdateDetails(
|
||||
onHoldDragUpdate!(DragUpdateDetails(
|
||||
globalPosition: event.position,
|
||||
localPosition: event.localPosition,
|
||||
delta: event.delta));
|
||||
@ -320,9 +320,9 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
@override
|
||||
void rejectGesture(int pointer) {
|
||||
_TapTracker tracker = _trackers[pointer];
|
||||
_TapTracker? tracker = _trackers[pointer];
|
||||
// If tracker isn't in the list, check if this is the first tap tracker
|
||||
if (tracker == null && _firstTap != null && _firstTap.pointer == pointer) {
|
||||
if (tracker == null && _firstTap != null && _firstTap!.pointer == pointer) {
|
||||
tracker = _firstTap;
|
||||
}
|
||||
// If tracker is still null, we rejected ourselves already
|
||||
@ -333,11 +333,11 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
void _resolve() {
|
||||
_stopSecondTapDownTimer();
|
||||
_firstTap?.entry?.resolve(GestureDisposition.accepted);
|
||||
_secondTap?.entry?.resolve(GestureDisposition.accepted);
|
||||
_firstTap?.entry.resolve(GestureDisposition.accepted);
|
||||
_secondTap?.entry.resolve(GestureDisposition.accepted);
|
||||
_isStart = true;
|
||||
// TODO start details
|
||||
if (onHoldDragStart != null) onHoldDragStart(DragStartDetails());
|
||||
if (onHoldDragStart != null) onHoldDragStart!(DragStartDetails());
|
||||
}
|
||||
|
||||
void _reject(_TapTracker tracker) {
|
||||
@ -367,16 +367,16 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
}
|
||||
// Note, order is important below in order for the resolve -> reject logic
|
||||
// to work properly.
|
||||
final _TapTracker tracker = _firstTap;
|
||||
final _TapTracker tracker = _firstTap!;
|
||||
_firstTap = null;
|
||||
_reject(tracker);
|
||||
GestureBinding.instance.gestureArena.release(tracker.pointer);
|
||||
GestureBinding.instance!.gestureArena.release(tracker.pointer);
|
||||
|
||||
if (_secondTap != null) {
|
||||
final _TapTracker tracker = _secondTap;
|
||||
final _TapTracker tracker = _secondTap!;
|
||||
_secondTap = null;
|
||||
_reject(tracker);
|
||||
GestureBinding.instance.gestureArena.release(tracker.pointer);
|
||||
GestureBinding.instance!.gestureArena.release(tracker.pointer);
|
||||
}
|
||||
}
|
||||
// TODO 正确的释放资源
|
||||
@ -387,7 +387,7 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
void _registerFirstTap(_TapTracker tracker) {
|
||||
_startFirstTapUpTimer();
|
||||
GestureBinding.instance.gestureArena.hold(tracker.pointer);
|
||||
GestureBinding.instance!.gestureArena.hold(tracker.pointer);
|
||||
// Note, order is important below in order for the clear -> reject logic to
|
||||
// work properly.
|
||||
_freezeTracker(tracker);
|
||||
@ -399,12 +399,12 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
// 清除first tap的状态
|
||||
if (_firstTap != null) {
|
||||
_stopFirstTapUpTimer();
|
||||
_freezeTracker(_firstTap);
|
||||
_freezeTracker(_firstTap!);
|
||||
_firstTap = null;
|
||||
}
|
||||
|
||||
_startSecondTapDownTimer();
|
||||
GestureBinding.instance.gestureArena.hold(tracker.pointer);
|
||||
GestureBinding.instance!.gestureArena.hold(tracker.pointer);
|
||||
|
||||
_secondTap = tracker;
|
||||
|
||||
@ -430,21 +430,21 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
void _stopFirstTapUpTimer() {
|
||||
if (_firstTapUpTimer != null) {
|
||||
_firstTapUpTimer.cancel();
|
||||
_firstTapUpTimer!.cancel();
|
||||
_firstTapUpTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
void _stopSecondTapDownTimer() {
|
||||
if (_secondTapDownTimer != null) {
|
||||
_secondTapDownTimer.cancel();
|
||||
_secondTapDownTimer!.cancel();
|
||||
_secondTapDownTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
void _checkCancel() {
|
||||
if (onHoldDragCancel != null) {
|
||||
invokeCallback<void>('onHoldDragCancel', onHoldDragCancel);
|
||||
invokeCallback<void>('onHoldDragCancel', onHoldDragCancel!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,19 +454,19 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
DoubleFinerTapGestureRecognizer({
|
||||
Object debugOwner,
|
||||
Set<PointerDeviceKind> supportedDevices,
|
||||
Object? debugOwner,
|
||||
Set<PointerDeviceKind>? supportedDevices,
|
||||
}) : super(
|
||||
debugOwner: debugOwner,
|
||||
supportedDevices: supportedDevices,
|
||||
);
|
||||
|
||||
GestureTapDownCallback onDoubleFinerTapDown;
|
||||
GestureTapDownCallback onDoubleFinerTap;
|
||||
GestureTapCancelCallback onDoubleFinerTapCancel;
|
||||
GestureTapDownCallback? onDoubleFinerTapDown;
|
||||
GestureTapDownCallback? onDoubleFinerTap;
|
||||
GestureTapCancelCallback? onDoubleFinerTapCancel;
|
||||
|
||||
Timer _firstTapTimer; // 第一次点击后的计时 超时未等到第二次操作则reject
|
||||
_TapTracker _firstTap;
|
||||
Timer? _firstTapTimer; // 第一次点击后的计时 超时未等到第二次操作则reject
|
||||
_TapTracker? _firstTap;
|
||||
|
||||
var _isStart = false;
|
||||
|
||||
@ -505,7 +505,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
kind: getKindForPointer(event.pointer),
|
||||
);
|
||||
invokeCallback<void>(
|
||||
'onDoubleFinerTapDown', () => onDoubleFinerTapDown(details));
|
||||
'onDoubleFinerTapDown', () => onDoubleFinerTapDown!(details));
|
||||
}
|
||||
} else {
|
||||
// first tap
|
||||
@ -518,7 +518,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
void _trackTap(PointerDownEvent event) {
|
||||
final _TapTracker tracker = _TapTracker(
|
||||
event: event,
|
||||
entry: GestureBinding.instance.gestureArena.add(event.pointer, this),
|
||||
entry: GestureBinding.instance!.gestureArena.add(event.pointer, this),
|
||||
doubleTapMinTime: kDoubleTapMinTime,
|
||||
gestureSettings: gestureSettings,
|
||||
);
|
||||
@ -531,7 +531,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
// 实际的逻辑应该是第二次down后一段时间没有抬起则表示start 刚好是双击取反
|
||||
void _handleEvent(PointerEvent event) {
|
||||
final _TapTracker tracker = _trackers[event.pointer];
|
||||
final _TapTracker tracker = _trackers[event.pointer]!;
|
||||
if (event is PointerUpEvent) {
|
||||
debugPrint("PointerUpEvent");
|
||||
_upTap.add(tracker.pointer);
|
||||
@ -548,9 +548,9 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
@override
|
||||
void rejectGesture(int pointer) {
|
||||
_TapTracker tracker = _trackers[pointer];
|
||||
_TapTracker? tracker = _trackers[pointer];
|
||||
// If tracker isn't in the list, check if this is the first tap tracker
|
||||
if (tracker == null && _firstTap != null && _firstTap.pointer == pointer) {
|
||||
if (tracker == null && _firstTap != null && _firstTap!.pointer == pointer) {
|
||||
tracker = _firstTap;
|
||||
}
|
||||
// If tracker is still null, we rejected ourselves already
|
||||
@ -589,7 +589,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
}
|
||||
|
||||
void _registerTap(_TapTracker tracker) {
|
||||
GestureBinding.instance.gestureArena.hold(tracker.pointer);
|
||||
GestureBinding.instance!.gestureArena.hold(tracker.pointer);
|
||||
// Note, order is important below in order for the clear -> reject logic to
|
||||
// work properly.
|
||||
}
|
||||
@ -609,7 +609,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
void _stopFirstTapUpTimer() {
|
||||
if (_firstTapTimer != null) {
|
||||
_firstTapTimer.cancel();
|
||||
_firstTapTimer!.cancel();
|
||||
_firstTapTimer = null;
|
||||
}
|
||||
}
|
||||
@ -626,7 +626,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
void _resolve() {
|
||||
// TODO tap down details
|
||||
if (onDoubleFinerTap != null) onDoubleFinerTap(TapDownDetails());
|
||||
if (onDoubleFinerTap != null) onDoubleFinerTap!(TapDownDetails());
|
||||
_trackers.forEach((key, value) {
|
||||
value.entry.resolve(GestureDisposition.accepted);
|
||||
});
|
||||
@ -635,7 +635,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
|
||||
void _checkCancel() {
|
||||
if (onDoubleFinerTapCancel != null) {
|
||||
invokeCallback<void>('onHoldDragCancel', onDoubleFinerTapCancel);
|
||||
invokeCallback<void>('onHoldDragCancel', onDoubleFinerTapCancel!);
|
||||
}
|
||||
}
|
||||
|
||||
@ -647,10 +647,10 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
|
||||
/// larger gesture.
|
||||
class _TapTracker {
|
||||
_TapTracker({
|
||||
PointerDownEvent event,
|
||||
this.entry,
|
||||
Duration doubleTapMinTime,
|
||||
this.gestureSettings,
|
||||
required PointerDownEvent event,
|
||||
required this.entry,
|
||||
required Duration doubleTapMinTime,
|
||||
required this.gestureSettings,
|
||||
}) : assert(doubleTapMinTime != null),
|
||||
assert(event != null),
|
||||
assert(event.buttons != null),
|
||||
@ -660,7 +660,7 @@ class _TapTracker {
|
||||
_doubleTapMinTimeCountdown =
|
||||
_CountdownZoned(duration: doubleTapMinTime);
|
||||
|
||||
final DeviceGestureSettings gestureSettings;
|
||||
final DeviceGestureSettings? gestureSettings;
|
||||
final int pointer;
|
||||
final GestureArenaEntry entry;
|
||||
final Offset _initialGlobalPosition;
|
||||
@ -669,17 +669,17 @@ class _TapTracker {
|
||||
|
||||
bool _isTrackingPointer = false;
|
||||
|
||||
void startTrackingPointer(PointerRoute route, Matrix4 transform) {
|
||||
void startTrackingPointer(PointerRoute route, Matrix4? transform) {
|
||||
if (!_isTrackingPointer) {
|
||||
_isTrackingPointer = true;
|
||||
GestureBinding.instance.pointerRouter.addRoute(pointer, route, transform);
|
||||
GestureBinding.instance!.pointerRouter.addRoute(pointer, route, transform);
|
||||
}
|
||||
}
|
||||
|
||||
void stopTrackingPointer(PointerRoute route) {
|
||||
if (_isTrackingPointer) {
|
||||
_isTrackingPointer = false;
|
||||
GestureBinding.instance.pointerRouter.removeRoute(pointer, route);
|
||||
GestureBinding.instance!.pointerRouter.removeRoute(pointer, route);
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,7 +700,7 @@ class _TapTracker {
|
||||
/// CountdownZoned tracks whether the specified duration has elapsed since
|
||||
/// creation, honoring [Zone].
|
||||
class _CountdownZoned {
|
||||
_CountdownZoned({Duration duration}) : assert(duration != null) {
|
||||
_CountdownZoned({required Duration duration}) : assert(duration != null) {
|
||||
Timer(duration, _onTimeout);
|
||||
}
|
||||
|
||||
@ -714,18 +714,19 @@ class _CountdownZoned {
|
||||
}
|
||||
|
||||
RawGestureDetector getMixinGestureDetector({
|
||||
Widget child,
|
||||
GestureTapUpCallback onTapUp,
|
||||
GestureDoubleTapCallback onDoubleTap,
|
||||
GestureDragStartCallback onHoldDragStart,
|
||||
GestureDragUpdateCallback onHoldDragUpdate,
|
||||
GestureDragCancelCallback onHoldDragCancel,
|
||||
GestureTapDownCallback onDoubleFinerTap,
|
||||
GestureDragStartCallback onOneFingerPanStart,
|
||||
GestureDragUpdateCallback onOneFingerPanUpdate,
|
||||
GestureScaleUpdateCallback onTwoFingerScaleUpdate,
|
||||
GestureDragUpdateCallback onTwoFingerHorizontalDragUpdate,
|
||||
GestureDragUpdateCallback onTwoFingerVerticalDragUpdate,
|
||||
Widget? child,
|
||||
GestureTapUpCallback? onTapUp,
|
||||
GestureDoubleTapCallback? onDoubleTap,
|
||||
GestureDragStartCallback? onHoldDragStart,
|
||||
GestureDragUpdateCallback? onHoldDragUpdate,
|
||||
GestureDragCancelCallback? onHoldDragCancel,
|
||||
GestureTapDownCallback? onDoubleFinerTap,
|
||||
GestureDragStartCallback? onOneFingerPanStart,
|
||||
GestureDragUpdateCallback? onOneFingerPanUpdate,
|
||||
GestureScaleUpdateCallback? onTwoFingerScaleUpdate,
|
||||
GestureScaleEndCallback? onTwoFingerScaleEnd,
|
||||
GestureDragUpdateCallback? onTwoFingerHorizontalDragUpdate,
|
||||
GestureDragUpdateCallback? onTwoFingerVerticalDragUpdate,
|
||||
}) {
|
||||
return RawGestureDetector(
|
||||
child: child,
|
||||
@ -763,6 +764,7 @@ RawGestureDetector getMixinGestureDetector({
|
||||
..onOneFingerPanStart = onOneFingerPanStart
|
||||
..onOneFingerPanUpdate = onOneFingerPanUpdate
|
||||
..onTwoFingerScaleUpdate = onTwoFingerScaleUpdate
|
||||
..onTwoFingerScaleEnd = onTwoFingerScaleEnd
|
||||
..onTwoFingerHorizontalDragUpdate = onTwoFingerHorizontalDragUpdate
|
||||
..onTwoFingerVerticalDragUpdate = onTwoFingerVerticalDragUpdate;
|
||||
})
|
||||
|
@ -8,7 +8,7 @@ import 'model.dart';
|
||||
import 'remote_page.dart';
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
HomePage({Key key, this.title}) : super(key: key);
|
||||
HomePage({Key? key, required this.title}) : super(key: key);
|
||||
|
||||
final String title;
|
||||
|
||||
@ -55,18 +55,20 @@ class _HomePageState extends State<HomePage> {
|
||||
},
|
||||
onTap: () {
|
||||
() async {
|
||||
var value = await showMenu(
|
||||
var value = await showMenu<dynamic>(
|
||||
context: context,
|
||||
position: this._menuPos,
|
||||
items: [
|
||||
PopupMenuItem<String>(
|
||||
child: Text(translate('ID Server')),
|
||||
value: 'id_server'),
|
||||
// TODO test
|
||||
isAndroid
|
||||
? PopupMenuItem<String>(
|
||||
? PopupMenuItem<dynamic>(
|
||||
child: Text(translate('Share My Screen')),
|
||||
value: 'server')
|
||||
: null,
|
||||
: PopupMenuItem<dynamic>(
|
||||
child: SizedBox.shrink(), value: ''),
|
||||
PopupMenuItem<String>(
|
||||
child: Text(translate('About') + ' RustDesk'),
|
||||
value: 'about'),
|
||||
@ -328,8 +330,8 @@ void showServer(BuildContext context) {
|
||||
labelText: translate('ID Server'),
|
||||
),
|
||||
validator: validate,
|
||||
onSaved: (String value) {
|
||||
id = value.trim();
|
||||
onSaved: (String? value) {
|
||||
if (value != null) id = value.trim();
|
||||
},
|
||||
),
|
||||
/*
|
||||
@ -350,8 +352,8 @@ void showServer(BuildContext context) {
|
||||
labelText: 'Key',
|
||||
),
|
||||
validator: null,
|
||||
onSaved: (String value) {
|
||||
key = value.trim();
|
||||
onSaved: (String? value) {
|
||||
if (value != null) key = value.trim();
|
||||
},
|
||||
),
|
||||
])),
|
||||
@ -366,8 +368,8 @@ void showServer(BuildContext context) {
|
||||
TextButton(
|
||||
style: flatButtonStyle,
|
||||
onPressed: () {
|
||||
if (formKey.currentState.validate()) {
|
||||
formKey.currentState.save();
|
||||
if (formKey.currentState != null && formKey.currentState!.validate()) {
|
||||
formKey.currentState!.save();
|
||||
if (id != id0)
|
||||
FFI.setByName('option',
|
||||
'{"name": "custom-rendezvous-server", "value": "$id"}');
|
||||
@ -391,7 +393,7 @@ Future<Null> showAbout(BuildContext context) async {
|
||||
showAlertDialog(
|
||||
context,
|
||||
(setState) => Tuple3(
|
||||
null,
|
||||
SizedBox.shrink(), // TODO test old:null
|
||||
Wrap(direction: Axis.vertical, spacing: 12, children: [
|
||||
Text('Version: $version'),
|
||||
InkWell(
|
||||
@ -409,12 +411,12 @@ Future<Null> showAbout(BuildContext context) async {
|
||||
)),
|
||||
)),
|
||||
]),
|
||||
null),
|
||||
[]),
|
||||
() async => true,
|
||||
true);
|
||||
}
|
||||
|
||||
String validate(value) {
|
||||
String? validate(value) {
|
||||
value = value.trim();
|
||||
if (value.isEmpty) {
|
||||
return null;
|
||||
|
103
lib/model.dart
103
lib/model.dart
@ -11,15 +11,15 @@ import 'common.dart';
|
||||
import 'native_model.dart' if (dart.library.html) 'web_model.dart';
|
||||
|
||||
class FfiModel with ChangeNotifier {
|
||||
PeerInfo _pi;
|
||||
Display _display;
|
||||
PeerInfo _pi = PeerInfo();
|
||||
Display _display = Display();
|
||||
var _decoding = false;
|
||||
bool _waitForImage;
|
||||
bool _waitForImage = false;
|
||||
bool _initialized = false;
|
||||
var _inputBlocked = false;
|
||||
final _permissions = Map<String, bool>();
|
||||
bool _secure;
|
||||
bool _direct;
|
||||
bool? _secure;
|
||||
bool? _direct;
|
||||
|
||||
get permissions => _permissions;
|
||||
|
||||
@ -32,6 +32,7 @@ class FfiModel with ChangeNotifier {
|
||||
get direct => _direct;
|
||||
|
||||
get pi => _pi;
|
||||
|
||||
get inputBlocked => _inputBlocked;
|
||||
|
||||
set inputBlocked(v) {
|
||||
@ -75,8 +76,8 @@ class FfiModel with ChangeNotifier {
|
||||
_direct = direct;
|
||||
}
|
||||
|
||||
Image getConnectionImage() {
|
||||
String icon;
|
||||
Image? getConnectionImage() {
|
||||
String? icon;
|
||||
if (secure == true && direct == true) {
|
||||
icon = 'secure';
|
||||
} else if (secure == false && direct == true) {
|
||||
@ -200,11 +201,11 @@ class FfiModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
class ImageModel with ChangeNotifier {
|
||||
ui.Image _image;
|
||||
ui.Image? _image;
|
||||
|
||||
ui.Image get image => _image;
|
||||
ui.Image? get image => _image;
|
||||
|
||||
void update(ui.Image image) {
|
||||
void update(ui.Image? image) {
|
||||
if (_image == null && image != null) {
|
||||
if (isDesktop) {
|
||||
FFI.canvasModel.updateViewStyle();
|
||||
@ -223,28 +224,26 @@ class ImageModel with ChangeNotifier {
|
||||
double get maxScale {
|
||||
if (_image == null) return 1.0;
|
||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||
final xscale = size.width / _image.width;
|
||||
final yscale = size.height / _image.height;
|
||||
final xscale = size.width / _image!.width;
|
||||
final yscale = size.height / _image!.height;
|
||||
return max(1.0, max(xscale, yscale));
|
||||
}
|
||||
|
||||
double get minScale {
|
||||
if (_image == null) return 1.0;
|
||||
final size = MediaQueryData.fromWindow(ui.window).size;
|
||||
final xscale = size.width / _image.width;
|
||||
final yscale = size.height / _image.height;
|
||||
final xscale = size.width / _image!.width;
|
||||
final yscale = size.height / _image!.height;
|
||||
return min(xscale, yscale);
|
||||
}
|
||||
}
|
||||
|
||||
class CanvasModel with ChangeNotifier {
|
||||
double _x;
|
||||
double _y;
|
||||
double _scale;
|
||||
double _x = 0;
|
||||
double _y = 0;
|
||||
double _scale = 1.0;
|
||||
|
||||
CanvasModel() {
|
||||
clear();
|
||||
}
|
||||
CanvasModel();
|
||||
|
||||
double get x => _x;
|
||||
|
||||
@ -355,7 +354,7 @@ class CanvasModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
class CursorModel with ChangeNotifier {
|
||||
ui.Image _image;
|
||||
ui.Image? _image;
|
||||
final _images = Map<int, Tuple3<ui.Image, double, double>>();
|
||||
double _x = -10000;
|
||||
double _y = -10000;
|
||||
@ -364,7 +363,7 @@ class CursorModel with ChangeNotifier {
|
||||
double _displayOriginX = 0;
|
||||
double _displayOriginY = 0;
|
||||
|
||||
ui.Image get image => _image;
|
||||
ui.Image? get image => _image;
|
||||
|
||||
double get x => _x - _displayOriginX;
|
||||
|
||||
@ -445,7 +444,7 @@ class CursorModel with ChangeNotifier {
|
||||
var tryMoveCanvasX = false;
|
||||
if (dx > 0) {
|
||||
final maxCanvasCanMove =
|
||||
_displayOriginX + FFI.imageModel.image.width - r.right;
|
||||
_displayOriginX + FFI.imageModel.image!.width - r.right;
|
||||
tryMoveCanvasX = _x + dx > cx && maxCanvasCanMove > 0;
|
||||
if (tryMoveCanvasX) {
|
||||
dx = min(dx, maxCanvasCanMove);
|
||||
@ -466,7 +465,7 @@ class CursorModel with ChangeNotifier {
|
||||
var tryMoveCanvasY = false;
|
||||
if (dy > 0) {
|
||||
final mayCanvasCanMove =
|
||||
_displayOriginY + FFI.imageModel.image.height - r.bottom;
|
||||
_displayOriginY + FFI.imageModel.image!.height - r.bottom;
|
||||
tryMoveCanvasY = _y + dy > cy && mayCanvasCanMove > 0;
|
||||
if (tryMoveCanvasY) {
|
||||
dy = min(dy, mayCanvasCanMove);
|
||||
@ -567,12 +566,12 @@ class CursorModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
class ClientState {
|
||||
bool isStart;
|
||||
bool isFileTransfer;
|
||||
String name;
|
||||
String peerId;
|
||||
bool isStart = false;
|
||||
bool isFileTransfer = false;
|
||||
String name = "";
|
||||
String peerId = "";
|
||||
|
||||
ClientState({this.isStart, this.isFileTransfer, this.name, this.peerId});
|
||||
ClientState(this.isStart, this.isFileTransfer, this.name, this.peerId);
|
||||
|
||||
ClientState.fromJson(Map<String, dynamic> json) {
|
||||
isStart = json['is_start'];
|
||||
@ -592,20 +591,17 @@ class ClientState {
|
||||
}
|
||||
|
||||
class ServerModel with ChangeNotifier {
|
||||
bool _mediaOk;
|
||||
bool _inputOk;
|
||||
// bool _needServerOpen;
|
||||
bool _isPeerStart;
|
||||
bool _isFileTransfer;
|
||||
String _peerName;
|
||||
String _peerID;
|
||||
bool _mediaOk = false;
|
||||
bool _inputOk = false;
|
||||
bool _isPeerStart = false;
|
||||
bool _isFileTransfer = false;
|
||||
String _peerName = "";
|
||||
String _peerID = "";
|
||||
|
||||
bool get mediaOk => _mediaOk;
|
||||
|
||||
bool get inputOk => _inputOk;
|
||||
|
||||
// bool get needServerOpen => _needServerOpen;
|
||||
|
||||
bool get isPeerStart => _isPeerStart;
|
||||
|
||||
bool get isFileTransfer => _isFileTransfer;
|
||||
@ -614,18 +610,7 @@ class ServerModel with ChangeNotifier {
|
||||
|
||||
String get peerID => _peerID;
|
||||
|
||||
ServerModel() {
|
||||
_mediaOk = false;
|
||||
_inputOk = false;
|
||||
_isPeerStart = false;
|
||||
_peerName = "";
|
||||
_peerID = "";
|
||||
}
|
||||
|
||||
// setNeedServerOpen(bool v){
|
||||
// _needServerOpen = v;
|
||||
// notifyListeners();
|
||||
// }
|
||||
ServerModel();
|
||||
|
||||
changeStatue(String name, bool value) {
|
||||
switch (name) {
|
||||
@ -753,7 +738,7 @@ class FFI {
|
||||
FFI.id = id;
|
||||
}
|
||||
|
||||
static Map<String, dynamic> popEvent() {
|
||||
static Map<String, dynamic>? popEvent() {
|
||||
var s = getByName('event');
|
||||
if (s == '') return null;
|
||||
try {
|
||||
@ -892,13 +877,13 @@ class Display {
|
||||
}
|
||||
|
||||
class PeerInfo {
|
||||
String version;
|
||||
String username;
|
||||
String hostname;
|
||||
String platform;
|
||||
bool sasEnabled;
|
||||
int currentDisplay;
|
||||
List<Display> displays;
|
||||
String version = "";
|
||||
String username = "";
|
||||
String hostname = "";
|
||||
String platform = "";
|
||||
bool sasEnabled = false;
|
||||
int currentDisplay = 0;
|
||||
List<Display> displays = [];
|
||||
}
|
||||
|
||||
void savePreference(String id, double xCursor, double yCursor, double xCanvas,
|
||||
@ -914,7 +899,7 @@ void savePreference(String id, double xCursor, double yCursor, double xCanvas,
|
||||
prefs.setString('peer' + id, json.encode(p));
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getPreference(String id) async {
|
||||
Future<Map<String, dynamic>?> getPreference(String id) async {
|
||||
if (!isDesktop) return null;
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
var p = prefs.getString('peer' + id);
|
||||
|
@ -11,8 +11,8 @@ import 'common.dart';
|
||||
|
||||
class RgbaFrame extends Struct {
|
||||
@Uint32()
|
||||
int len;
|
||||
Pointer<Uint8> data;
|
||||
external int len;
|
||||
external Pointer<Uint8> data;
|
||||
}
|
||||
|
||||
typedef F2 = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>);
|
||||
@ -21,24 +21,25 @@ typedef F4 = void Function(Pointer<RgbaFrame>);
|
||||
typedef F5 = Pointer<RgbaFrame> Function();
|
||||
|
||||
class PlatformFFI {
|
||||
static Pointer<RgbaFrame> _lastRgbaFrame;
|
||||
static Pointer<RgbaFrame>? _lastRgbaFrame;
|
||||
static String _dir = '';
|
||||
static String _homeDir = '';
|
||||
static F2 _getByName;
|
||||
static F3 _setByName;
|
||||
static F4 _freeRgba;
|
||||
static F5 _getRgba;
|
||||
static F2? _getByName;
|
||||
static F3? _setByName;
|
||||
static F4? _freeRgba;
|
||||
static F5? _getRgba;
|
||||
|
||||
static void clearRgbaFrame() {
|
||||
if (_lastRgbaFrame != null && _lastRgbaFrame != nullptr)
|
||||
_freeRgba(_lastRgbaFrame);
|
||||
if (_lastRgbaFrame != null &&
|
||||
_lastRgbaFrame != nullptr &&
|
||||
_freeRgba != null) _freeRgba!(_lastRgbaFrame!);
|
||||
}
|
||||
|
||||
static Uint8List getRgba() {
|
||||
static Uint8List? getRgba() {
|
||||
if (_getRgba == null) return null;
|
||||
_lastRgbaFrame = _getRgba();
|
||||
_lastRgbaFrame = _getRgba!();
|
||||
if (_lastRgbaFrame == null || _lastRgbaFrame == nullptr) return null;
|
||||
final ref = _lastRgbaFrame.ref;
|
||||
final ref = _lastRgbaFrame!.ref;
|
||||
return Uint8List.sublistView(ref.data.asTypedList(ref.len));
|
||||
}
|
||||
|
||||
@ -51,7 +52,7 @@ class PlatformFFI {
|
||||
if (_getByName == null) return '';
|
||||
var a = name.toNativeUtf8();
|
||||
var b = arg.toNativeUtf8();
|
||||
var p = _getByName(a, b);
|
||||
var p = _getByName!(a, b);
|
||||
assert(p != nullptr && p != null);
|
||||
var res = p.toDartString();
|
||||
calloc.free(p);
|
||||
@ -64,7 +65,7 @@ class PlatformFFI {
|
||||
if (_setByName == null) return;
|
||||
var a = name.toNativeUtf8();
|
||||
var b = value.toNativeUtf8();
|
||||
_setByName(a, b);
|
||||
_setByName!(a, b);
|
||||
calloc.free(a);
|
||||
calloc.free(b);
|
||||
}
|
||||
@ -110,6 +111,7 @@ class PlatformFFI {
|
||||
|
||||
static void startDesktopWebListener(
|
||||
Function(Map<String, dynamic>) handleMouse) {}
|
||||
|
||||
static void stopDesktopWebListener() {}
|
||||
|
||||
static void setMethodCallHandler(FMethod callback) {
|
||||
|
@ -14,7 +14,7 @@ import 'model.dart';
|
||||
final initText = '\1' * 1024;
|
||||
|
||||
class RemotePage extends StatefulWidget {
|
||||
RemotePage({Key key, this.id}) : super(key: key);
|
||||
RemotePage({Key? key, required this.id}) : super(key: key);
|
||||
|
||||
final String id;
|
||||
|
||||
@ -23,8 +23,8 @@ class RemotePage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RemotePageState extends State<RemotePage> {
|
||||
Timer _interval;
|
||||
Timer _timer;
|
||||
Timer? _interval;
|
||||
Timer? _timer;
|
||||
bool _showBar = !isDesktop;
|
||||
double _bottom = 0;
|
||||
String _value = '';
|
||||
@ -47,14 +47,14 @@ class _RemotePageState extends State<RemotePage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
FFI.connect(widget.id);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) {
|
||||
SystemChrome.setEnabledSystemUIOverlays([]);
|
||||
showLoading(translate('Connecting...'), context);
|
||||
_interval =
|
||||
Timer.periodic(Duration(milliseconds: 30), (timer) => interval());
|
||||
});
|
||||
Wakelock.enable();
|
||||
loadingCancelCallback = () => _interval.cancel();
|
||||
loadingCancelCallback = () => _interval?.cancel();
|
||||
_touchMode = FFI.getByName('peer_option', "touch-mode") != '';
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||
_focusNode.dispose();
|
||||
FFI.close();
|
||||
loadingCancelCallback = null;
|
||||
_interval.cancel();
|
||||
_interval?.cancel();
|
||||
_timer?.cancel();
|
||||
dismissLoading();
|
||||
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
|
||||
@ -354,8 +354,8 @@ class _RemotePageState extends State<RemotePage> {
|
||||
onTapUp: (d) {
|
||||
if (_drag || _scroll) return;
|
||||
if (_touchMode) {
|
||||
FFI.cursorModel.touch(
|
||||
d.localPosition.dx, d.localPosition.dy, _right);
|
||||
FFI.cursorModel
|
||||
.touch(d.localPosition.dx, d.localPosition.dy, _right);
|
||||
} else {
|
||||
FFI.tap(_right);
|
||||
}
|
||||
@ -385,12 +385,12 @@ class _RemotePageState extends State<RemotePage> {
|
||||
FFI.cursorModel.updatePan(d.delta.dx, d.delta.dy, _touchMode, _drag);
|
||||
},
|
||||
onTwoFingerScaleUpdate: (d) {
|
||||
var scale = (d.scale -1) / 20 + 1;
|
||||
FFI.canvasModel.updateScale(scale);
|
||||
_scale = scale;
|
||||
FFI.canvasModel.updateScale(d.scale/_scale);
|
||||
_scale = d.scale;
|
||||
},
|
||||
onTwoFingerScaleEnd: (d)=>_scale = 1,
|
||||
onTwoFingerVerticalDragUpdate: (d) {
|
||||
FFI.scroll( - d.delta.dy / 20);
|
||||
FFI.scroll(d.delta.dy / 2);
|
||||
});
|
||||
return GestureDetector(
|
||||
onLongPress: () {
|
||||
@ -491,9 +491,8 @@ class _RemotePageState extends State<RemotePage> {
|
||||
paints.add(CursorPaint());
|
||||
}
|
||||
return MouseRegion(
|
||||
cursor: keyboard
|
||||
? SystemMouseCursors.none
|
||||
: null, // still laggy, set cursor directly for web is better
|
||||
cursor: keyboard ? SystemMouseCursors.none : MouseCursor.defer,
|
||||
// TODO old null // still laggy, set cursor directly for web is better
|
||||
onEnter: (event) {
|
||||
print('enter');
|
||||
FFI.listenToMouse(true);
|
||||
@ -586,8 +585,8 @@ class _RemotePageState extends State<RemotePage> {
|
||||
FFI.setByName('refresh');
|
||||
} else if (value == 'paste') {
|
||||
() async {
|
||||
ClipboardData data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
if (data.text != null) {
|
||||
ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
if (data != null && data.text != null) {
|
||||
FFI.setByName('input_string', '${data.text}');
|
||||
}
|
||||
}();
|
||||
@ -618,8 +617,8 @@ class _RemotePageState extends State<RemotePage> {
|
||||
return SizedBox();
|
||||
}
|
||||
final size = MediaQuery.of(context).size;
|
||||
var wrap =
|
||||
(String text, void Function() onPressed, [bool active, IconData icon]) {
|
||||
var wrap = (String text, void Function() onPressed,
|
||||
[bool? active, IconData? icon]) {
|
||||
return TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
minimumSize: Size(0, 0),
|
||||
@ -811,13 +810,13 @@ class CursorPaint extends StatelessWidget {
|
||||
|
||||
class ImagePainter extends CustomPainter {
|
||||
ImagePainter({
|
||||
this.image,
|
||||
this.x,
|
||||
this.y,
|
||||
this.scale,
|
||||
required this.image,
|
||||
required this.x,
|
||||
required this.y,
|
||||
required this.scale,
|
||||
});
|
||||
|
||||
ui.Image image;
|
||||
ui.Image? image;
|
||||
double x;
|
||||
double y;
|
||||
double scale;
|
||||
@ -826,7 +825,7 @@ class ImagePainter extends CustomPainter {
|
||||
void paint(Canvas canvas, Size size) {
|
||||
if (image == null) return;
|
||||
canvas.scale(scale, scale);
|
||||
canvas.drawImage(image, new Offset(x, y), new Paint());
|
||||
canvas.drawImage(image!, new Offset(x, y), new Paint());
|
||||
}
|
||||
|
||||
@override
|
||||
@ -853,7 +852,9 @@ void enterPasswordDialog(String id, BuildContext context) {
|
||||
),
|
||||
value: remember,
|
||||
onChanged: (v) {
|
||||
setState(() => remember = v);
|
||||
if (v != null) {
|
||||
setState(() => remember = v);
|
||||
}
|
||||
},
|
||||
),
|
||||
]),
|
||||
@ -918,7 +919,7 @@ CheckboxListTile getToggle(
|
||||
}
|
||||
|
||||
RadioListTile<String> getRadio(String name, String toValue, String curValue,
|
||||
void Function(String) onChange) {
|
||||
void Function(String?) onChange) {
|
||||
return RadioListTile<String>(
|
||||
controlAffinity: ListTileControlAffinity.trailing,
|
||||
title: Text(translate(name)),
|
||||
@ -985,13 +986,15 @@ void showOptions(BuildContext context) {
|
||||
more.add(getToggle(setState, 'privacy-mode', 'Privacy mode'));
|
||||
}
|
||||
}
|
||||
var setQuality = (String value) {
|
||||
var setQuality = (String? value) {
|
||||
if(value == null) return;
|
||||
setState(() {
|
||||
quality = value;
|
||||
FFI.setByName('image_quality', value);
|
||||
});
|
||||
};
|
||||
var setViewStyle = (String value) {
|
||||
var setViewStyle = (String? value) {
|
||||
if(value == null) return;
|
||||
setState(() {
|
||||
viewStyle = value;
|
||||
FFI.setByName(
|
||||
@ -1000,7 +1003,7 @@ void showOptions(BuildContext context) {
|
||||
});
|
||||
};
|
||||
return Tuple3(
|
||||
null,
|
||||
SizedBox.shrink(),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: displays +
|
||||
@ -1012,7 +1015,7 @@ void showOptions(BuildContext context) {
|
||||
getRadio('Stretch', 'stretch', viewStyle, setViewStyle),
|
||||
Divider(color: MyTheme.border),
|
||||
]
|
||||
: {}) +
|
||||
: []) +
|
||||
<Widget>[
|
||||
getRadio('Good image quality', 'best', quality, setQuality),
|
||||
getRadio('Balanced', 'balanced', quality, setQuality),
|
||||
@ -1023,7 +1026,7 @@ void showOptions(BuildContext context) {
|
||||
setState, 'show-remote-cursor', 'Show remote cursor'),
|
||||
] +
|
||||
more),
|
||||
null);
|
||||
[]);
|
||||
}, () async => true, true, 0);
|
||||
}
|
||||
|
||||
@ -1047,6 +1050,7 @@ void showSetOSPassword(BuildContext context, bool login) {
|
||||
),
|
||||
value: autoLogin,
|
||||
onChanged: (v) {
|
||||
if(v==null) return;
|
||||
setState(() => autoLogin = v);
|
||||
},
|
||||
),
|
||||
|
@ -101,7 +101,7 @@ class _ServerInfoState extends State<ServerInfo> {
|
||||
labelStyle:
|
||||
TextStyle(fontWeight: FontWeight.bold, color: MyTheme.accent50),
|
||||
),
|
||||
onSaved: (String value) {},
|
||||
onSaved: (String? value) {},
|
||||
),
|
||||
TextFormField(
|
||||
readOnly: true,
|
||||
@ -123,7 +123,7 @@ class _ServerInfoState extends State<ServerInfo> {
|
||||
_passwdShow = !_passwdShow;
|
||||
});
|
||||
})),
|
||||
onSaved: (String value) {},
|
||||
onSaved: (String? value) {},
|
||||
),
|
||||
],
|
||||
));
|
||||
@ -187,7 +187,7 @@ class _PermissionCheckerState extends State<PermissionChecker> {
|
||||
}
|
||||
}
|
||||
|
||||
BuildContext loginReqAlertCtx;
|
||||
BuildContext? loginReqAlertCtx;
|
||||
|
||||
void showLoginReqAlert(BuildContext context, String peerID, String name) async {
|
||||
await showDialog(
|
||||
@ -238,7 +238,7 @@ void showLoginReqAlert(BuildContext context, String peerID, String name) async {
|
||||
|
||||
clearLoginReqAlert() {
|
||||
if (loginReqAlertCtx != null) {
|
||||
Navigator.of(loginReqAlertCtx).pop();
|
||||
Navigator.of(loginReqAlertCtx!).pop();
|
||||
FFI.serverModel.updateClientState();
|
||||
}
|
||||
}
|
||||
@ -372,8 +372,10 @@ void toAndroidChannelInit() {
|
||||
FFI.serverModel.updateClientState();
|
||||
debugPrint(
|
||||
"pre show loginAlert:${FFI.serverModel.isFileTransfer.toString()}");
|
||||
showLoginReqAlert(
|
||||
currentCtx, FFI.serverModel.peerID, FFI.serverModel.peerName);
|
||||
if(currentCtx!=null){
|
||||
showLoginReqAlert(
|
||||
currentCtx!, FFI.serverModel.peerID, FFI.serverModel.peerName);
|
||||
}
|
||||
debugPrint("from jvm:try_start_without_auth done");
|
||||
break;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ Map<String, dynamic> getEvent(MouseEvent evt) {
|
||||
out['buttons'] = evt
|
||||
.buttons; // left button: 1, right button: 2, middle button: 4, 1 | 2 = 3 (left + right)
|
||||
if (evt.buttons != 0) {
|
||||
lastMouseDownButtons = evt.buttons;
|
||||
lastMouseDownButtons = evt.buttons!;
|
||||
} else {
|
||||
out['buttons'] = lastMouseDownButtons;
|
||||
}
|
||||
@ -125,7 +125,7 @@ void handleKey(KeyboardEvent evt, bool down) {
|
||||
name = evt.code;
|
||||
} else {
|
||||
name = evt.key;
|
||||
if (name.toLowerCase() != name.toUpperCase() &&
|
||||
if (name!=null && name.toLowerCase() != name.toUpperCase() &&
|
||||
name == name.toUpperCase()) {
|
||||
if (!evt.shiftKey) out['shift'] = 'true';
|
||||
}
|
||||
|
11
pubspec.yaml
11
pubspec.yaml
@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.1.9+20
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
@ -32,10 +32,11 @@ dependencies:
|
||||
path_provider: ^2.0.2
|
||||
external_path: ^1.0.1
|
||||
provider: ^5.0.0
|
||||
flutter_easyloading: # not Null safety 2.2.0
|
||||
git:
|
||||
url: git://github.com/open-trade/flutter_easyloading
|
||||
#path: flutter_easyloading
|
||||
flutter_easyloading: ^3.0.3
|
||||
# flutter_easyloading: # not Null safety 2.2.0
|
||||
# git:
|
||||
# url: git://github.com/open-trade/flutter_easyloading
|
||||
# #path: flutter_easyloading
|
||||
tuple: ^2.0.0
|
||||
wakelock: ^0.5.2
|
||||
device_info: ^2.0.2
|
||||
|
Loading…
x
Reference in New Issue
Block a user