UI: Validate address entered in settings.

This commit is contained in:
Unknown W. Brackets committed 2019-08-18 10:12:22 -07:00
1 parent 3bc2cad31b
commit 30dcc2a13a
4 files changed
+125 -4

No files matched your search

+84
View File
@@ -22,6 +22,7 @@
#include "base/colorutil.h"
#include "base/timeutil.h"
#include "math/curves.h"
#include "net/resolve.h"
#include "gfx_es2/gpu_features.h"
#include "gfx_es2/draw_buffer.h"
#include "i18n/i18n.h"
@@ -1468,6 +1469,7 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
I18NCategory *sy = GetI18NCategory("System");
I18NCategory *di = GetI18NCategory("Dialog");
I18NCategory *n = GetI18NCategory("Networking");
LinearLayout *valueRow = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, Margins(0, 0, 0, 10)));
@@ -1495,6 +1497,13 @@ void HostnameSelectScreen::CreatePopupContents(UI::ViewGroup *parent) {
buttonsRow2->Add(new Button(di->T("Delete")))->OnClick.Handle(this, &HostnameSelectScreen::OnDeleteClick);
buttonsRow2->Add(new Button(di->T("Delete all")))->OnClick.Handle(this, &HostnameSelectScreen::OnDeleteAllClick);
buttonsRow2->Add(new Spacer(new LinearLayoutParams(1.0, G_RIGHT)));
errorView_ = parent->Add(new TextView(n->T("Invalid IP or hostname"), ALIGN_HCENTER, false, new LinearLayoutParams(Margins(0, 10, 0, 0))));
errorView_->SetTextColor(0xFF3030FF);
errorView_->SetVisibility(V_GONE);
progressView_ = parent->Add(new TextView(n->T("Validating address..."), ALIGN_HCENTER, false, new LinearLayoutParams(Margins(0, 10, 0, 0))));
progressView_->SetVisibility(V_GONE);
}
void HostnameSelectScreen::SendEditKey(int keyCode, int flags) {
@@ -1528,6 +1537,81 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) {
return UI::EVENT_DONE;
}
void HostnameSelectScreen::ResolverThread() {
std::unique_lock<std::mutex> guard(resolverLock_);
while (resolverState_ != ResolverState::QUIT) {
resolverCond_.wait(guard);
if (resolverState_ == ResolverState::QUEUED) {
resolverState_ = ResolverState::PROGRESS;
addrinfo *resolved = nullptr;
std::string err;
toResolveResult_ = net::DNSResolve(toResolve_, "80", &resolved, err);
if (resolved)
net::DNSResolveFree(resolved);
resolverState_ = ResolverState::READY;
}
}
}
bool HostnameSelectScreen::CanComplete(DialogResult result) {
if (result != DR_OK)
return true;
std::string value = addrView_->GetText();
if (lastResolved_ == value) {
return true;
}
// Currently running.
if (resolverState_ == ResolverState::PROGRESS)
return false;
std::lock_guard<std::mutex> guard(resolverLock_);
switch (resolverState_) {
case ResolverState::PROGRESS:
case ResolverState::QUIT:
return false;
case ResolverState::QUEUED:
case ResolverState::WAITING:
break;
case ResolverState::READY:
if (toResolve_ == value) {
// Reset the state, nothing there now.
resolverState_ = ResolverState::WAITING;
toResolve_.clear();
lastResolved_ = value;
lastResolvedResult_ = toResolveResult_;
if (lastResolvedResult_) {
errorView_->SetVisibility(UI::V_GONE);
} else {
errorView_->SetVisibility(UI::V_VISIBLE);
}
progressView_->SetVisibility(UI::V_GONE);
return true;
}
// Throw away that last result, it was for a different value.
break;
}
resolverState_ = ResolverState::QUEUED;
toResolve_ = value;
resolverCond_.notify_one();
progressView_->SetVisibility(UI::V_VISIBLE);
errorView_->SetVisibility(UI::V_GONE);
return false;
}
void HostnameSelectScreen::OnCompleted(DialogResult result) {
if (result == DR_OK)
*value_ = addrView_->GetText();
+33 -1
View File
@@ -18,6 +18,9 @@
#pragma once
#include "ppsspp_config.h"
#include <condition_variable>
#include <mutex>
#include <thread>
#include "ui/ui_screen.h"
#include "UI/MiscScreens.h"
@@ -179,20 +182,49 @@ class HostnameSelectScreen : public PopupScreen {
public:
HostnameSelectScreen(std::string *value, const std::string &title)
: PopupScreen(title, "OK", "Cancel"), value_(value) {
resolver_ = std::thread([](HostnameSelectScreen *thiz) {
thiz->ResolverThread();
}, this);
}
~HostnameSelectScreen() {
resolverState_ = ResolverState::QUIT;
resolverCond_.notify_one();
resolver_.join();
}
void CreatePopupContents(UI::ViewGroup *parent) override;
protected:
void OnCompleted(DialogResult result) override;
bool CanComplete(DialogResult result) override;
private:
void ResolverThread();
void SendEditKey(int keyCode, int flags = 0);
UI::EventReturn OnNumberClick(UI::EventParams &e);
UI::EventReturn OnPointClick(UI::EventParams &e);
UI::EventReturn OnDeleteClick(UI::EventParams &e);
UI::EventReturn OnDeleteAllClick(UI::EventParams &e);
enum class ResolverState {
WAITING,
QUEUED,
PROGRESS,
READY,
QUIT,
};
std::string *value_;
UI::TextEdit *addrView_;
UI::TextEdit *addrView_ = nullptr;
UI::TextView *errorView_ = nullptr;
UI::TextView *progressView_ = nullptr;
std::thread resolver_;
ResolverState resolverState_ = ResolverState::WAITING;
std::mutex resolverLock_;
std::condition_variable resolverCond_;
std::string toResolve_ = "";
bool toResolveResult_ = false;
std::string lastResolved_ = "";
bool lastResolvedResult_ = false;
};
+7 -3
View File
@@ -268,6 +268,8 @@ bool PopupScreen::key(const KeyInput &key) {
void PopupScreen::update() {
UIDialogScreen::update();
defaultButton_->SetEnabled(CanComplete(DR_OK));
float animatePos = 1.0f;
++frames_;
@@ -314,10 +316,12 @@ void PopupScreen::SetPopupOrigin(const UI::View *view) {
}
void PopupScreen::TriggerFinish(DialogResult result) {
finishFrame_ = frames_;
finishResult_ = result;
if (CanComplete(result)) {
finishFrame_ = frames_;
finishResult_ = result;
OnCompleted(result);
OnCompleted(result);
}
}
void PopupScreen::resized() {
+1
View File
@@ -84,6 +84,7 @@ protected:
virtual bool FillVertical() const { return false; }
virtual UI::Size PopupWidth() const { return 550; }
virtual bool ShowButtons() const { return true; }
virtual bool CanComplete(DialogResult result) { return true; }
virtual void OnCompleted(DialogResult result) {}
virtual void update() override;