Windows: Implement System_ShareFile as a Save As dialog

Win32 has no share sheet hookup yet, so sharing a file offers to save a
copy of it. ShareFilesAsZip no longer needs an app cache directory, which
Windows doesn't set; it falls back to the memstick cache folder through
DIRECTORY_APP_CACHE. The save dialog now asks before overwriting.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-11 21:52:38 +02:00
1 parent 7cab022eaf
commit 0d032fa2ee
3 files changed
+38 -4

No files matched your search

+4 -3
View File
@@ -30,14 +30,15 @@
#include "Common/System/Request.h"
#include "Common/System/System.h"
#include "Common/TimeUtil.h"
#include "Core/Config.h"
#include "Core/Util/PathUtil.h"
#include "UI/ShareFiles.h"
// How long a shared zip is kept for the receiving app to read.
static constexpr int64_t SHARE_KEEP_SECONDS = 60 * 60;
static Path ShareDirectory() {
return g_Config.appCacheDirectory / "share";
// Falls back to the memstick cache folder on platforms without an app cache directory (Windows).
return GetSysDirectory(DIRECTORY_APP_CACHE) / "share";
}
// Deletes the folders of earlier shares (named by their time) once they're old enough.
@@ -57,7 +58,7 @@ static void CleanUpOldShares(int64_t now) {
}
bool CanShareFiles() {
return System_GetPropertyBool(SYSPROP_SUPPORTS_SHARE_FILE) && !g_Config.appCacheDirectory.empty();
return System_GetPropertyBool(SYSPROP_SUPPORTS_SHARE_FILE);
}
bool ShareFilesAsZip(std::string_view zipName, const std::vector<ShareZipEntry> &files) {
+1 -1
View File
@@ -135,7 +135,7 @@ std::string BrowseForFolder2(HWND parent, std::string_view title, std::string_vi
ofn.nMaxFile = ARRAY_SIZE(fileBuffer);
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER;
if (!_bLoad)
ofn.Flags |= OFN_HIDEREADONLY;
ofn.Flags |= OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
int success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
if (success) {
+33
View File
@@ -455,6 +455,7 @@ bool System_GetPropertyBool(SystemProperty prop) {
case SYSPROP_CAN_SHOW_FILE:
case SYSPROP_CAN_LAUNCH_URL:
case SYSPROP_HAS_TRASH_BIN:
case SYSPROP_SUPPORTS_SHARE_FILE:
return true;
case SYSPROP_HAS_IMAGE_BROWSER:
return true;
@@ -782,6 +783,38 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
}).detach();
return true;
case SystemRequestType::SHARE_FILE:
{
// No share sheet here yet, so offer to save a copy instead. param2 (the MIME type) isn't needed.
const Path source(param1);
if (!File::Exists(source)) {
ERROR_LOG(Log::System, "SHARE_FILE: '%s' doesn't exist", param1.c_str());
return false;
}
std::thread([source] {
SetCurrentThreadName("ShareFile");
std::wstring filter;
std::wstring extension;
const std::string ext = source.GetFileExtension(); // Lowercase, with the dot.
if (ext.size() > 1) {
extension = ConvertUTF8ToWString(ext.substr(1));
std::wstring upper = extension;
std::transform(upper.begin(), upper.end(), upper.begin(), towupper);
filter = upper + L" files (*." + extension + L")|*." + extension + L"|";
}
filter = FinalizeFilter(filter + L"All files (*.*)|*.*||");
std::string out;
if (!W32Util::BrowseForFileName(false, MainWindow::GetHWND(), L"", nullptr, ConvertUTF8ToWString(source.GetFilename()).c_str(), filter.c_str(), extension.c_str(), out)) {
return;
}
const Path dest(out);
if (dest != source && !File::Copy(source, dest)) {
ERROR_LOG(Log::System, "SHARE_FILE: Couldn't copy '%s' to '%s'", source.c_str(), dest.c_str());
}
}).detach();
return true;
}
case SystemRequestType::APPLY_FULLSCREEN_STATE:
{
MainWindow::SendApplyFullscreenState();