This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/gui/search/SearchController.cpp
Tamás Bálint Misius a9d231587c
Show save button thumbnail in the preview if it's available
This is good enough for now but also more limited than I'd like because if the thumbnail arrives (gets rendered or downloaded) later than the preview is opened, it's never shown.
2023-05-13 13:21:05 +02:00

383 lines
9.5 KiB
C++

#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<void ()> 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<SaveInfo> 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<VideoBuffer> 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<int> saves;
public:
RemoveSavesTask(std::vector<int> 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<int> 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<int> saves;
SearchController *c;
bool publish;
public:
UnpublishSavesTask(std::vector<int> 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<int> 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<int> saves;
public:
FavouriteSavesTask(std::vector<int> 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<int> saves;
public:
UnfavouriteSavesTask(std::vector<int> 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<int> selected = searchModel->GetSelected();
if (!searchModel->GetShowFavourite())
new TaskWindow("Favouring saves", new FavouriteSavesTask(selected));
else
new TaskWindow("Unfavouring saves", new UnfavouriteSavesTask(selected));
ClearSelection();
}