From a2c0f61181c182c0d88c3470ab37597d2ed65733 Mon Sep 17 00:00:00 2001 From: Rye Mutt <rye@alchemyviewer.org> Date: Thu, 5 Oct 2023 23:54:10 -0400 Subject: [PATCH] Ensure all file picking operations are non-blocking for better ux --- indra/newview/llfloaterpreference.cpp | 88 ++++++++++++++------------- indra/newview/llfloaterpreference.h | 1 + indra/newview/llfloaterregioninfo.cpp | 30 ++++----- indra/newview/llfloaterregioninfo.h | 2 + indra/newview/llpaneleditwearable.cpp | 18 +++--- indra/newview/llpaneleditwearable.h | 1 + indra/newview/llpanelgrouproles.cpp | 18 ++++-- indra/newview/llpanelgrouproles.h | 1 + indra/newview/llvoavatar.cpp | 20 +++--- indra/newview/llvoavatar.h | 1 + 10 files changed, 97 insertions(+), 83 deletions(-) diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index fb4f0211fba..39ecf87aa54 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -76,6 +76,7 @@ #include "llviewercontrol.h" #include "llviewercamera.h" #include "llviewereventrecorder.h" +#include "llviewermenufile.h" #include "llviewermessage.h" #include "llviewerwindow.h" #include "llviewerthrottle.h" @@ -746,60 +747,61 @@ void LLFloaterPreference::reloadSkinList() void LLFloaterPreference::onAddSkin() { - LLFilePicker& filepicker = LLFilePicker::instance(); - if (filepicker.getOpenFile(LLFilePicker::FFLOAD_ZIP)) + LLFilePickerReplyThread::startPicker(boost::bind(&LLFloaterPreference::onAddSkinCallback, this, _1), LLFilePicker::FFLOAD_ZIP, false); +} + +void LLFloaterPreference::onAddSkinCallback(const std::vector<std::string>& filenames) +{ + const std::string& package = filenames[0]; + auto zip = std::make_unique<ALUnZip>(package); + if (zip->isValid()) { - const std::string& package = filepicker.getFirstFile(); - auto zip = std::make_unique<ALUnZip>(package); - if (zip->isValid()) + size_t buf_size = zip->getSizeFile("manifest.json"); + if (buf_size) { - size_t buf_size = zip->getSizeFile("manifest.json"); - if (buf_size) - { - buf_size++; - buf_size *= sizeof(char); - auto buf = std::make_unique<char[]>(buf_size); - zip->extractFile("manifest.json", buf.get(), buf_size); - buf[buf_size - 1] = '\0'; // force. - std::stringstream ss; - ss << std::string(const_cast<const char*>(buf.get()), buf_size); - buf.reset(); + buf_size++; + buf_size *= sizeof(char); + auto buf = std::make_unique<char[]>(buf_size); + zip->extractFile("manifest.json", buf.get(), buf_size); + buf[buf_size - 1] = '\0'; // force. + std::stringstream ss; + ss << std::string(const_cast<const char*>(buf.get()), buf_size); + buf.reset(); - nlohmann::json root; - try + nlohmann::json root; + try + { + ss >> root; + const std::string& name = root.value("name", "Unknown"); + std::string pathname = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "skins"); + if (!gDirUtilp->fileExists(pathname)) { - ss >> root; - const std::string& name = root.value("name", "Unknown"); - std::string pathname = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "skins"); - if (!gDirUtilp->fileExists(pathname)) - { - LLFile::mkdir(pathname); - } - pathname = gDirUtilp->add(pathname, name); - if (!LLFile::isdir(pathname) && (LLFile::mkdir(pathname) != 0)) - { - LLNotificationsUtil::add("AddSkinUnpackFailed"); - } - else if (!zip->extract(pathname)) - { - LLNotificationsUtil::add("AddSkinUnpackFailed"); - } - else - { - loadUserSkins(); - LLNotificationsUtil::add("AddSkinSuccess", LLSD().with("PACKAGE", name)); - } + LLFile::mkdir(pathname); + } + pathname = gDirUtilp->add(pathname, name); + if (!LLFile::isdir(pathname) && (LLFile::mkdir(pathname) != 0)) + { + LLNotificationsUtil::add("AddSkinUnpackFailed"); } - catch(const nlohmann::json::exception&) + else if (!zip->extract(pathname)) { - LLNotificationsUtil::add("AddSkinCantParseManifest", LLSD().with("PACKAGE", package)); + LLNotificationsUtil::add("AddSkinUnpackFailed"); + } + else + { + loadUserSkins(); + LLNotificationsUtil::add("AddSkinSuccess", LLSD().with("PACKAGE", name)); } } - else + catch(const nlohmann::json::exception&) { - LLNotificationsUtil::add("AddSkinNoManifest", LLSD().with("PACKAGE", package)); + LLNotificationsUtil::add("AddSkinCantParseManifest", LLSD().with("PACKAGE", package)); } } + else + { + LLNotificationsUtil::add("AddSkinNoManifest", LLSD().with("PACKAGE", package)); + } } } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 79ecec12b3d..ff6aba9fe13 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -227,6 +227,7 @@ class LLFloaterPreference final : public LLFloater, public LLAvatarPropertiesObs void loadUserSkins(); void reloadSkinList(); void onAddSkin(); + void onAddSkinCallback(const std::vector<std::string>& filenames); void onRemoveSkin(); void callbackRemoveSkin(const LLSD& notification, const LLSD& response); void onApplySkin(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index b54e1c08f30..2ec19d50d41 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -80,6 +80,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" #include "llviewerinventory.h" +#include "llviewermenufile.h" #include "llviewertexture.h" #include "llviewertexturelist.h" #include "llviewerregion.h" @@ -1567,13 +1568,14 @@ bool LLPanelRegionTerrainInfo::callbackTextureHeights(const LLSD& notification, // static void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data) { - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(LLFilePicker::FFSAVE_RAW, "terrain.raw")) - { - LL_WARNS() << "No file" << LL_ENDL; - return; - } - std::string filepath = picker.getFirstFile(); + LLDir::getScrubbedFileName(LLRegionInfoModel::instance().mSimName+"_terrain.raw"); + LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelRegionTerrainInfo::onClickDownloadRawCallback, _1, data), LLFilePicker::FFSAVE_RAW, LLDir::getScrubbedFileName(LLRegionInfoModel::instance().mSimName + "_terrain.raw")); +} + +// static +void LLPanelRegionTerrainInfo::onClickDownloadRawCallback(const std::vector<std::string>& filenames, void* data) +{ + std::string filepath = filenames[0]; gXferManager->expectFileForRequest(filepath); LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; @@ -1587,13 +1589,13 @@ void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data) // static void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data) { - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(LLFilePicker::FFLOAD_RAW)) - { - LL_WARNS() << "No file" << LL_ENDL; - return; - } - std::string filepath = picker.getFirstFile(); + LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRawCallback, data, _1), LLFilePicker::FFLOAD_RAW, false); +} + +// static +void LLPanelRegionTerrainInfo::onClickUploadRawCallback(void* data, const std::vector<std::string>& filenames) +{ + std::string filepath = filenames[0]; gXferManager->expectFileForTransfer(filepath); LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index a1b11faafa9..21bd79b97a7 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -260,7 +260,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo virtual BOOL sendUpdate(); static void onClickDownloadRaw(void*); + static void onClickDownloadRawCallback(const std::vector<std::string>& filenames, void* data); static void onClickUploadRaw(void*); + static void onClickUploadRawCallback(void* data, const std::vector<std::string>& filenames); static void onClickBakeTerrain(void*); bool callbackBakeTerrain(const LLSD& notification, const LLSD& response); bool callbackTextureHeights(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 9e7ffc9efa2..06a0b002663 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -62,6 +62,7 @@ #include "llcommandhandler.h" #include "lltextutil.h" #include "llappearancemgr.h" +#include "llviewermenufile.h" // register panel with appropriate XML static LLPanelInjector<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable"); @@ -1202,14 +1203,13 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO const std::string accordion_tab = subpart_entry->mAccordionTab; LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel); - LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab); - if (!panel_list) { LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL; continue; } + LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab); if (!tab) { LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL; @@ -1664,14 +1664,12 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefine void LLPanelEditWearable::onClickedImportBtn() { - LLFilePicker& file_picker = LLFilePicker::instance(); - if(!file_picker.getOpenFile(LLFilePicker::FFLOAD_XML)) - { - LL_INFOS("ShapeImport") << "User closed the filepicker. Aborting!" << LL_ENDL; - return; - } - - const std::string filename = file_picker.getFirstFile(); + LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelEditWearable::onClickedImportBtnCallback, this, _1), LLFilePicker::FFLOAD_XML, false); +} + +void LLPanelEditWearable::onClickedImportBtnCallback(const std::vector<std::string>& filenames) +{ + const std::string filename = filenames[0]; LLXmlTree tree; if (!tree.parseFile(filename, FALSE)) { diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 1e5d8c23f1a..fbca41b27f5 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -90,6 +90,7 @@ class LLPanelEditWearable : public LLPanel void updateVerbs(); void onClickedImportBtn(); + void onClickedImportBtnCallback(const std::vector<std::string>& filenames); void onColorSwatchCommit(const LLUICtrl*); void onTexturePickerCommit(const LLUICtrl*); diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index c6f5595ded0..fbe53ec4edd 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -53,6 +53,7 @@ #include "llviewerwindow.h" #include "llfocusmgr.h" #include "llviewercontrol.h" +#include "llviewermenufile.h" #include "roles_constants.h" #include "llfilepicker.h" @@ -1959,18 +1960,25 @@ void LLPanelGroupMembersSubTab::handleBanMember() handleEjectMembers(); } - void LLPanelGroupMembersSubTab::onExportMembersToCSV() { if (mPendingMemberUpdate) return; - + + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if (gdatap) + { + LLFilePickerReplyThread::startPicker(boost::bind(&LLPanelGroupMembersSubTab::exportMembersToCSVCallback, this, _1), LLFilePicker::FFSAVE_CSV, LLDir::getScrubbedFileName(gdatap->mName + "_members.csv")); + } +} + +void LLPanelGroupMembersSubTab::exportMembersToCSVCallback(const std::vector<std::string>& filenames) +{ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); - LLFilePicker& file_picker = LLFilePicker::instance(); - if (!file_picker.getSaveFile(LLFilePicker::FFSAVE_CSV, LLDir::getScrubbedFileName(gdatap->mName + "_members.csv"))) + if (!gdatap) { return; } - std::string fullpath = file_picker.getFirstFile(); + std::string fullpath = filenames[0]; LLAPRFile outfile; outfile.open(fullpath, LL_APR_WB ); diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 60fa4109cd6..1d3c9ea4f52 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -209,6 +209,7 @@ class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab bool matchesSearchFilter(const std::string& fullname); void onExportMembersToCSV(); + void exportMembersToCSVCallback(const std::vector<std::string>& filenames); U64 getAgentPowersBasedOnRoleChanges(const LLUUID& agent_id); bool getRoleChangeType(const LLUUID& member_id, diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6d2add0077d..c2cce800c90 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -127,6 +127,7 @@ #include "alcinematicmode.h" #include "llsidepanelappearance.h" +#include "llviewermenufile.h" extern F32 SPEED_ADJUST_MAX; extern F32 SPEED_ADJUST_MAX_SEC; @@ -10264,29 +10265,26 @@ void LLVOAvatar::getSortedJointNames(S32 joint_type, std::vector<std::string>& r std::sort(result.begin(), result.end()); } -void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables ) +void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables) { std::string outprefix(prefix); if (outprefix.empty()) { - outprefix = getFullname() + (isSelf()?"_s":"_o"); + outprefix = getFullname() + (isSelf() ? "_s" : "_o"); } if (outprefix.empty()) { outprefix = std::string("new_archetype"); } - std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); + std::string outfilename = get_sequential_numbered_file_name(outprefix, ".xml"); + LLFilePickerReplyThread::startPicker(boost::bind(&LLVOAvatar::dumpArchetypeXMLCallback, this, _1, group_by_wearables), LLFilePicker::FFSAVE_XML, outfilename); +} - LLFilePicker& file_picker = LLFilePicker::instance(); - if (!file_picker.getSaveFile(LLFilePicker::FFSAVE_XML, outfilename)) - { - LL_INFOS("DumpArchetypeXML") << "User closed the filepicker" << LL_ENDL; - return; - } - +void LLVOAvatar::dumpArchetypeXMLCallback(const std::vector<std::string>& filenames, bool group_by_wearables) +{ LLAPRFile outfile; LLWearableType *wr_inst = LLWearableType::getInstance(); - std::string fullpath = file_picker.getFirstFile(); + std::string fullpath = filenames[0]; if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB )) { apr_file_t* file = outfile.getFileHandle(); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 820c46ae0d4..f70ac2d3116 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -1184,6 +1184,7 @@ class LLVOAvatar : public: void getSortedJointNames(S32 joint_type, std::vector<std::string>& result) const; void dumpArchetypeXML(const std::string& prefix, bool group_by_wearables = false); + void dumpArchetypeXMLCallback(const std::vector<std::string>& filenames, bool group_by_wearables); void dumpAppearanceMsgParams( const std::string& dump_prefix, const LLAppearanceMessageContents& contents); static void dumpBakedStatus(); -- GitLab