mirror of
https://github.com/Tencent/Hippy.git
synced 2026-10-22 08:46:09 +08:00
151 lines
5.3 KiB
Dart
151 lines
5.3 KiB
Dart
//
|
|
// Tencent is pleased to support the open source community by making
|
|
// Hippy available.
|
|
//
|
|
// Copyright (C) 2022 THL A29 Limited, a Tencent company.
|
|
// All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import 'dart:convert';
|
|
import 'dart:ui';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/scheduler.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:voltron_renderer/common/voltron_map.dart';
|
|
|
|
import '../common/promise.dart';
|
|
import '../common/voltron_array.dart';
|
|
import '../viewmodel/view_model.dart';
|
|
import 'log_util.dart';
|
|
|
|
/// devtools utils for screenshot
|
|
class DevtoolsUtil {
|
|
static const String kTag = "DevtoolsUtil";
|
|
static const String kGetScreenShot = "getScreenShot";
|
|
static const String kAddFrameCallback = "addFrameCallback";
|
|
static const String kRemoveFrameCallback = "removeFrameCallback";
|
|
static const String kGetLocationOnScreen = "getLocationOnScreen";
|
|
static const String kScreenShot = "screenShot";
|
|
static const String kScreenWidth = "width";
|
|
static const String kScreenHeight = "height";
|
|
static const String kScreenScale = "screenScale";
|
|
static const String kFrameCallbackId = "frameCallbackId";
|
|
static const String kXOnScreen = "xOnScreen";
|
|
static const String kYOnScreen = "yOnScreen";
|
|
static const String kViewWidth = "viewWidth";
|
|
static const String kViewHeight = "viewHeight";
|
|
static final Map _callbacks = <int, Promise>{};
|
|
|
|
static void onPostFrame(Duration timeStamp) {
|
|
_callbacks.forEach((key, value) {
|
|
value.resolve(VoltronMap());
|
|
});
|
|
if (_callbacks.isNotEmpty) {
|
|
SchedulerBinding.instance.addPostFrameCallback(onPostFrame);
|
|
}
|
|
}
|
|
|
|
static void addFrameCallback(RenderViewModel viewModel, VoltronArray array, Promise? promise) {
|
|
if (array.size() > 0) {
|
|
final paramsMap = array.get<VoltronMap>(0);
|
|
final callbackId = paramsMap?.get<int>(kFrameCallbackId);
|
|
_callbacks[callbackId] = promise;
|
|
SchedulerBinding.instance.addPostFrameCallback(onPostFrame);
|
|
}
|
|
}
|
|
|
|
static void removeFrameCallback(RenderViewModel viewModel, VoltronArray array, Promise? promise) {
|
|
if (array.size() > 0) {
|
|
final paramsMap = array.get<VoltronMap>(0);
|
|
final callbackId = paramsMap?.get<int>(kFrameCallbackId);
|
|
_callbacks.remove(callbackId);
|
|
}
|
|
}
|
|
|
|
static Future<void> getScreenShot(RenderViewModel viewModel, VoltronArray array, Promise? promise) async {
|
|
if (promise == null) {
|
|
return;
|
|
}
|
|
|
|
/// find rootKey
|
|
final globalKey = viewModel.context.getInstance(viewModel.rootId)?.rootKey;
|
|
final renderObject = globalKey?.currentContext?.findRenderObject();
|
|
if (globalKey == null) {
|
|
LogUtils.e(kTag, "getScreenShot globalKey == null");
|
|
return;
|
|
}
|
|
|
|
/// catch screenshot and encode base64
|
|
final boundary = renderObject as RenderRepaintBoundary;
|
|
final image = await boundary.toImage();
|
|
final byteData = await image.toByteData(format: ImageByteFormat.png);
|
|
final pngByteList = byteData?.buffer.asUint8List();
|
|
final base64Content = pngByteList == null ? "" : base64Encode(pngByteList);
|
|
|
|
/// promise callback
|
|
final resultMap = VoltronMap();
|
|
resultMap.push(kScreenShot, base64Content);
|
|
|
|
final mediaQuery = MediaQueryData.fromWindow(window);
|
|
final deviceWidth = mediaQuery.size.width.round();
|
|
final deviceHeight = mediaQuery.size.height.round();
|
|
resultMap.push(kScreenWidth, deviceWidth);
|
|
resultMap.push(kScreenHeight, deviceHeight);
|
|
resultMap.push(kScreenScale, 1.0);
|
|
promise.resolve(resultMap);
|
|
}
|
|
|
|
static Future<void> getLocationOnScreen(
|
|
RenderViewModel viewModel, VoltronArray array, Promise? promise) async {
|
|
if (promise == null) {
|
|
return;
|
|
}
|
|
var rootViewModel = viewModel.context.rootViewModelMap[viewModel.rootId];
|
|
var renderObject =
|
|
viewModel.currentContext?.findRenderObject() as RenderBox?;
|
|
var rootRenderObject =
|
|
rootViewModel?.currentContext?.findRenderObject() as RenderBox?;
|
|
var x = 0.0;
|
|
var y = 0.0;
|
|
var width = 0.0;
|
|
var height = 0.0;
|
|
if (renderObject == null || rootRenderObject == null) {
|
|
promise.reject("this view or root view is null");
|
|
} else {
|
|
var rootPosition = rootRenderObject.localToGlobal(Offset.zero);
|
|
var rootX = rootPosition.dx;
|
|
var rootY = rootPosition.dy;
|
|
|
|
var position = renderObject.localToGlobal(Offset.zero);
|
|
var size = renderObject.size;
|
|
|
|
x = position.dx - rootX;
|
|
y = position.dy - rootY;
|
|
width = size.width;
|
|
height = size.height;
|
|
}
|
|
|
|
final resultMap = VoltronMap();
|
|
resultMap.push(kXOnScreen, x.toInt());
|
|
resultMap.push(kYOnScreen, y.toInt());
|
|
resultMap.push(kViewWidth, width.toInt());
|
|
resultMap.push(kViewHeight, height.toInt());
|
|
promise.resolve(resultMap);
|
|
}
|
|
}
|