Add support for prevent screen capture

This commit is contained in:
2023-09-22 17:28:33 +08:00
parent 50ff4b3fdd
commit 286e2fbb5b
7 changed files with 102 additions and 2 deletions

View File

@@ -22,6 +22,7 @@ import 'config/shared_preferences.dart';
import 'config/windows.dart';
import 'main.dart';
import 'platform/clipboard.dart';
import 'platform/display.dart';
import 'platform/path.dart';
import 'platform/set_title.dart';
import 'tags.dart';
@@ -121,6 +122,7 @@ EHApi get api {
final AuthInfo auth = AuthInfo();
final Clipboard platformClipboard = Clipboard();
final Display platformDisplay = Display();
final Path platformPath = Path();
final TagsInfo tags = TagsInfo();
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey =

View File

@@ -85,5 +85,6 @@
"maxZipFilenameLength": "Maximum length of filenames in Zip files",
"downloadComplete": "Download completed.",
"downloadZipFailed": "Failed to download ZIP file.",
"rating": "Rating"
"rating": "Rating",
"preventScreenCapture": "Prevent screen capture"
}

View File

@@ -85,5 +85,6 @@
"maxZipFilenameLength": "Zip文件中文件名的最大长度",
"downloadComplete": "下载完毕。",
"downloadZipFailed": "Zip文件下载失败。",
"rating": "评分"
"rating": "评分",
"preventScreenCapture": "防止截屏"
}

View File

@@ -151,6 +151,9 @@ void main() async {
await windowManager.ensureInitialized();
}
await initLogger();
if (prefs.getBool("preventScreenCapture") ?? false) {
await platformDisplay.enableProtect();
}
GoRouter.optionURLReflectsImperativeAPIs = true;
runApp(const MainApp());
}

31
lib/platform/display.dart Normal file
View File

@@ -0,0 +1,31 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
final _log = Logger("platformDisplay");
class Display {
static const platform =
MethodChannel("lifegpc.eh_downloader_flutter/display");
Future<bool> disableProtect() async {
if (kIsWeb) return true;
try {
await platform.invokeMethod<void>("disableProtect");
return true;
} catch (e) {
_log.warning("Failed to disable protect", e);
return false;
}
}
Future<bool> enableProtect() async {
if (kIsWeb) return true;
try {
await platform.invokeMethod<void>("enableProtect");
return true;
} catch (e) {
_log.warning("Failed to enable protect", e);
return false;
}
}
}

View File

@@ -19,11 +19,13 @@ class SettingsPage extends StatefulWidget {
class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
bool _oriDisplayAd = false;
Lang _oriLang = Lang.system;
bool _oriPreventScreenCapture = false;
bool _oriShowNsfw = false;
bool _oriShowTranslatedTag = false;
bool _oriUseTitleJpn = false;
bool _displayAd = false;
Lang _lang = Lang.system;
bool _preventScreenCapture = false;
bool _showNsfw = false;
bool _showTranslatedTag = false;
bool _useTitleJpn = false;
@@ -71,6 +73,14 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
_oriShowTranslatedTag = false;
_showTranslatedTag = false;
}
try {
_oriPreventScreenCapture = prefs.getBool("preventScreenCapture") ?? false;
_preventScreenCapture = _oriPreventScreenCapture;
} catch (e) {
_log.warning("Failed to get preventScreenCapture:", e);
_oriPreventScreenCapture = false;
_preventScreenCapture = false;
}
}
void fallback(BuildContext context) {
@@ -87,6 +97,7 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
_showNsfw = false;
_displayAd = false;
_showTranslatedTag = _oriLang.toLocale().languageCode == "zh";
_preventScreenCapture = false;
});
}
@@ -130,6 +141,23 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
_oriShowTranslatedTag = _showTranslatedTag;
}
}
if (_oriPreventScreenCapture != _preventScreenCapture) {
if (!await prefs.setBool("preventScreenCapture", _preventScreenCapture)) {
re = false;
_log.warning("Failed to save preventScreenCapture.");
} else {
_oriPreventScreenCapture = _preventScreenCapture;
}
if (_preventScreenCapture) {
if (!await platformDisplay.enableProtect()) {
_log.warning("Failed to enable protect.");
}
} else {
if (!await platformDisplay.disableProtect()) {
_log.warning("Failed to disable protect.");
}
}
}
return re;
}
@@ -250,6 +278,21 @@ class _SettingsPage extends State<SettingsPage> with ThemeModeWidget {
.showTranslatedTag),
),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 8),
child: CheckboxMenuButton(
value: _preventScreenCapture,
onChanged: (bool? value) {
if (value != null) {
setState(() {
_preventScreenCapture = value;
});
}
},
child: Text(AppLocalizations.of(context)!
.preventScreenCapture),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

View File

@@ -224,6 +224,25 @@ bool FlutterWindow::OnCreate() {
result->NotImplemented();
}
});
flutter::MethodChannel<> display(flutter_controller_->engine()->messenger(), "lifegpc.eh_downloader_flutter/display",
&flutter::StandardMethodCodec::GetInstance());
display.SetMethodCallHandler([&](const flutter::MethodCall<>& call, std::unique_ptr<flutter::MethodResult<>> result) {
if (call.method_name() == "enableProtect") {
if (!SetWindowDisplayAffinity(Win32Window::GetHandle(), WDA_EXCLUDEFROMCAPTURE)) {
result->Error("ERROR", "Failed to enable protect.");
return;
}
result->Success();
} else if (call.method_name() == "disableProtect") {
if (!SetWindowDisplayAffinity(Win32Window::GetHandle(), WDA_NONE)) {
result->Error("ERROR", "Failed to disable protect.");
return;
}
result->Success();
} else {
result->NotImplemented();
}
});
SetChildContent(flutter_controller_->view()->GetNativeWindow());