#include "SearchController.h" #include "Controller.h" #include "SearchModel.h" #include "SearchView.h" #include "client/Client.h" #include "client/SaveInfo.h" #include "client/GameSave.h" #include "common/platform/Platform.h" #include "common/tpt-minmax.h" #include "graphics/Graphics.h" #include "tasks/Task.h" #include "tasks/TaskWindow.h" #include "gui/dialogues/ConfirmPrompt.h" #include "gui/preview/PreviewController.h" #include "gui/preview/PreviewView.h" #include "SimulationConfig.h" SearchController::SearchController(std::function onDone_): activePreview(NULL), nextQueryTime(0.0f), nextQueryDone(true), instantOpen(false), doRefresh(false), HasExited(false) { searchModel = new SearchModel(); searchView = new SearchView(); searchModel->AddObserver(searchView); searchView->AttachController(this); searchModel->UpdateSaveList(1, ""); onDone = onDone_; } const SaveInfo *SearchController::GetLoadedSave() const { return searchModel->GetLoadedSave(); } std::unique_ptr SearchController::TakeLoadedSave() { return searchModel->TakeLoadedSave(); } void SearchController::Update() { if (doRefresh) { if (searchModel->UpdateSaveList(searchModel->GetPageNum(), searchModel->GetLastQuery())) { nextQueryDone = true; doRefresh = false; } } else if (!nextQueryDone && nextQueryTime < Platform::GetTime()) { if (searchModel->UpdateSaveList(1, nextQuery)) nextQueryDone = true; } searchModel->Update(); if(activePreview && activePreview->HasExited) { delete activePreview; activePreview = NULL; if(searchModel->GetLoadedSave()) { Exit(); } } } void SearchController::Exit() { InstantOpen(false); searchView->CloseActiveWindow(); if (onDone) onDone(); //HasExited = true; } SearchController::~SearchController() { delete activePreview; searchView->CloseActiveWindow(); delete searchModel; delete searchView; } void SearchController::DoSearch(String query, bool now) { nextQuery = query; if (!now) { nextQueryTime = Platform::GetTime()+600; nextQueryDone = false; } else { nextQueryDone = searchModel->UpdateSaveList(1, nextQuery); } } void SearchController::DoSearch2(String query) { // calls SearchView function to set textbox text, then calls DoSearch searchView->Search(query); } void SearchController::Refresh() { doRefresh = true; } void SearchController::SetPage(int page) { if (page != searchModel->GetPageNum() && page > 0 && page <= searchModel->GetPageCount()) searchModel->UpdateSaveList(page, searchModel->GetLastQuery()); } void SearchController::SetPageRelative(int offset) { int page = std::min(std::max(searchModel->GetPageNum() + offset, 1), searchModel->GetPageCount()); if (page != searchModel->GetPageNum()) searchModel->UpdateSaveList(page, searchModel->GetLastQuery()); } void SearchController::ChangeSort() { if(searchModel->GetSort() == "new") { searchModel->SetSort("best"); } else { searchModel->SetSort("new"); } searchModel->UpdateSaveList(1, searchModel->GetLastQuery()); } void SearchController::ShowOwn(bool show) { if(Client::Ref().GetAuthUser().UserID) { searchModel->SetShowFavourite(false); searchModel->SetShowOwn(show); } else searchModel->SetShowOwn(false); searchModel->UpdateSaveList(1, searchModel->GetLastQuery()); } void SearchController::ShowFavourite(bool show) { if(Client::Ref().GetAuthUser().UserID) { searchModel->SetShowOwn(false); searchModel->SetShowFavourite(show); } else searchModel->SetShowFavourite(false); searchModel->UpdateSaveList(1, searchModel->GetLastQuery()); } void SearchController::Selected(int saveID, bool selected) { if(!Client::Ref().GetAuthUser().UserID) return; if(selected) searchModel->SelectSave(saveID); else searchModel->DeselectSave(saveID); } void SearchController::SelectAllSaves() { if (!Client::Ref().GetAuthUser().UserID) return; if (searchModel->GetShowOwn() || Client::Ref().GetAuthUser().UserElevation == User::ElevationModerator || Client::Ref().GetAuthUser().UserElevation == User::ElevationAdmin) searchModel->SelectAllSaves(); } void SearchController::InstantOpen(bool instant) { instantOpen = instant; } void SearchController::OpenSaveDone() { if (activePreview->GetDoOpen() && activePreview->GetSaveInfo()) { searchModel->SetLoadedSave(activePreview->TakeSaveInfo()); } else { searchModel->SetLoadedSave(nullptr); } } void SearchController::OpenSave(int saveID, int saveDate, std::unique_ptr thumbnail) { delete activePreview; Graphics * g = searchView->GetGraphics(); g->BlendFilledRect(RectSized(Vec2{ XRES/3, WINDOWH-20 }, Vec2{ XRES/3, 20 }), 0x000000_rgb .WithAlpha(150)); //dim the "Page X of Y" a little to make the CopyTextButton more noticeable activePreview = new PreviewController(saveID, saveDate, instantOpen, [this] { OpenSaveDone(); }, std::move(thumbnail)); activePreview->GetView()->MakeActiveWindow(); } void SearchController::ClearSelection() { searchModel->ClearSelected(); } void SearchController::RemoveSelected() { StringBuilder desc; desc << "Are you sure you want to delete " << searchModel->GetSelected().size() << " save"; if(searchModel->GetSelected().size()>1) desc << "s"; desc << "?"; new ConfirmPrompt("Delete saves", desc.Build(), { [this] { removeSelectedC(); } }); } void SearchController::removeSelectedC() { class RemoveSavesTask : public Task { SearchController *c; std::vector saves; public: RemoveSavesTask(std::vector saves_, SearchController *c_) { saves = saves_; c = c_; } bool doWork() override { for (size_t i = 0; i < saves.size(); i++) { notifyStatus(String::Build("Deleting save [", saves[i], "] ...")); if (Client::Ref().DeleteSave(saves[i])!=RequestOkay) { notifyError(String::Build("Failed to delete [", saves[i], "]: ", Client::Ref().GetLastError())); c->Refresh(); return false; } notifyProgress((i + 1) * 100 / saves.size()); } c->Refresh(); return true; } }; std::vector selected = searchModel->GetSelected(); new TaskWindow("Removing saves", new RemoveSavesTask(selected, this)); ClearSelection(); searchModel->UpdateSaveList(searchModel->GetPageNum(), searchModel->GetLastQuery()); } void SearchController::UnpublishSelected(bool publish) { StringBuilder desc; desc << "Are you sure you want to " << (publish ? String("publish ") : String("unpublish ")) << searchModel->GetSelected().size() << " save"; if (searchModel->GetSelected().size() > 1) desc << "s"; desc << "?"; new ConfirmPrompt(publish ? String("Publish Saves") : String("Unpublish Saves"), desc.Build(), { [this, publish] { unpublishSelectedC(publish); } }); } void SearchController::unpublishSelectedC(bool publish) { class UnpublishSavesTask : public Task { std::vector saves; SearchController *c; bool publish; public: UnpublishSavesTask(std::vector saves_, SearchController *c_, bool publish_) { saves = saves_; c = c_; publish = publish_; } bool PublishSave(int saveID) { notifyStatus(String::Build("Publishing save [", saveID, "]")); if (Client::Ref().PublishSave(saveID) != RequestOkay) return false; return true; } bool UnpublishSave(int saveID) { notifyStatus(String::Build("Unpublishing save [", saveID, "]")); if (Client::Ref().UnpublishSave(saveID) != RequestOkay) return false; return true; } bool doWork() override { bool ret; for (size_t i = 0; i < saves.size(); i++) { if (publish) ret = PublishSave(saves[i]); else ret = UnpublishSave(saves[i]); if (!ret) { if (publish) // uses html page so error message will be spam notifyError(String::Build("Failed to publish [", saves[i], "], is this save yours?")); else notifyError(String::Build("Failed to unpublish [", saves[i], "]: " + Client::Ref().GetLastError())); c->Refresh(); return false; } notifyProgress((i + 1) * 100 / saves.size()); } c->Refresh(); return true; } }; std::vector selected = searchModel->GetSelected(); new TaskWindow(publish ? String("Publishing Saves") : String("Unpublishing Saves"), new UnpublishSavesTask(selected, this, publish)); } void SearchController::FavouriteSelected() { class FavouriteSavesTask : public Task { std::vector saves; public: FavouriteSavesTask(std::vector saves_) { saves = saves_; } bool doWork() override { for (size_t i = 0; i < saves.size(); i++) { notifyStatus(String::Build("Favouring save [", saves[i], "]")); if (Client::Ref().FavouriteSave(saves[i], true)!=RequestOkay) { notifyError(String::Build("Failed to favourite [", saves[i], "]: " + Client::Ref().GetLastError())); return false; } notifyProgress((i + 1) * 100 / saves.size()); } return true; } }; class UnfavouriteSavesTask : public Task { std::vector saves; public: UnfavouriteSavesTask(std::vector saves_) { saves = saves_; } bool doWork() override { for (size_t i = 0; i < saves.size(); i++) { notifyStatus(String::Build("Unfavouring save [", saves[i], "]")); if (Client::Ref().FavouriteSave(saves[i], false)!=RequestOkay) { notifyError(String::Build("Failed to unfavourite [", saves[i], "]: " + Client::Ref().GetLastError())); return false; } notifyProgress((i + 1) * 100 / saves.size()); } return true; } }; std::vector selected = searchModel->GetSelected(); if (!searchModel->GetShowFavourite()) new TaskWindow("Favouring saves", new FavouriteSavesTask(selected)); else new TaskWindow("Unfavouring saves", new UnfavouriteSavesTask(selected)); ClearSelection(); }