feat: 增加防丢失页面
This commit is contained in:
parent
0474f3c9d9
commit
26f6c10557
@ -37,6 +37,17 @@
|
||||
|
||||
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
|
||||
<queries>
|
||||
<!-- Twitter/X -->
|
||||
<package android:name="com.twitter.android" />
|
||||
<package android:name="com.x.android" />
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<data android:scheme="twitter" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<!-- 如果 targetSdkVersion >= 33 -->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<application
|
||||
|
||||
BIN
assets/images/followX.png
Normal file
BIN
assets/images/followX.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
7
assets/images/icon-6.svg
Normal file
7
assets/images/icon-6.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.6 4.53333H11.7867V1.81333H9.06665V0H11.7867C12.2676 0 12.7288 0.191047 13.0689 0.531113C13.4089 0.871179 13.6 1.33241 13.6 1.81333V4.53333Z" fill="black"/>
|
||||
<path d="M1.81333 4.53333H0V1.81333C0 1.33241 0.191047 0.871179 0.531113 0.531113C0.871179 0.191047 1.33241 0 1.81333 0H4.53333V1.81333H1.81333V4.53333Z" fill="black"/>
|
||||
<path d="M4.53333 13.6H1.81333C1.33241 13.6 0.871179 13.4089 0.531113 13.0689C0.191047 12.7288 0 12.2676 0 11.7867V9.06665H1.81333V11.7867H4.53333V13.6Z" fill="black"/>
|
||||
<path d="M11.7867 13.6H9.06665V11.7867H11.7867V9.06665H13.6V11.7867C13.6 12.2676 13.4089 12.7288 13.0689 13.0689C12.7288 13.4089 12.2676 13.6 11.7867 13.6Z" fill="black"/>
|
||||
<path d="M6.79996 3.62665C6.07857 3.62665 5.38672 3.91322 4.87663 4.42332C4.36653 4.93342 4.07996 5.62526 4.07996 6.34665C4.07996 8.15998 6.07009 9.81238 6.79996 10.88C7.52982 9.81238 9.51996 8.15998 9.51996 6.34665C9.51996 5.62526 9.23339 4.93342 8.72329 4.42332C8.21319 3.91322 7.52134 3.62665 6.79996 3.62665ZM6.79996 7.25331C6.62063 7.25331 6.44534 7.20014 6.29624 7.10051C6.14714 7.00089 6.03093 6.85929 5.96231 6.69361C5.89368 6.52794 5.87573 6.34564 5.91071 6.16977C5.94569 5.99389 6.03205 5.83234 6.15885 5.70554C6.28565 5.57874 6.4472 5.49239 6.62307 5.4574C6.79895 5.42242 6.98125 5.44037 7.14692 5.509C7.31259 5.57762 7.4542 5.69383 7.55382 5.84293C7.65345 5.99203 7.70662 6.16733 7.70662 6.34665C7.70662 6.58711 7.6111 6.81772 7.44107 6.98776C7.27103 7.15779 7.04042 7.25331 6.79996 7.25331Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -58,6 +58,11 @@
|
||||
<string>需要相册权限以支持图片上传功能</string>
|
||||
<key>SERVICE_IDENTIFIER</key>
|
||||
<string>$(SERVICE_IDENTIFIER)</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>twitter</string>
|
||||
<string>x-scheme-handler</string>
|
||||
</array>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
import 'package:get/get.dart';
|
||||
import '../controllers/hi_anti_lost_controller.dart';
|
||||
|
||||
class HIAntiLostBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<HIAntiLostController>(
|
||||
() => HIAntiLostController(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:gal/gal.dart';
|
||||
import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class HIAntiLostController extends GetxController {
|
||||
final GlobalKey repaintKey = GlobalKey();
|
||||
|
||||
Future<void> saveImage() async {
|
||||
KRCommonUtil.kr_showLoading(message: "正在保存...");
|
||||
try {
|
||||
// Check permission
|
||||
final hasAccess = await Gal.hasAccess();
|
||||
if (!hasAccess) {
|
||||
await Gal.requestAccess();
|
||||
}
|
||||
|
||||
// Capture image
|
||||
RenderRepaintBoundary? boundary =
|
||||
repaintKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
|
||||
|
||||
if (boundary == null) {
|
||||
throw Exception("Cannot find boundary");
|
||||
}
|
||||
|
||||
// Check if the boundary needs layout (sometimes Offstage needs a frame)
|
||||
if (boundary.debugNeedsPaint) {
|
||||
await Future.delayed(const Duration(milliseconds: 20));
|
||||
boundary = repaintKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
|
||||
}
|
||||
|
||||
ui.Image image = await boundary!.toImage(pixelRatio: 3.0);
|
||||
ByteData? byteData =
|
||||
await image.toByteData(format: ui.ImageByteFormat.png);
|
||||
|
||||
if (byteData != null) {
|
||||
final Uint8List pngBytes = byteData.buffer.asUint8List();
|
||||
await Gal.putImageBytes(pngBytes);
|
||||
KRCommonUtil.kr_showToast("保存成功");
|
||||
} else {
|
||||
KRCommonUtil.kr_showToast("生成图片失败");
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("Save image error: $e");
|
||||
if (e is GalException) {
|
||||
KRCommonUtil.kr_showToast("保存失败: No Permission");
|
||||
} else {
|
||||
KRCommonUtil.kr_showToast("保存失败");
|
||||
}
|
||||
} finally {
|
||||
KRCommonUtil.kr_hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
void openTwitter() async {
|
||||
// Try Deep Link first
|
||||
final Uri appUrl = Uri.parse('twitter://user?screen_name=hifasttech');
|
||||
final Uri webUrl = Uri.parse('https://x.com/hifasttech');
|
||||
|
||||
try {
|
||||
if (await canLaunchUrl(appUrl)) {
|
||||
await launchUrl(appUrl);
|
||||
} else {
|
||||
// Fallback to web
|
||||
if (!await launchUrl(webUrl, mode: LaunchMode.externalApplication)) {
|
||||
KRCommonUtil.kr_showToast("无法打开链接");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("Open Twitter error: $e");
|
||||
// Fallback to web if anything goes wrong
|
||||
try {
|
||||
if (!await launchUrl(webUrl, mode: LaunchMode.externalApplication)) {
|
||||
KRCommonUtil.kr_showToast("无法打开链接");
|
||||
}
|
||||
} catch (e) {
|
||||
KRCommonUtil.kr_showToast("无法打开链接");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
152
lib/app/modules/hi_anti_lost/views/hi_anti_lost_view.dart
Normal file
152
lib/app/modules/hi_anti_lost/views/hi_anti_lost_view.dart
Normal file
@ -0,0 +1,152 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/hi_base_scaffold.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_anti_lost/controllers/hi_anti_lost_controller.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_anti_lost/widgets/hi_anti_lost_share_card.dart';
|
||||
|
||||
class HIAntiLostView extends GetView<HIAntiLostController> {
|
||||
const HIAntiLostView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return HIBaseScaffold(
|
||||
showBack: true,
|
||||
title: null,
|
||||
topContentAreaHeight: 0,
|
||||
backgroundColor: Colors.black, // Dark background
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
// 1. Visible Content
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 60.h),
|
||||
// Card Container
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.symmetric(horizontal: 40.w),
|
||||
padding: EdgeInsets.symmetric(vertical: 16.w, horizontal: 0.w),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.circular(25.r),
|
||||
border: Border.all(
|
||||
color: Theme.of(context).primaryColor, width: 4),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'保存二维码,防止失联',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontSize: 24.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 25.h),
|
||||
Text(
|
||||
'建议保存Hi快VPN防丢二维码到相册\n永久保障您的互联网自由',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontSize: 14.sp,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
// QR Code
|
||||
LayoutBuilder(builder: (context, constraints) {
|
||||
// Use a reasonable size for the QR code
|
||||
return Container(
|
||||
width: 124.w,
|
||||
height: 124.w,
|
||||
child: QrImageView(
|
||||
data:
|
||||
'https://github.com/hi-vpn/hi-client', // Replace with real URL
|
||||
version: QrVersions.auto,
|
||||
backgroundColor: Colors.transparent,
|
||||
eyeStyle: QrEyeStyle(
|
||||
eyeShape: QrEyeShape.square,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
dataModuleStyle: QrDataModuleStyle(
|
||||
dataModuleShape: QrDataModuleShape.square,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
// center image
|
||||
embeddedImage:
|
||||
const AssetImage('assets/images/kr-logo.png'),
|
||||
embeddedImageStyle: QrEmbeddedImageStyle(
|
||||
size: Size(36.w, 36.w),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 30.h),
|
||||
|
||||
// Save Button
|
||||
GestureDetector(
|
||||
onTap: controller.saveImage,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.symmetric(horizontal: 40.w),
|
||||
height: 44.h,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).primaryColor,
|
||||
borderRadius: BorderRadius.circular(22.h),
|
||||
),
|
||||
child: Text(
|
||||
'保存到本地',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 60.h),
|
||||
],
|
||||
),
|
||||
|
||||
// 2. Bottom Button (Follow us on X)
|
||||
Positioned(
|
||||
bottom: 40.h,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Center(
|
||||
child: GestureDetector(
|
||||
onTap: controller.openTwitter,
|
||||
child: KrLocalImage(
|
||||
imageName: 'followX',
|
||||
width: 140,
|
||||
height: 30,
|
||||
imageType: ImageType
|
||||
.png, // Assuming it is png as user said followX.png
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 3. Invisible Share Card for Generation
|
||||
Positioned(
|
||||
left: 10000,
|
||||
child: RepaintBoundary(
|
||||
key: controller.repaintKey,
|
||||
child: const HIAntiLostShareCard(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
|
||||
|
||||
class HIAntiLostShareCard extends StatelessWidget {
|
||||
const HIAntiLostShareCard({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Fixed width for the generated image, independent of screen size
|
||||
final double cardWidth = 375.0;
|
||||
final double cardHeight = 600.0; // Approx height
|
||||
|
||||
return Container(
|
||||
width: cardWidth,
|
||||
// minimal height or let it expand
|
||||
padding: EdgeInsets.all(20),
|
||||
color: Colors.black, // Dark background
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 40),
|
||||
// Title
|
||||
Text(
|
||||
'保存二维码,防止失联',
|
||||
style: TextStyle(
|
||||
color: const Color(0xFFCCFF00),
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'AlibabaPuHuiTi-Medium',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
// Description
|
||||
Text(
|
||||
'建议保存Hi快VPN防丢二维码到相册\n永久保障您的互联网自由',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: const Color(0xFFCCFF00),
|
||||
fontSize: 14,
|
||||
height: 1.5,
|
||||
fontFamily: 'AlibabaPuHuiTi-Regular',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40),
|
||||
// QR Code Card
|
||||
Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black,
|
||||
border: Border.all(color: const Color(0xFFCCFF00), width: 3),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: QrImageView(
|
||||
data: 'https://github.com/hi-vpn/hi-client', // Replace with actual URL
|
||||
version: QrVersions.auto,
|
||||
size: 200,
|
||||
backgroundColor: Colors.transparent,
|
||||
eyeStyle: const QrEyeStyle(
|
||||
eyeShape: QrEyeShape.square,
|
||||
color: Color(0xFFCCFF00),
|
||||
),
|
||||
dataModuleStyle: const QrDataModuleStyle(
|
||||
dataModuleShape: QrDataModuleShape.square,
|
||||
color: Color(0xFFCCFF00),
|
||||
),
|
||||
embeddedImage: const AssetImage('assets/images/kr-logo.png'),
|
||||
embeddedImageStyle: const QrEmbeddedImageStyle(
|
||||
size: Size(50, 50),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40),
|
||||
// Footer branding
|
||||
Text(
|
||||
'HiVPN',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
fontSize: 12,
|
||||
letterSpacing: 2,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -51,6 +51,11 @@ class HIMenuView extends GetView<HIMenuController> implements HasSwipeConfig {
|
||||
title: '邀请好友',
|
||||
route: Routes.KR_INVITE,
|
||||
),
|
||||
// const MenuItem(
|
||||
// iconName: 'icon-6',
|
||||
// title: '软件防丢',
|
||||
// route: Routes.HI_ANTI_LOST,
|
||||
// ),
|
||||
MenuItem(
|
||||
iconName: 'icon-5',
|
||||
title: '在线客服',
|
||||
|
||||
@ -7,6 +7,8 @@ import 'package:kaer_with_panels/app/modules/hi_node_list/bindings/hi_node_list_
|
||||
import 'package:kaer_with_panels/app/modules/hi_node_list/views/hi_page_node_view.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_user_info/bindings/hi_user_info_binding.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_user_info/views/hi_user_info_view.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_anti_lost/bindings/hi_anti_lost_binding.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_anti_lost/views/hi_anti_lost_view.dart';
|
||||
|
||||
import '../modules/kr_crisp_chat/bindings/kr_crisp_binding.dart';
|
||||
import '../modules/kr_crisp_chat/views/kr_crisp_view.dart';
|
||||
@ -130,5 +132,11 @@ class AppPages {
|
||||
popGesture: false,
|
||||
arguments: {'showSubscriptionButton': true}, // 显示购买按钮
|
||||
),
|
||||
GetPage(
|
||||
name: _Paths.HI_ANTI_LOST,
|
||||
page: () => SwipeWrapper.detect(() => const HIAntiLostView()),
|
||||
binding: HIAntiLostBinding(),
|
||||
popGesture: false,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ abstract class Routes {
|
||||
static const HI_NODE_LIST = _Paths.HI_NODE_LIST;
|
||||
static const HI_HELP = _Paths.HI_HELP;
|
||||
static const HI_USER_INFO = _Paths.HI_USER_INFO;
|
||||
static const HI_ANTI_LOST = _Paths.HI_ANTI_LOST;
|
||||
}
|
||||
|
||||
abstract class _Paths {
|
||||
@ -48,4 +49,5 @@ abstract class _Paths {
|
||||
static const HI_NODE_LIST = '/hi_node_list';
|
||||
static const HI_HELP = '/hi_help';
|
||||
static const HI_USER_INFO = '/hi-user-info';
|
||||
static const HI_ANTI_LOST = '/hi-anti-lost';
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import connectivity_plus
|
||||
import device_info_plus
|
||||
import flutter_inappwebview_macos
|
||||
import flutter_udid
|
||||
import gal
|
||||
import in_app_purchase_storekit
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
@ -23,6 +24,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
||||
GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin"))
|
||||
InAppPurchasePlugin.register(with: registry.registrar(forPlugin: "InAppPurchasePlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
|
||||
@ -680,6 +680,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
gal:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: gal
|
||||
sha256: "969598f986789127fd407a750413249e1352116d4c2be66e81837ffeeaafdfee"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
get:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@ -112,6 +112,7 @@ dependencies:
|
||||
in_app_purchase: ^3.2.3
|
||||
in_app_purchase_storekit: ^0.4.2
|
||||
intl: ^0.20.2
|
||||
gal: ^2.3.2
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
||||
#include <gal/gal_plugin_c_api.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <protocol_handler_windows/protocol_handler_windows_plugin_c_api.h>
|
||||
#include <screen_retriever_windows/screen_retriever_windows_plugin_c_api.h>
|
||||
@ -24,6 +25,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi"));
|
||||
FlutterUdidPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
|
||||
GalPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("GalPluginCApi"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
ProtocolHandlerWindowsPluginCApiRegisterWithRegistrar(
|
||||
|
||||
@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
connectivity_plus
|
||||
flutter_inappwebview_windows
|
||||
flutter_udid
|
||||
gal
|
||||
permission_handler_windows
|
||||
protocol_handler_windows
|
||||
screen_retriever_windows
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user