Merge branch 'service' of github.com:open-trade/flutter_hbb into service

This commit is contained in:
csf 2022-04-04 15:03:24 +08:00
commit 72936b55bd
18 changed files with 98 additions and 148 deletions

View File

@ -0,0 +1 @@
../../../../../../../../.android/libc++_shared.so

View File

@ -0,0 +1 @@
../../../../../../../../.android/libcrypto.so

View File

@ -0,0 +1 @@
../../../../../../../../.android/liblibrustdesk.so

View File

@ -0,0 +1 @@
../../../../../../../../.android/libssl.so

View File

@ -6,7 +6,6 @@ import android.content.Intent
import android.os.Build import android.os.Build
import android.widget.Toast import android.widget.Toast
// 开机自启动 此功能暂不开启
class BootReceiver : BroadcastReceiver() { class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
if ("android.intent.action.BOOT_COMPLETED" == intent.action){ if ("android.intent.action.BOOT_COMPLETED" == intent.action){

View File

@ -29,7 +29,6 @@ class InputService : AccessibilityService() {
@RequiresApi(Build.VERSION_CODES.N) @RequiresApi(Build.VERSION_CODES.N)
fun rustMouseInput(mask: Int, _x: Int, _y: Int) { fun rustMouseInput(mask: Int, _x: Int, _y: Int) {
// TODO 按键抬起按下时候 x y 都是0
if (!(mask == 9 || mask == 10)) { if (!(mask == 9 || mask == 10)) {
mouseX = _x * INFO.scale mouseX = _x * INFO.scale
mouseY = _y * INFO.scale mouseY = _y * INFO.scale
@ -77,12 +76,10 @@ class InputService : AccessibilityService() {
dispatchGesture(builder.build(), object : GestureResultCallback() { dispatchGesture(builder.build(), object : GestureResultCallback() {
override fun onCompleted(gestureDescription: GestureDescription) { override fun onCompleted(gestureDescription: GestureDescription) {
super.onCompleted(gestureDescription) super.onCompleted(gestureDescription)
Log.d(logTag, "滑动成功")
} }
override fun onCancelled(gestureDescription: GestureDescription) { override fun onCancelled(gestureDescription: GestureDescription) {
super.onCancelled(gestureDescription) super.onCancelled(gestureDescription)
Log.d(logTag, "滑动失败 ")
} }
}, null) }, null)
} }

View File

@ -126,7 +126,6 @@ class MainActivity : FlutterActivity() {
startActivityForResult(mIntent, MEDIA_REQUEST_CODE) startActivityForResult(mIntent, MEDIA_REQUEST_CODE)
} }
// 在onActivityResult中成功获取到mediaProjection就开始就调用此函数开始初始化监听服务
private fun initService() { private fun initService() {
if (mediaProjectionResultIntent == null) { if (mediaProjectionResultIntent == null) {
Log.w(logTag, "initService fail,mediaProjectionResultIntent is null") Log.w(logTag, "initService fail,mediaProjectionResultIntent is null")
@ -178,8 +177,6 @@ class MainActivity : FlutterActivity() {
} }
private fun updateMachineInfo() { private fun updateMachineInfo() {
// 屏幕尺寸 控制最长边不超过1400 超过则减半并储存缩放比例 实际发送给手机端的尺寸为缩小后的尺寸
// input控制时再通过缩放比例恢复原始尺寸进行path入参
val dm = DisplayMetrics() val dm = DisplayMetrics()
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

View File

@ -41,14 +41,14 @@ const val EXTRA_LOGIN_REQ_NOTIFY = "EXTRA_LOGIN_REQ_NOTIFY"
const val DEFAULT_NOTIFY_TITLE = "RustDesk" const val DEFAULT_NOTIFY_TITLE = "RustDesk"
const val DEFAULT_NOTIFY_TEXT = "Service is running" const val DEFAULT_NOTIFY_TEXT = "Service is running"
const val DEFAULT_NOTIFY_ID = 1 const val DEFAULT_NOTIFY_ID = 1
const val NOTIFY_ID_OFFSET = 100 // 为每个客户端ID增加这个偏移量而得到通知栏ID避免使用0且防止和默认ID冲突 const val NOTIFY_ID_OFFSET = 100
const val NOTIFY_TYPE_START_CAPTURE = "NOTIFY_TYPE_START_CAPTURE" const val NOTIFY_TYPE_START_CAPTURE = "NOTIFY_TYPE_START_CAPTURE"
const val MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_VP9 const val MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_VP9
// video const // video const
const val MAX_SCREEN_SIZE = 1200 // 内置编码器有上限 且实际使用中不需要过高的分辨率 const val MAX_SCREEN_SIZE = 1200
const val VIDEO_KEY_BIT_RATE = 1024_000 const val VIDEO_KEY_BIT_RATE = 1024_000
const val VIDEO_KEY_FRAME_RATE = 30 const val VIDEO_KEY_FRAME_RATE = 30
@ -157,14 +157,13 @@ class MainService : Service() {
private val logTag = "LOG_SERVICE" private val logTag = "LOG_SERVICE"
private val useVP9 = false private val useVP9 = false
private val binder = LocalBinder() private val binder = LocalBinder()
private var _isReady = false // 是否获取了录屏权限 private var _isReady = false
private var _isStart = false // 是否正在进行录制 private var _isStart = false
val isReady: Boolean val isReady: Boolean
get() = _isReady get() = _isReady
val isStart: Boolean val isStart: Boolean
get() = _isStart get() = _isStart
// video 注意 这里imageReader要成为成员变量防止被回收 https://www.cnblogs.com/yongdaimi/p/11004560.html
private var mediaProjection: MediaProjection? = null private var mediaProjection: MediaProjection? = null
private var surface: Surface? = null private var surface: Surface? = null
private val sendVP9Thread = Executors.newSingleThreadExecutor() private val sendVP9Thread = Executors.newSingleThreadExecutor()
@ -179,7 +178,7 @@ class MainService : Service() {
private var audioData: FloatArray? = null private var audioData: FloatArray? = null
private var minBufferSize = 0 private var minBufferSize = 0
private var isNewData = false private var isNewData = false
private val audioZeroData: FloatArray = FloatArray(32) // 必须是32位 如果只有8位进行ffi传输时会出错 private val audioZeroData: FloatArray = FloatArray(32)
private var audioRecordStat = false private var audioRecordStat = false
// notification // notification
@ -208,7 +207,6 @@ class MainService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d("whichService", "this service:${Thread.currentThread()}") Log.d("whichService", "this service:${Thread.currentThread()}")
// 只有init的时候通过onStartCommand 且开启前台服务
if (intent?.action == INIT_SERVICE) { if (intent?.action == INIT_SERVICE) {
Log.d(logTag, "service starting:${startId}:${Thread.currentThread()}") Log.d(logTag, "service starting:${startId}:${Thread.currentThread()}")
createForegroundNotification() createForegroundNotification()
@ -217,25 +215,20 @@ class MainService : Service() {
intent.getParcelableExtra<Intent>(EXTRA_MP_DATA)?.let { intent.getParcelableExtra<Intent>(EXTRA_MP_DATA)?.let {
mediaProjection = mediaProjection =
mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it) mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it)
Log.d(logTag, "获取mMediaProjection成功$mediaProjection")
checkMediaPermission() checkMediaPermission()
surface = createSurface() surface = createSurface()
init(this) init(this)
_isReady = true _isReady = true
} ?: let { } ?: let {
Log.d(logTag, "获取mMediaProjection失败")
} }
// } else if (intent?.action == ACTION_LOGIN_REQ_NOTIFY) { // } else if (intent?.action == ACTION_LOGIN_REQ_NOTIFY) {
// 暂时不开启通知从通知栏确认登录
// val notifyLoginRes = intent.getBooleanExtra(EXTRA_LOGIN_REQ_NOTIFY, false) // val notifyLoginRes = intent.getBooleanExtra(EXTRA_LOGIN_REQ_NOTIFY, false)
// Log.d(logTag, "从通知栏点击了:$notifyLoginRes")
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
@SuppressLint("WrongConstant") @SuppressLint("WrongConstant")
private fun createSurface(): Surface? { private fun createSurface(): Surface? {
// 暂时只使用原始数据的情况
return if (useVP9) { return if (useVP9) {
// TODO // TODO
null null
@ -246,7 +239,7 @@ class MainService : Service() {
INFO.screenWidth, INFO.screenWidth,
INFO.screenHeight, INFO.screenHeight,
PixelFormat.RGBA_8888, PixelFormat.RGBA_8888,
2 // maxImages 至少是2 2
).apply { ).apply {
setOnImageAvailableListener({ imageReader: ImageReader -> setOnImageAvailableListener({ imageReader: ImageReader ->
try { try {
@ -292,7 +285,6 @@ class MainService : Service() {
startRawVideoRecorder(mediaProjection!!) startRawVideoRecorder(mediaProjection!!)
} }
// 音频只支持安卓10以及以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
startAudioRecorder() startAudioRecorder()
} }
@ -363,7 +355,6 @@ class MainService : Service() {
@SuppressLint("WrongConstant") @SuppressLint("WrongConstant")
private fun startVP9VideoRecorder(mp: MediaProjection) { private fun startVP9VideoRecorder(mp: MediaProjection) {
//使用内置编码器
createMediaCodec() createMediaCodec()
videoEncoder?.let { videoEncoder?.let {
surface = it.createInputSurface() surface = it.createInputSurface()
@ -391,7 +382,6 @@ class MainService : Service() {
) { ) {
codec.getOutputBuffer(index)?.let { buf -> codec.getOutputBuffer(index)?.let { buf ->
sendVP9Thread.execute { sendVP9Thread.execute {
// TODO 优化内存使用方式
val byteArray = ByteArray(buf.limit()) val byteArray = ByteArray(buf.limit())
buf.get(byteArray) buf.get(byteArray)
// sendVp9(byteArray) // sendVp9(byteArray)
@ -411,7 +401,7 @@ class MainService : Service() {
videoEncoder = MediaCodec.createEncoderByType(MIME_TYPE) videoEncoder = MediaCodec.createEncoderByType(MIME_TYPE)
val mFormat = MediaFormat.createVideoFormat(MIME_TYPE, INFO.screenWidth, INFO.screenHeight) val mFormat = MediaFormat.createVideoFormat(MIME_TYPE, INFO.screenWidth, INFO.screenHeight)
mFormat.setInteger(MediaFormat.KEY_BIT_RATE, VIDEO_KEY_BIT_RATE) mFormat.setInteger(MediaFormat.KEY_BIT_RATE, VIDEO_KEY_BIT_RATE)
mFormat.setInteger(MediaFormat.KEY_FRAME_RATE, VIDEO_KEY_FRAME_RATE) // codec的帧率设置无效 mFormat.setInteger(MediaFormat.KEY_FRAME_RATE, VIDEO_KEY_FRAME_RATE)
mFormat.setInteger( mFormat.setInteger(
MediaFormat.KEY_COLOR_FORMAT, MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible
@ -433,7 +423,6 @@ class MainService : Service() {
thread { thread {
while (audioRecordStat) { while (audioRecordStat) {
val res = audioRecorder!!.read(audioData!!, 0, minBufferSize, READ_BLOCKING) val res = audioRecorder!!.read(audioData!!, 0, minBufferSize, READ_BLOCKING)
// 录制float 需要使用对应的read float[] 函数
if (res != AudioRecord.ERROR_INVALID_OPERATION) { if (res != AudioRecord.ERROR_INVALID_OPERATION) {
isNewData = true isNewData = true
} }
@ -493,7 +482,6 @@ class MainService : Service() {
private fun initNotification() { private fun initNotification() {
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// 设置通知渠道 android8开始引入 老版本会被忽略 这个东西的作用相当于为通知分类 给用户选择通知消息的种类
notificationChannel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { notificationChannel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelId = "RustDesk" val channelId = "RustDesk"
val channelName = "RustDesk Service" val channelName = "RustDesk Service"
@ -517,7 +505,7 @@ class MainService : Service() {
private fun createForegroundNotification() { private fun createForegroundNotification() {
val intent = Intent(this, MainActivity::class.java).apply { val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
action = Intent.ACTION_MAIN // 不设置会造成每次都重新启动一个新的Activity action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER) addCategory(Intent.CATEGORY_LAUNCHER)
putExtra("type", type) putExtra("type", type)
} }
@ -539,19 +527,16 @@ class MainService : Service() {
.setColor(ContextCompat.getColor(this, R.color.primary)) .setColor(ContextCompat.getColor(this, R.color.primary))
.setWhen(System.currentTimeMillis()) .setWhen(System.currentTimeMillis())
.build() .build()
// 这里满足前台服务首次启动时5s内设定好通知内容这里使用startForeground后续普通调用使用notificationManager即可
startForeground(DEFAULT_NOTIFY_ID, notification) startForeground(DEFAULT_NOTIFY_ID, notification)
} }
private fun loginRequestNotification(clientID:Int, type: String, username: String, peerId: String) { private fun loginRequestNotification(clientID:Int, type: String, username: String, peerId: String) {
// notificationBuilder 第一次使用时状态已保存,再次生成时只需要调整需要修改的部分
cancelNotification(clientID) cancelNotification(clientID)
val notification = notificationBuilder val notification = notificationBuilder
.setOngoing(false) .setOngoing(false)
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentTitle(translate("Do you accept?")) .setContentTitle(translate("Do you accept?"))
.setContentText("$type:$username-$peerId") .setContentText("$type:$username-$peerId")
// 暂时不开启通知栏接受请求
// .setStyle(MediaStyle().setShowActionsInCompactView(0, 1)) // .setStyle(MediaStyle().setShowActionsInCompactView(0, 1))
// .addAction(R.drawable.check_blue, "check", genLoginRequestPendingIntent(true)) // .addAction(R.drawable.check_blue, "check", genLoginRequestPendingIntent(true))
// .addAction(R.drawable.close_red, "close", genLoginRequestPendingIntent(false)) // .addAction(R.drawable.close_red, "close", genLoginRequestPendingIntent(false))
@ -574,11 +559,6 @@ class MainService : Service() {
return clientID + NOTIFY_ID_OFFSET return clientID + NOTIFY_ID_OFFSET
} }
/**
* 关闭通知的情况
* 1.UI端接受或拒绝
* 2.peer端通过密码建立了连接在onClientAuthorizedNotification中已处理 peer端手动取消了连接
*/
fun cancelNotification(clientID:Int){ fun cancelNotification(clientID:Int){
notificationManager.cancel(getClientNotifyID(clientID)) notificationManager.cancel(getClientNotifyID(clientID))
} }

View File

@ -25,7 +25,7 @@ data class Info(
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun testVP9Support(): Boolean { fun testVP9Support(): Boolean {
return true // 函数内部永远返回true 暂时只使用原始数据 return true
val res = MediaCodecList(MediaCodecList.ALL_CODECS) val res = MediaCodecList(MediaCodecList.ALL_CODECS)
.findEncoderForFormat( .findEncoderForFormat(
MediaFormat.createVideoFormat( MediaFormat.createVideoFormat(

View File

@ -7,9 +7,6 @@ import 'package:flutter_hbb/pages/chat_page.dart';
import 'model.dart'; import 'model.dart';
class ChatModel with ChangeNotifier { class ChatModel with ChangeNotifier {
// -1idid唯一
// ididid
// id和peer_id不同id等同于conn的顺序累加id
static final clientModeID = -1; static final clientModeID = -1;
final Map<int, List<ChatMessage>> _messages = Map()..[clientModeID] = []; final Map<int, List<ChatMessage>> _messages = Map()..[clientModeID] = [];

View File

@ -26,10 +26,6 @@ class FileModel extends ChangeNotifier {
var _localOption = DirectoryOption(); var _localOption = DirectoryOption();
var _remoteOption = DirectoryOption(); var _remoteOption = DirectoryOption();
/// _jobIdfile_num是文件夹中的单独文件id
///
/// file_num = 0;
/// 3 file_num = 2;
var _jobId = 0; var _jobId = 0;
var _jobProgress = JobProgress(); // from rust update var _jobProgress = JobProgress(); // from rust update
@ -119,7 +115,6 @@ class FileModel extends ChangeNotifier {
_fileFetcher.tryCompleteTask(evt['value'], evt['is_local']); _fileFetcher.tryCompleteTask(evt['value'], evt['is_local']);
} }
// job
jobDone(Map<String, dynamic> evt) { jobDone(Map<String, dynamic> evt) {
if (_jobResultListener.isListening) { if (_jobResultListener.isListening) {
_jobResultListener.complete(evt); _jobResultListener.complete(evt);
@ -250,7 +245,7 @@ class FileModel extends ChangeNotifier {
"path": from.path, "path": from.path,
"to": PathUtil.join(toPath, from.name, isWindows), "to": PathUtil.join(toPath, from.name, isWindows),
"show_hidden": showHidden.toString(), "show_hidden": showHidden.toString(),
"is_remote": (!(items.isLocal!)).toString() // from的位置而不是to的位置 "is_remote": (!(items.isLocal!)).toString()
}; };
FFI.setByName("send_files", jsonEncode(msg)); FFI.setByName("send_files", jsonEncode(msg));
}); });
@ -282,7 +277,6 @@ class FileModel extends ChangeNotifier {
_jobId, item.path, items.isLocal!, true); _jobId, item.path, items.isLocal!, true);
fd.format(isWindows); fd.format(isWindows);
EasyLoading.dismiss(); EasyLoading.dismiss();
//
if (fd.entries.isEmpty) { if (fd.entries.isEmpty) {
final confirm = await showRemoveDialog(translate("Are you sure you want to delete this empty directory?"), item.name, false); final confirm = await showRemoveDialog(translate("Are you sure you want to delete this empty directory?"), item.name, false);
if (confirm == true) { if (confirm == true) {
@ -476,7 +470,7 @@ class FileFetcher {
Timer(Duration(seconds: 2), () { Timer(Duration(seconds: 2), () {
tasks.remove(path); tasks.remove(path);
if (c.isCompleted) return; // map if (c.isCompleted) return;
c.completeError("Failed to read dir,timeout"); c.completeError("Failed to read dir,timeout");
}); });
return c.future; return c.future;
@ -492,7 +486,7 @@ class FileFetcher {
Timer(Duration(seconds: 2), () { Timer(Duration(seconds: 2), () {
tasks.remove(id); tasks.remove(id);
if (c.isCompleted) return; // map if (c.isCompleted) return;
c.completeError("Failed to read dir,timeout"); c.completeError("Failed to read dir,timeout");
}); });
return c.future; return c.future;

View File

@ -419,17 +419,6 @@ showInputWarnAlert() async {
DialogManager.register(alertContext); DialogManager.register(alertContext);
return AlertDialog( return AlertDialog(
title: Text(translate("How to get Android input permission?")), title: Text(translate("How to get Android input permission?")),
// content: Text.rich(TextSpan(style: TextStyle(), children: [
// // [] : [Installed Services]
// // [Installed Services][RustDesk Input]
// TextSpan(text: "请在接下来的系统设置页\n进入"),
// TextSpan(text: " [服务] ", style: TextStyle(color: MyTheme.accent)),
// TextSpan(text: "配置页面\n"),
// TextSpan(
// text: " [RustDesk Input] ",
// style: TextStyle(color: MyTheme.accent)),
// TextSpan(text: "服务开启")
// ])),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [

View File

@ -83,7 +83,7 @@ class PlatformFFI {
static void setMethodCallHandler(FMethod callback) {} static void setMethodCallHandler(FMethod callback) {}
static Future<bool> invokeMethod(String method) async { static Future<bool> invokeMethod(String method, [ dynamic arguments]) async {
return true; return true;
} }
} }

View File

@ -22,7 +22,7 @@ class ChatPage extends StatelessWidget implements PageShape {
@override @override
final appBarActions = [ final appBarActions = [
PopupMenuButton<int>( PopupMenuButton<int>(
icon: Icon(Icons.list_alt), icon: Icon(Icons.more_vert),
itemBuilder: (context) { itemBuilder: (context) {
final chatModel = FFI.chatModel; final chatModel = FFI.chatModel;
final serverModel = FFI.serverModel; final serverModel = FFI.serverModel;
@ -194,9 +194,7 @@ class _ChatWindowOverlayState extends State<ChatWindowOverlay> {
}); });
} }
checkScreenSize() { checkScreenSize() {}
// TODO
}
checkKeyboard() { checkKeyboard() {
final bottomHeight = MediaQuery.of(context).viewInsets.bottom; final bottomHeight = MediaQuery.of(context).viewInsets.bottom;

View File

@ -286,37 +286,40 @@ class _WebMenuState extends State<WebMenu> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
Provider.of<FfiModel>(context); Provider.of<FfiModel>(context);
final username = getUsername(); final username = getUsername();
return PopupMenuButton<String>(itemBuilder: (context) { return PopupMenuButton<String>(
return [ icon: Icon(Icons.more_vert),
PopupMenuItem( itemBuilder: (context) {
child: Text(translate('ID/Relay Server')), return [
value: "server", PopupMenuItem(
), child: Text(translate('ID/Relay Server')),
PopupMenuItem( value: "server",
child: Text(username == null ),
? translate("Login") PopupMenuItem(
: translate("Logout") + ' ($username)'), child: Text(username == null
value: "login", ? translate("Login")
), : translate("Logout") + ' ($username)'),
PopupMenuItem( value: "login",
child: Text(translate('About') + ' RustDesk'), ),
value: "about", PopupMenuItem(
) child: Text(translate('About') + ' RustDesk'),
]; value: "about",
}, onSelected: (value) { )
if (value == 'server') { ];
showServer(); },
} onSelected: (value) {
if (value == 'about') { if (value == 'server') {
showAbout(); showServer();
} }
if (value == 'login') { if (value == 'about') {
if (username == null) { showAbout();
showLogin(); }
} else { if (value == 'login') {
logout(); if (username == null) {
} showLogin();
} } else {
}); logout();
}
}
});
} }
} }

View File

@ -360,7 +360,6 @@ class _FileManagerPageState extends State<FileManagerPage> {
if (model.selectMode) { if (model.selectMode) {
if (_selectedItems.length == 0 || !isOtherPage) { if (_selectedItems.length == 0 || !isOtherPage) {
//
return BottomSheetBody( return BottomSheetBody(
leading: Icon(Icons.check), leading: Icon(Icons.check),
title: translate("Selected"), title: translate("Selected"),
@ -377,7 +376,6 @@ class _FileManagerPageState extends State<FileManagerPage> {
) )
]); ]);
} else { } else {
//
return BottomSheetBody( return BottomSheetBody(
leading: Icon(Icons.input), leading: Icon(Icons.input),
title: translate("Paste here?"), title: translate("Paste here?"),

View File

@ -17,41 +17,44 @@ class ServerPage extends StatelessWidget implements PageShape {
@override @override
final appBarActions = [ final appBarActions = [
PopupMenuButton<String>(itemBuilder: (context) { PopupMenuButton<String>(
return [ icon: Icon(Icons.more_vert),
PopupMenuItem( itemBuilder: (context) {
child: Text(translate("Change ID")), return [
value: "changeID", PopupMenuItem(
enabled: false, child: Text(translate("Change ID")),
), value: "changeID",
PopupMenuItem( enabled: false,
child: Text(translate("Set your own password")), ),
value: "changePW", PopupMenuItem(
enabled: FFI.serverModel.isStart, child: Text(translate("Set your own password")),
), value: "changePW",
PopupMenuItem( enabled: FFI.serverModel.isStart,
child: Text(translate("Refresh random password")), ),
value: "refreshPW", PopupMenuItem(
enabled: FFI.serverModel.isStart, child: Text(translate("Refresh random password")),
) value: "refreshPW",
]; enabled: FFI.serverModel.isStart,
}, onSelected: (value) { )
if (value == "changeID") { ];
// TODO },
} else if (value == "changePW") { onSelected: (value) {
updatePasswordDialog(); if (value == "changeID") {
} else if (value == "refreshPW") { // TODO
() async { } else if (value == "changePW") {
showLoading(translate("Waiting")); updatePasswordDialog();
if(await FFI.serverModel.updatePassword("")){ } else if (value == "refreshPW") {
showSuccess(); () async {
}else{ showLoading(translate("Waiting"));
showError(); if (await FFI.serverModel.updatePassword("")) {
showSuccess();
} else {
showError();
}
debugPrint("end updatePassword");
}();
} }
debugPrint("end updatePassword"); })
}();
}
})
]; ];
@override @override

View File

@ -239,8 +239,8 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
bool _isStart = false; bool _isStart = false;
Timer? _firstTapUpTimer; // reject Timer? _firstTapUpTimer;
Timer? _secondTapDownTimer; // reject drag update Timer? _secondTapDownTimer;
_TapTracker? _firstTap; _TapTracker? _firstTap;
_TapTracker? _secondTap; _TapTracker? _secondTap;
@ -266,7 +266,6 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
@override @override
void addAllowedPointer(PointerDownEvent event) { void addAllowedPointer(PointerDownEvent event) {
//
if (_firstTap != null) { if (_firstTap != null) {
if (!_firstTap!.isWithinGlobalTolerance(event, kDoubleTapSlop)) { if (!_firstTap!.isWithinGlobalTolerance(event, kDoubleTapSlop)) {
// Ignore out-of-bounds second taps. // Ignore out-of-bounds second taps.
@ -285,7 +284,7 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
localPosition: event.localPosition))); localPosition: event.localPosition)));
} }
} }
_trackTap(event); // tap _trackTap(event);
} }
void _trackTap(PointerDownEvent event) { void _trackTap(PointerDownEvent event) {
@ -301,14 +300,12 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
tracker.startTrackingPointer(_handleEvent, event.transform); tracker.startTrackingPointer(_handleEvent, event.transform);
} }
// down后一段时间没有抬起则表示start
void _handleEvent(PointerEvent event) { void _handleEvent(PointerEvent event) {
final _TapTracker tracker = _trackers[event.pointer]!; final _TapTracker tracker = _trackers[event.pointer]!;
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
if (_firstTap == null && _secondTap == null) { if (_firstTap == null && _secondTap == null) {
_registerFirstTap(tracker); _registerFirstTap(tracker);
} else { } else {
//
_reject(tracker); _reject(tracker);
} }
} else if (event is PointerDownEvent) { } else if (event is PointerDownEvent) {
@ -316,7 +313,6 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
_registerSecondTap(tracker); _registerSecondTap(tracker);
} }
} else if (event is PointerMoveEvent) { } else if (event is PointerMoveEvent) {
// first tap move second tap move且已经通过竞技场则update
if (!tracker.isWithinGlobalTolerance(event, kDoubleTapTouchSlop)) { if (!tracker.isWithinGlobalTolerance(event, kDoubleTapTouchSlop)) {
if (_firstTap != null && _firstTap!.pointer == event.pointer) { if (_firstTap != null && _firstTap!.pointer == event.pointer) {
// first tap move // first tap move
@ -403,7 +399,6 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
GestureBinding.instance!.gestureArena.release(tracker.pointer); GestureBinding.instance!.gestureArena.release(tracker.pointer);
} }
} }
// TODO
_firstTap = null; _firstTap = null;
_secondTap = null; _secondTap = null;
_clearTrackers(); _clearTrackers();
@ -420,7 +415,6 @@ class HoldTapMoveGestureRecognizer extends GestureRecognizer {
} }
void _registerSecondTap(_TapTracker tracker) { void _registerSecondTap(_TapTracker tracker) {
// first tap的状态
if (_firstTap != null) { if (_firstTap != null) {
_stopFirstTapUpTimer(); _stopFirstTapUpTimer();
_freezeTracker(_firstTap!); _freezeTracker(_firstTap!);
@ -489,7 +483,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
GestureTapDownCallback? onDoubleFinerTap; GestureTapDownCallback? onDoubleFinerTap;
GestureTapCancelCallback? onDoubleFinerTapCancel; GestureTapCancelCallback? onDoubleFinerTapCancel;
Timer? _firstTapTimer; // reject Timer? _firstTapTimer;
_TapTracker? _firstTap; _TapTracker? _firstTap;
var _isStart = false; var _isStart = false;
@ -518,7 +512,6 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
@override @override
void addAllowedPointer(PointerDownEvent event) { void addAllowedPointer(PointerDownEvent event) {
//
debugPrint("addAllowedPointer"); debugPrint("addAllowedPointer");
if (_isStart) { if (_isStart) {
// second // second
@ -536,7 +529,7 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
_isStart = true; _isStart = true;
_startFirstTapDownTimer(); _startFirstTapDownTimer();
} }
_trackTap(event); // tap _trackTap(event);
} }
void _trackTap(PointerDownEvent event) { void _trackTap(PointerDownEvent event) {
@ -553,7 +546,6 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
_registerTap(tracker); _registerTap(tracker);
} }
// down后一段时间没有抬起则表示start
void _handleEvent(PointerEvent event) { void _handleEvent(PointerEvent event) {
final _TapTracker tracker = _trackers[event.pointer]!; final _TapTracker tracker = _trackers[event.pointer]!;
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
@ -608,7 +600,6 @@ class DoubleFinerTapGestureRecognizer extends GestureRecognizer {
void _reset() { void _reset() {
_stopFirstTapUpTimer(); _stopFirstTapUpTimer();
_firstTap = null; _firstTap = null;
// TODO
_clearTrackers(); _clearTrackers();
} }