mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge remote-tracking branch 'rustdesk/master' into flutter_desktop
# Conflicts: # Cargo.lock # Cargo.toml # build.rs # flutter/.gitignore # flutter/lib/common.dart # flutter/lib/mobile/pages/remote_page.dart # flutter/lib/models/model.dart # flutter/lib/models/native_model.dart # flutter/lib/models/server_model.dart # flutter/pubspec.lock # flutter/pubspec.yaml # src/client.rs # src/client/file_trait.rs # src/flutter.rs # src/mobile_ffi.rs # src/ui.rs
This commit is contained in:
5
flutter/.gitignore
vendored
5
flutter/.gitignore
vendored
@@ -54,4 +54,7 @@ linux/flutter/generated_plugins.cmake
|
||||
macos/Flutter/GeneratedPluginRegistrant.swift
|
||||
windows/flutter/generated_plugin_registrant.cc
|
||||
windows/flutter/generated_plugin_registrant.h
|
||||
windows/flutter/generated_plugins.cmake
|
||||
windows/flutter/generated_plugins.cmake
|
||||
flutter_export_environment.sh
|
||||
Flutter-Generated.xcconfig
|
||||
key.jks
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<!--<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />-->
|
||||
|
||||
<application
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package com.carriez.flutter_hbb
|
||||
|
||||
/**
|
||||
* Handle remote input and dispatch android gesture
|
||||
*
|
||||
* Inspired by [droidVNC-NG] https://github.com/bk138/droidVNC-NG
|
||||
*/
|
||||
|
||||
import android.accessibilityservice.AccessibilityService
|
||||
import android.accessibilityservice.GestureDescription
|
||||
import android.content.Context
|
||||
@@ -32,12 +38,6 @@ class InputService : AccessibilityService() {
|
||||
get() = ctx != null
|
||||
}
|
||||
|
||||
private external fun init(ctx: Context)
|
||||
|
||||
init {
|
||||
System.loadLibrary("rustdesk")
|
||||
}
|
||||
|
||||
private val logTag = "input service"
|
||||
private var leftIsDown = false
|
||||
private var touchPath = Path()
|
||||
@@ -50,9 +50,8 @@ class InputService : AccessibilityService() {
|
||||
private val wheelActionsQueue = LinkedList<GestureDescription>()
|
||||
private var isWheelActionsPolling = false
|
||||
|
||||
@Keep
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
fun rustMouseInput(mask: Int, _x: Int, _y: Int) {
|
||||
fun onMouseInput(mask: Int, _x: Int, _y: Int) {
|
||||
val x = if (_x < 0) {
|
||||
0
|
||||
} else {
|
||||
@@ -207,12 +206,15 @@ class InputService : AccessibilityService() {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onServiceConnected() {
|
||||
super.onServiceConnected()
|
||||
ctx = this
|
||||
Log.d(logTag, "onServiceConnected!")
|
||||
init(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
ctx = null
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onAccessibilityEvent(event: AccessibilityEvent?) {}
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
package com.carriez.flutter_hbb
|
||||
|
||||
/**
|
||||
* Handle events from flutter
|
||||
* Request MediaProjection permission
|
||||
*
|
||||
* Inspired by [droidVNC-NG] https://github.com/bk138/droidVNC-NG
|
||||
*/
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.carriez.flutter_hbb
|
||||
|
||||
/**
|
||||
* Capture screen,get video and audio,send to rust.
|
||||
* Handle notification
|
||||
* Dispatch notifications
|
||||
*
|
||||
* Inspired by [droidVNC-NG] https://github.com/bk138/droidVNC-NG
|
||||
*/
|
||||
package com.carriez.flutter_hbb
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
@@ -69,10 +72,32 @@ class MainService : Service() {
|
||||
System.loadLibrary("rustdesk")
|
||||
}
|
||||
|
||||
@Keep
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
fun rustMouseInput(mask: Int, x: Int, y: Int) {
|
||||
// turn on screen with LIFT_DOWN when screen off
|
||||
if (!powerManager.isInteractive && mask == LIFT_DOWN) {
|
||||
if (wakeLock.isHeld) {
|
||||
Log.d(logTag,"Turn on Screen, WakeLock release")
|
||||
wakeLock.release()
|
||||
}
|
||||
Log.d(logTag,"Turn on Screen")
|
||||
wakeLock.acquire(5000)
|
||||
} else {
|
||||
InputService.ctx?.onMouseInput(mask,x,y)
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
fun rustGetByName(name: String): String {
|
||||
return when (name) {
|
||||
"screen_size" -> "${SCREEN_INFO.width}:${SCREEN_INFO.height}"
|
||||
"screen_size" -> {
|
||||
JSONObject().apply {
|
||||
put("width",SCREEN_INFO.width)
|
||||
put("height",SCREEN_INFO.height)
|
||||
put("scale",SCREEN_INFO.scale)
|
||||
}.toString()
|
||||
}
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
@@ -130,6 +155,9 @@ class MainService : Service() {
|
||||
private var serviceLooper: Looper? = null
|
||||
private var serviceHandler: Handler? = null
|
||||
|
||||
private val powerManager: PowerManager by lazy { applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager }
|
||||
private val wakeLock: PowerManager.WakeLock by lazy { powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "rustdesk:wakelock")}
|
||||
|
||||
// jvm call rust
|
||||
private external fun init(ctx: Context)
|
||||
private external fun startServer()
|
||||
@@ -191,10 +219,6 @@ class MainService : Service() {
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
InputService.ctx?.disableSelf()
|
||||
}
|
||||
InputService.ctx = null
|
||||
checkMediaPermission()
|
||||
super.onDestroy()
|
||||
}
|
||||
@@ -383,10 +407,6 @@ class MainService : Service() {
|
||||
|
||||
mediaProjection = null
|
||||
checkMediaPermission()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
InputService.ctx?.disableSelf()
|
||||
}
|
||||
InputService.ctx = null
|
||||
stopForeground(true)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
$ANDROID_NDK/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-strip android/app/src/main/jniLibs/arm64-v8a/*
|
||||
flutter build apk --target-platform android-arm64 --release --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build appbundle --target-platform android-arm64 --release --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build apk --target-platform android-arm64,android-arm --release --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build apk ---split-per-abi --target-platform android-arm64,android-arm --release --obfuscate --split-debug-info ./split-debug-info
|
||||
flutter build appbundle --target-platform android-arm64,android-arm --release --obfuscate --split-debug-info ./split-debug-info
|
||||
|
||||
# build in linux
|
||||
# $ANDROID_NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-strip android/app/src/main/jniLibs/arm64-v8a/*
|
||||
|
||||
125
flutter/build_android_deps.sh
Executable file
125
flutter/build_android_deps.sh
Executable file
@@ -0,0 +1,125 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build libyuv / opus / libvpx / oboe for Android
|
||||
# Required:
|
||||
# 1. set VCPKG_ROOT / ANDROID_NDK path environment variables
|
||||
# 2. vcpkg initialized
|
||||
# 3. ndk, version: 22 (if ndk < 22 you need to change LD as `export LD=$TOOLCHAIN/bin/$NDK_LLVM_TARGET-ld`)
|
||||
|
||||
if [ -z "$ANDROID_NDK" ]; then
|
||||
echo "Failed! Please set ANDROID_NDK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$VCPKG_ROOT" ]; then
|
||||
echo "Failed! Please set VCPKG_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
API_LEVEL="21"
|
||||
|
||||
# NDK llvm toolchain
|
||||
HOST_TAG="linux-x86_64" # current platform, set as `ls $ANDROID_NDK/toolchains/llvm/prebuilt/`
|
||||
TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST_TAG
|
||||
|
||||
function build {
|
||||
ANDROID_ABI=$1
|
||||
VCPKG_TARGET=$2
|
||||
NDK_LLVM_TARGET=$3
|
||||
LIBVPX_TARGET=$4
|
||||
|
||||
PREFIX=$VCPKG_ROOT/installed/$VCPKG_TARGET/
|
||||
|
||||
# 1
|
||||
echo "*** [$ANDROID_ABI][Start] Build opus / libyuv from vcpkg"
|
||||
export ANDROID_NDK_HOME=$ANDROID_NDK
|
||||
pushd $VCPKG_ROOT
|
||||
$VCPKG_ROOT/vcpkg install opus --triplet $VCPKG_TARGET
|
||||
$VCPKG_ROOT/vcpkg install libyuv --triplet $VCPKG_TARGET
|
||||
popd
|
||||
echo "*** [$ANDROID_ABI][Finished] Build opus / libyuv from vcpkg"
|
||||
|
||||
# 2
|
||||
echo "*** [$ANDROID_ABI][Start] Build libvpx"
|
||||
pushd build/libvpx
|
||||
export AR=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-ar
|
||||
export AS=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-as
|
||||
export LD=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-ld.gold # if ndk < 22, use aarch64-linux-android-ld
|
||||
export RANLIB=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-ranlib
|
||||
export STRIP=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-strip
|
||||
|
||||
if [ $NDK_LLVM_TARGET == "arm-linux-androideabi" ]
|
||||
then
|
||||
export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi${API_LEVEL}-clang
|
||||
export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi${API_LEVEL}-clang++
|
||||
else
|
||||
export CC=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}${API_LEVEL}-clang
|
||||
export CXX=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}${API_LEVEL}-clang++
|
||||
fi
|
||||
make clean
|
||||
./configure --target=$LIBVPX_TARGET \
|
||||
--enable-pic --disable-vp8 \
|
||||
--disable-webm-io \
|
||||
--disable-unit-tests \
|
||||
--disable-examples \
|
||||
--disable-libyuv \
|
||||
--disable-postproc \
|
||||
--disable-vp8 \
|
||||
--disable-tools \
|
||||
--disable-docs \
|
||||
--prefix=$PREFIX
|
||||
make -j5
|
||||
make install
|
||||
|
||||
popd
|
||||
echo "*** [$ANDROID_ABI][Finished] Build libvpx"
|
||||
|
||||
# 3
|
||||
echo "*** [$ANDROID_ABI][Start] Build oboe"
|
||||
pushd build/oboe
|
||||
make clean
|
||||
cmake -DBUILD_SHARED_LIBS=true \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DANDROID_TOOLCHAIN=clang \
|
||||
-DANDROID_STL=c++_shared \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DANDROID_ABI=$ANDROID_ABI \
|
||||
-DANDROID_PLATFORM=android-$API_LEVEL
|
||||
make -j5
|
||||
make install
|
||||
mv $PREFIX/lib/$ANDROID_ABI/liboboe.a $PREFIX/lib/
|
||||
popd
|
||||
echo "*** [$ANDROID_ABI][Finished] Build oboe"
|
||||
|
||||
echo "*** [$ANDROID_ABI][All Finished]"
|
||||
}
|
||||
|
||||
git clone -b v1.11.0 --depth=1 https://github.com/webmproject/libvpx.git build/libvpx
|
||||
git clone -b 1.6.1 --depth=1 https://github.com/google/oboe build/oboe
|
||||
patch -N -d build/oboe -p1 < ../src/oboe.patch
|
||||
|
||||
# VCPKG_TARGET ANDROID_ABI
|
||||
# arm64-android arm64-v8a
|
||||
# arm-android armeabi-v7a
|
||||
# x64-android x86_64
|
||||
# x86-android x86
|
||||
|
||||
# NDK_LLVM_TARGET
|
||||
# aarch64-linux-android
|
||||
# arm-linux-androideabi
|
||||
# x86_64-linux-android
|
||||
# i686-linux-android
|
||||
|
||||
# LIBVPX_TARGET :
|
||||
# arm64-android-gcc
|
||||
# armv7-android-gcc
|
||||
# x86_64-android-gcc
|
||||
# x86-android-gcc
|
||||
|
||||
# args: ANDROID_ABI VCPKG_TARGET NDK_LLVM_TARGET LIBVPX_TARGET
|
||||
build arm64-v8a arm64-android aarch64-linux-android arm64-android-gcc
|
||||
build armeabi-v7a arm-android arm-linux-androideabi armv7-android-gcc
|
||||
|
||||
# rm -rf build/libvpx
|
||||
# rm -rf build/oboe
|
||||
@@ -236,7 +236,7 @@ class AccessibilityListener extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
onPointerUp: (evt) {
|
||||
if (evt.size == 1 && GestureBinding.instance != null) {
|
||||
if (evt.size == 1) {
|
||||
GestureBinding.instance.handlePointerEvent(PointerUpEvent(
|
||||
pointer: evt.pointer + offset,
|
||||
size: 0.1,
|
||||
@@ -246,7 +246,7 @@ class AccessibilityListener extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
onPointerMove: (evt) {
|
||||
if (evt.size == 1 && GestureBinding.instance != null) {
|
||||
if (evt.size == 1) {
|
||||
GestureBinding.instance.handlePointerEvent(PointerMoveEvent(
|
||||
pointer: evt.pointer + offset,
|
||||
size: 0.1,
|
||||
|
||||
@@ -113,8 +113,8 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
: InkWell(
|
||||
onTap: () async {
|
||||
final url = _updateUrl + '.apk';
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
@@ -275,7 +275,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
? []
|
||||
: [
|
||||
PopupMenuItem<String>(
|
||||
child: Text(translate('File transfer')), value: 'file')
|
||||
child: Text(translate('Transfer File')), value: 'file')
|
||||
]),
|
||||
elevation: 8,
|
||||
);
|
||||
|
||||
@@ -35,6 +35,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||
String _value = '';
|
||||
double _scale = 1;
|
||||
double _mouseScrollIntegral = 0; // mouse scroll speed controller
|
||||
Orientation? _currentOrientation;
|
||||
|
||||
var _more = true;
|
||||
var _fn = false;
|
||||
@@ -127,7 +128,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||
common < oldValue.length &&
|
||||
common < newValue.length &&
|
||||
newValue[common] == oldValue[common];
|
||||
++common);
|
||||
++common) {}
|
||||
for (i = 0; i < oldValue.length - common; ++i) {
|
||||
gFFI.inputKey('VK_BACK');
|
||||
}
|
||||
@@ -260,12 +261,22 @@ class _RemotePageState extends State<RemotePage> {
|
||||
color: Colors.black,
|
||||
child: isWebDesktop
|
||||
? getBodyForDesktopWithListener(keyboard)
|
||||
: SafeArea(
|
||||
child: Container(
|
||||
: SafeArea(child:
|
||||
OrientationBuilder(builder: (ctx, orientation) {
|
||||
if (_currentOrientation != orientation) {
|
||||
debugPrint("on orientation changed");
|
||||
Timer(Duration(milliseconds: 200), () {
|
||||
resetMobileActionsOverlay();
|
||||
_currentOrientation = orientation;
|
||||
FFI.canvasModel.updateViewStyle();
|
||||
});
|
||||
}
|
||||
return Container(
|
||||
color: MyTheme.canvasColor,
|
||||
child: _isPhysicalMouse
|
||||
? getBodyForMobile()
|
||||
: getBodyForMobileWithGesture())));
|
||||
: getBodyForMobileWithGesture());
|
||||
})));
|
||||
})
|
||||
],
|
||||
))),
|
||||
|
||||
@@ -204,7 +204,7 @@ class _PermissionCheckerState extends State<PermissionChecker> {
|
||||
serverModel.toggleService),
|
||||
PermissionRow(translate("Input Control"), serverModel.inputOk,
|
||||
serverModel.toggleInput),
|
||||
PermissionRow(translate("File Transfer"), serverModel.fileOk,
|
||||
PermissionRow(translate("Transfer File"), serverModel.fileOk,
|
||||
serverModel.toggleFile),
|
||||
hasAudioPermission
|
||||
? PermissionRow(translate("Audio Capture"), serverModel.audioOk,
|
||||
|
||||
@@ -70,8 +70,8 @@ class _SettingsState extends State<SettingsPage> {
|
||||
tiles: [
|
||||
SettingsTile.navigation(
|
||||
onPressed: (context) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
},
|
||||
title: Text(translate("Version: ") + version),
|
||||
@@ -107,8 +107,8 @@ void showAbout() {
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
const url = 'https://rustdesk.com/';
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
@@ -151,7 +151,7 @@ fetch('http://localhost:21114/api/login', {
|
||||
'uuid': gFFI.getByName('uuid')
|
||||
};
|
||||
try {
|
||||
final response = await http.post(Uri.parse('${url}/api/login'),
|
||||
final response = await http.post(Uri.parse('$url/api/login'),
|
||||
headers: {"Content-Type": "application/json"}, body: json.encode(body));
|
||||
return parseResp(response.body);
|
||||
} catch (e) {
|
||||
@@ -189,7 +189,7 @@ void refreshCurrentUser() async {
|
||||
'uuid': gFFI.getByName('uuid')
|
||||
};
|
||||
try {
|
||||
final response = await http.post(Uri.parse('${url}/api/currentUser'),
|
||||
final response = await http.post(Uri.parse('$url/api/currentUser'),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer $token"
|
||||
@@ -215,7 +215,7 @@ void logout() async {
|
||||
'uuid': gFFI.getByName('uuid')
|
||||
};
|
||||
try {
|
||||
await http.post(Uri.parse('${url}/api/logout'),
|
||||
await http.post(Uri.parse('$url/api/logout'),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer $token"
|
||||
@@ -245,7 +245,7 @@ String getUrl() {
|
||||
url = 'http://${tmp[0]}:$port';
|
||||
}
|
||||
} else {
|
||||
url = 'http://${url}:21114';
|
||||
url = 'http://$url:21114';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,10 +594,7 @@ class _TapTracker {
|
||||
required this.entry,
|
||||
required Duration doubleTapMinTime,
|
||||
required this.gestureSettings,
|
||||
}) : assert(doubleTapMinTime != null),
|
||||
assert(event != null),
|
||||
assert(event.buttons != null),
|
||||
pointer = event.pointer,
|
||||
}) : pointer = event.pointer,
|
||||
_initialGlobalPosition = event.position,
|
||||
initialButtons = event.buttons,
|
||||
_doubleTapMinTimeCountdown =
|
||||
@@ -643,7 +640,7 @@ class _TapTracker {
|
||||
/// CountdownZoned tracks whether the specified duration has elapsed since
|
||||
/// creation, honoring [Zone].
|
||||
class _CountdownZoned {
|
||||
_CountdownZoned({required Duration duration}) : assert(duration != null) {
|
||||
_CountdownZoned({required Duration duration}) {
|
||||
Timer(duration, _onTimeout);
|
||||
}
|
||||
|
||||
|
||||
@@ -228,6 +228,12 @@ class DraggableMobileActions extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
resetMobileActionsOverlay() {
|
||||
if (mobileActionsOverlayEntry == null) return;
|
||||
hideMobileActionsOverlay();
|
||||
showMobileActionsOverlay();
|
||||
}
|
||||
|
||||
showMobileActionsOverlay() {
|
||||
if (mobileActionsOverlayEntry != null) return;
|
||||
if (globalKey.currentContext == null ||
|
||||
|
||||
@@ -621,15 +621,7 @@ class FileFetcher {
|
||||
|
||||
tryCompleteTask(String? msg, String? isLocalStr) {
|
||||
if (msg == null || isLocalStr == null) return;
|
||||
late final isLocal;
|
||||
late final tasks;
|
||||
if (isLocalStr == "true") {
|
||||
isLocal = true;
|
||||
} else if (isLocalStr == "false") {
|
||||
isLocal = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final fd = FileDirectory.fromJson(jsonDecode(msg));
|
||||
if (fd.id > 0) {
|
||||
|
||||
@@ -229,6 +229,7 @@ class FfiModel with ChangeNotifier {
|
||||
}
|
||||
|
||||
void handleSwitchDisplay(Map<String, dynamic> evt) {
|
||||
final oldOrientation = _display.width > _display.height;
|
||||
var old = _pi.currentDisplay;
|
||||
_pi.currentDisplay = int.parse(evt['display']);
|
||||
_display.x = double.parse(evt['x']);
|
||||
@@ -237,6 +238,11 @@ class FfiModel with ChangeNotifier {
|
||||
_display.height = int.parse(evt['height']);
|
||||
if (old != _pi.currentDisplay)
|
||||
parent.target?.cursorModel.updateDisplayOrigin(_display.x, _display.y);
|
||||
|
||||
// remote is mobile, and orientation changed
|
||||
if ((_display.width > _display.height) != oldOrientation) {
|
||||
gFFI.canvasModel.updateViewStyle();
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ class ServerModel with ChangeNotifier {
|
||||
* 2. check config
|
||||
* audio true by default (if permission on) (false default < Android 10)
|
||||
* file true by default (if permission on)
|
||||
* input false by default (it need turning on manually everytime)
|
||||
*/
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:js';
|
||||
|
||||
2
flutter/ndk_arm.sh
Executable file
2
flutter/ndk_arm.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
cargo ndk --platform 21 --target armv7-linux-androideabi build --release
|
||||
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# 1.1.9-1 works for android, but for ios it becomes 1.1.91, need to set it to 1.1.9-a.1 for iOS, will get 1.1.9.1, but iOS store not allow 4 numbers
|
||||
version: 1.1.10+27
|
||||
version: 1.1.10-1+28
|
||||
|
||||
environment:
|
||||
sdk: ">=2.16.1"
|
||||
|
||||
Reference in New Issue
Block a user