Magpie/src/Magpie.App/HomeViewModel.cpp
Xu 3ce10c2b74
支持触控输入 (#900)
* chore: 删除不需要的 const 说明符

* chore: 优化 Updater 分组

* feat: 添加 TouchHelper 项目

* feat: TouchHelper 需要 UIAccess 权限

* feat: 缩放配置页面改名为缩放模式页面

* feat: 添加自签名证书

* chore: 发布时为 TouchHelper 签名

* feat: 实现 TouchHelper 的功能

* feat: 高级选项移到主页

* feat: 实现安装证书

* perf: 安装证书前检查是否已经安装

* feat: 在单独的文件中记录 TouchHelper 的版本号

* feat: 实现 UI 功能 (1/2)

* feat: 实现 UI 功能 (2/2)

* fix: 修复有时更改触控支持选项时崩溃的问题

* feat: 给触控选项添加说明

* feat: 设置证书友好名称

* feat: 记录 MagSetInputTransform 调用结果

* docs: 添加触控支持说明

* docs: 添加英语文档

* docs: 更新编译文档

* refactor: 使用 ChangeWindowMessageFilterEx 替换 ChangeWindowMessageFilter

* UI: 优化触控支持 UI

* feat: 缩放前自动修复触控支持

* docs: 更新触控支持文档

* feat: 管理员身份下不展示提示

* feat: 了解更多按钮指向文档

* feat: 尝试解决黑边问题

* feat: 解决黑边的触控

* chore: 优化注释

* fix: 优化错误处理

* refactor
2024-05-09 22:32:50 +08:00

432 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pch.h"
#include "HomeViewModel.h"
#if __has_include("HomeViewModel.g.cpp")
#include "HomeViewModel.g.cpp"
#endif
#include "AppSettings.h"
#include "ScalingService.h"
#include "Win32Utils.h"
#include "StrUtils.h"
#include "UpdateService.h"
#include "CommonSharedConstants.h"
#include "TouchHelper.h"
#include "LocalizationService.h"
namespace winrt::Magpie::App::implementation {
HomeViewModel::HomeViewModel() {
ScalingService& ScalingService = ScalingService::Get();
_isRunningChangedRevoker = ScalingService.IsRunningChanged(
auto_revoke, { this, &HomeViewModel::_ScalingService_IsRunningChanged });
_isTimerOnRevoker = ScalingService.IsTimerOnChanged(
auto_revoke, { this, &HomeViewModel::_ScalingService_IsTimerOnChanged });
_timerTickRevoker = ScalingService.TimerTick(
auto_revoke, { this, &HomeViewModel::_ScalingService_TimerTick });
_wndToRestoreChangedRevoker = ScalingService.WndToRestoreChanged(
auto_revoke, { this, &HomeViewModel::_ScalingService_WndToRestoreChanged });
UpdateService& updateService = UpdateService::Get();
_showUpdateCard = updateService.IsShowOnHomePage();
_isShowOnHomePageChangedRevoker = updateService.IsShowOnHomePageChanged(
auto_revoke,
[this](bool value) {
if (value) {
ShowUpdateCard(true);
}
}
);
}
bool HomeViewModel::IsTimerOn() const noexcept {
return ScalingService::Get().IsTimerOn();
}
double HomeViewModel::TimerProgressRingValue() const noexcept {
ScalingService& ScalingService = ScalingService::Get();
return ScalingService.IsTimerOn() ? ScalingService.TimerProgress() : 1.0f;
}
hstring HomeViewModel::TimerLabelText() const noexcept {
ScalingService& ScalingService = ScalingService::Get();
return to_hstring((int)std::ceil(ScalingService.SecondsLeft()));
}
hstring HomeViewModel::TimerButtonText() const noexcept {
ScalingService& ScalingService = ScalingService::Get();
ResourceLoader resourceLoader =
ResourceLoader::GetForCurrentView(CommonSharedConstants::APP_RESOURCE_MAP_ID);
if (ScalingService.IsTimerOn()) {
return resourceLoader.GetString(L"Home_Activation_Timer_Cancel");
} else {
hstring fmtStr = resourceLoader.GetString(L"Home_Activation_Timer_ButtonText");
return hstring(fmt::format(
fmt::runtime(std::wstring_view(fmtStr)),
AppSettings::Get().CountdownSeconds()
));
}
}
bool HomeViewModel::IsNotRunning() const noexcept {
return !ScalingService::Get().IsRunning();
}
void HomeViewModel::ToggleTimer() const noexcept {
ScalingService& ScalingService = ScalingService::Get();
if (ScalingService.IsTimerOn()) {
ScalingService.StopTimer();
} else {
ScalingService.StartTimer();
}
}
uint32_t HomeViewModel::Delay() const noexcept {
return AppSettings::Get().CountdownSeconds();
}
void HomeViewModel::Delay(uint32_t value) {
AppSettings::Get().CountdownSeconds(value);
RaisePropertyChanged(L"Delay");
RaisePropertyChanged(L"TimerButtonText");
}
bool HomeViewModel::IsAutoRestore() const noexcept {
return AppSettings::Get().IsAutoRestore();
}
void HomeViewModel::IsAutoRestore(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsAutoRestore() == value) {
return;
}
settings.IsAutoRestore(value);
RaisePropertyChanged(L"IsAutoRestore");
}
bool HomeViewModel::IsWndToRestore() const noexcept {
return (bool)ScalingService::Get().WndToRestore();
}
void HomeViewModel::ActivateRestore() const noexcept {
HWND wndToRestore = (HWND)ScalingService::Get().WndToRestore();
if (wndToRestore) {
Win32Utils::SetForegroundWindow(wndToRestore);
}
}
void HomeViewModel::ClearRestore() const {
ScalingService::Get().ClearWndToRestore();
}
hstring HomeViewModel::RestoreWndDesc() const noexcept {
HWND wndToRestore = (HWND)ScalingService::Get().WndToRestore();
if (!wndToRestore) {
return L"";
}
std::wstring title(GetWindowTextLength(wndToRestore), L'\0');
GetWindowText(wndToRestore, title.data(), (int)title.size() + 1);
ResourceLoader resourceLoader =
ResourceLoader::GetForCurrentView(CommonSharedConstants::APP_RESOURCE_MAP_ID);
hstring curWindow = resourceLoader.GetString(L"Home_Activation_AutoRestore_CurWindow");
if (title.empty()) {
hstring emptyTitle = resourceLoader.GetString(L"Home_Activation_AutoRestore_EmptyTitle");
return hstring(StrUtils::Concat(curWindow, L"<", emptyTitle, L">"));
} else {
return curWindow + title;
}
}
inline void HomeViewModel::ShowUpdateCard(bool value) noexcept {
_showUpdateCard = value;
if (!value) {
UpdateService::Get().IsShowOnHomePage(false);
}
RaisePropertyChanged(L"ShowUpdateCard");
RaisePropertyChanged(L"UpdateCardTitle");
}
hstring HomeViewModel::UpdateCardTitle() const noexcept {
UpdateService& updateService = UpdateService::Get();
if (updateService.Status() < UpdateStatus::Available) {
return {};
}
ResourceLoader resourceLoader =
ResourceLoader::GetForCurrentView(CommonSharedConstants::APP_RESOURCE_MAP_ID);
hstring titleFmt = resourceLoader.GetString(L"About_Version_UpdateCard_Title");
return hstring(fmt::format(fmt::runtime(std::wstring_view(titleFmt)), updateService.Tag()));
}
bool HomeViewModel::IsAutoCheckForUpdates() const noexcept {
return AppSettings::Get().IsAutoCheckForUpdates();
}
void HomeViewModel::IsAutoCheckForUpdates(bool value) noexcept {
AppSettings::Get().IsAutoCheckForUpdates(value);
}
void HomeViewModel::DownloadAndInstall() {
UpdateService::Get().DownloadAndInstall();
Application::Current().as<App>().RootPage().NavigateToAboutPage();
}
void HomeViewModel::ReleaseNotes() {
std::wstring url = StrUtils::Concat(
L"https://github.com/Blinue/Magpie/releases/tag/",
UpdateService::Get().Tag()
);
Win32Utils::ShellOpen(url.c_str());
}
void HomeViewModel::RemindMeLater() {
ShowUpdateCard(false);
}
bool HomeViewModel::IsTouchSupportEnabled() const noexcept {
// 不检查版本号是否匹配
return TouchHelper::IsTouchSupportEnabled();
}
fire_and_forget HomeViewModel::IsTouchSupportEnabled(bool value) {
if (IsTouchSupportEnabled() == value) {
co_return;
}
auto weakThis = get_weak();
CoreDispatcher dispatcher = CoreWindow::GetForCurrentThread().Dispatcher();
// UAC 可能导致 XAML Islands 崩溃,因此不能在主线程上执行 ShellExecute
// 见 https://github.com/microsoft/microsoft-ui-xaml/issues/4952
co_await resume_background();
TouchHelper::IsTouchSupportEnabled(value);
co_await dispatcher;
if (weakThis.get()) {
RaisePropertyChanged(L"IsTouchSupportEnabled");
RaisePropertyChanged(L"IsShowTouchSupportInfoBar");
}
}
Uri HomeViewModel::TouchSupportLearnMoreUrl() const noexcept {
if (LocalizationService::Get().Language() == L"zh-hans"sv) {
return Uri(L"https://github.com/Blinue/Magpie/blob/38e44d855f43f913b6d894112f09205f75ca07fa/docs/%E5%85%B3%E4%BA%8E%E8%A7%A6%E6%8E%A7%E6%94%AF%E6%8C%81.md");
} else {
return Uri(L"https://github.com/Blinue/Magpie/blob/38e44d855f43f913b6d894112f09205f75ca07fa/docs/About%20touch%20support.md");
}
}
bool HomeViewModel::IsShowTouchSupportInfoBar() const noexcept {
return !Win32Utils::IsProcessElevated() && IsTouchSupportEnabled();
}
bool HomeViewModel::IsAllowScalingMaximized() const noexcept {
return AppSettings::Get().IsAllowScalingMaximized();
}
void HomeViewModel::IsAllowScalingMaximized(bool value) {
AppSettings::Get().IsAllowScalingMaximized(value);
if (value) {
ScalingService::Get().CheckForeground();
}
}
bool HomeViewModel::IsInlineParams() const noexcept {
return AppSettings::Get().IsInlineParams();
}
void HomeViewModel::IsInlineParams(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsInlineParams() == value) {
return;
}
settings.IsInlineParams(value);
RaisePropertyChanged(L"IsInlineParams");
}
bool HomeViewModel::IsSimulateExclusiveFullscreen() const noexcept {
return AppSettings::Get().IsSimulateExclusiveFullscreen();
}
void HomeViewModel::IsSimulateExclusiveFullscreen(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsSimulateExclusiveFullscreen() == value) {
return;
}
settings.IsSimulateExclusiveFullscreen(value);
RaisePropertyChanged(L"IsSimulateExclusiveFullscreen");
}
bool HomeViewModel::IsDeveloperMode() const noexcept {
return AppSettings::Get().IsDeveloperMode();
}
void HomeViewModel::IsDeveloperMode(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsDeveloperMode() == value) {
return;
}
settings.IsDeveloperMode(value);
RaisePropertyChanged(L"IsDeveloperMode");
}
bool HomeViewModel::IsDebugMode() const noexcept {
return AppSettings::Get().IsDebugMode();
}
void HomeViewModel::IsDebugMode(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsDebugMode() == value) {
return;
}
settings.IsDebugMode(value);
RaisePropertyChanged(L"IsDebugMode");
}
bool HomeViewModel::IsEffectCacheDisabled() const noexcept {
return AppSettings::Get().IsEffectCacheDisabled();
}
void HomeViewModel::IsEffectCacheDisabled(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsEffectCacheDisabled() == value) {
return;
}
settings.IsEffectCacheDisabled(value);
RaisePropertyChanged(L"IsEffectCacheDisabled");
}
bool HomeViewModel::IsFontCacheDisabled() const noexcept {
return AppSettings::Get().IsFontCacheDisabled();
}
void HomeViewModel::IsFontCacheDisabled(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsFontCacheDisabled() == value) {
return;
}
settings.IsFontCacheDisabled(value);
RaisePropertyChanged(L"IsFontCacheDisabled");
}
bool HomeViewModel::IsSaveEffectSources() const noexcept {
return AppSettings::Get().IsSaveEffectSources();
}
void HomeViewModel::IsSaveEffectSources(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsSaveEffectSources() == value) {
return;
}
settings.IsSaveEffectSources(value);
RaisePropertyChanged(L"IsSaveEffectSources");
}
bool HomeViewModel::IsWarningsAreErrors() const noexcept {
return AppSettings::Get().IsWarningsAreErrors();
}
void HomeViewModel::IsWarningsAreErrors(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsWarningsAreErrors() == value) {
return;
}
settings.IsWarningsAreErrors(value);
RaisePropertyChanged(L"IsWarningsAreErrors");
}
int HomeViewModel::DuplicateFrameDetectionMode() const noexcept {
return (int)AppSettings::Get().DuplicateFrameDetectionMode();
}
void HomeViewModel::DuplicateFrameDetectionMode(int value) {
if (value < 0) {
return;
}
const auto mode = (::Magpie::Core::DuplicateFrameDetectionMode)value;
AppSettings& settings = AppSettings::Get();
if (settings.DuplicateFrameDetectionMode() == mode) {
return;
}
settings.DuplicateFrameDetectionMode(mode);
RaisePropertyChanged(L"DuplicateFrameDetectionMode");
RaisePropertyChanged(L"IsDynamicDection");
if (mode != ::Magpie::Core::DuplicateFrameDetectionMode::Dynamic) {
settings.IsStatisticsForDynamicDetectionEnabled(false);
RaisePropertyChanged(L"IsStatisticsForDynamicDetectionEnabled");
}
}
bool HomeViewModel::IsDynamicDection() const noexcept {
return AppSettings::Get().DuplicateFrameDetectionMode() == ::Magpie::Core::DuplicateFrameDetectionMode::Dynamic;
}
bool HomeViewModel::IsStatisticsForDynamicDetectionEnabled() const noexcept {
return AppSettings::Get().IsStatisticsForDynamicDetectionEnabled();
}
void HomeViewModel::IsStatisticsForDynamicDetectionEnabled(bool value) {
AppSettings& settings = AppSettings::Get();
if (settings.IsStatisticsForDynamicDetectionEnabled() == value) {
return;
}
settings.IsStatisticsForDynamicDetectionEnabled(value);
RaisePropertyChanged(L"IsStatisticsForDynamicDetectionEnabled");
}
void HomeViewModel::_ScalingService_IsTimerOnChanged(bool value) {
if (!value) {
RaisePropertyChanged(L"TimerProgressRingValue");
}
RaisePropertyChanged(L"TimerProgressRingValue");
RaisePropertyChanged(L"TimerLabelText");
RaisePropertyChanged(L"TimerButtonText");
RaisePropertyChanged(L"IsTimerOn");
}
void HomeViewModel::_ScalingService_TimerTick(double) {
RaisePropertyChanged(L"TimerProgressRingValue");
RaisePropertyChanged(L"TimerLabelText");
}
void HomeViewModel::_ScalingService_IsRunningChanged(bool) {
RaisePropertyChanged(L"IsNotRunning");
}
void HomeViewModel::_ScalingService_WndToRestoreChanged(HWND) {
RaisePropertyChanged(L"IsWndToRestore");
RaisePropertyChanged(L"RestoreWndDesc");
}
}