mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Projucer: Remove user login and license check code
This commit is contained in:
parent
fcaaf38c58
commit
7306fe1789
31 changed files with 108 additions and 2007 deletions
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_LicenseState.h"
|
||||
#include "jucer_LicenseQueryThread.h"
|
||||
|
||||
//==============================================================================
|
||||
class LicenseController final : private Timer
|
||||
{
|
||||
public:
|
||||
LicenseController()
|
||||
{
|
||||
checkLicense();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static LicenseState getAGPLState()
|
||||
{
|
||||
return { LicenseState::Type::agplv3, projucerMajorVersion, {}, {} };
|
||||
}
|
||||
|
||||
LicenseState getCurrentState() const noexcept
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
void setState (const LicenseState& newState)
|
||||
{
|
||||
if (state != newState)
|
||||
{
|
||||
state = newState;
|
||||
licenseStateToSettings (state, getGlobalProperties());
|
||||
|
||||
stateListeners.call ([] (LicenseStateListener& l) { l.licenseStateChanged(); });
|
||||
}
|
||||
}
|
||||
|
||||
void resetState()
|
||||
{
|
||||
setState ({});
|
||||
}
|
||||
|
||||
void signIn (const String& email, const String& password,
|
||||
std::function<void (const String&)> completionCallback)
|
||||
{
|
||||
licenseQueryThread.doSignIn (email, password,
|
||||
[this, completionCallback] (LicenseQueryThread::ErrorMessageAndType error,
|
||||
LicenseState newState)
|
||||
{
|
||||
completionCallback (error.first);
|
||||
setState (newState);
|
||||
});
|
||||
}
|
||||
|
||||
void cancelSignIn()
|
||||
{
|
||||
licenseQueryThread.cancelRunningJobs();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct LicenseStateListener
|
||||
{
|
||||
virtual ~LicenseStateListener() = default;
|
||||
virtual void licenseStateChanged() = 0;
|
||||
};
|
||||
|
||||
void addListener (LicenseStateListener* listenerToAdd)
|
||||
{
|
||||
stateListeners.add (listenerToAdd);
|
||||
}
|
||||
|
||||
void removeListener (LicenseStateListener* listenerToRemove)
|
||||
{
|
||||
stateListeners.remove (listenerToRemove);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
static const char* getLicenseStateValue (LicenseState::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LicenseState::Type::agplv3: return "AGPLv3";
|
||||
case LicenseState::Type::personal: return "personal";
|
||||
case LicenseState::Type::educational: return "edu";
|
||||
case LicenseState::Type::indie: return "indie";
|
||||
case LicenseState::Type::pro: return "pro";
|
||||
case LicenseState::Type::none:
|
||||
default: break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LicenseState::Type getLicenseTypeFromValue (const String& d)
|
||||
{
|
||||
if (d == getLicenseStateValue (LicenseState::Type::agplv3)) return LicenseState::Type::agplv3;
|
||||
if (d == getLicenseStateValue (LicenseState::Type::personal)) return LicenseState::Type::personal;
|
||||
if (d == getLicenseStateValue (LicenseState::Type::educational)) return LicenseState::Type::educational;
|
||||
if (d == getLicenseStateValue (LicenseState::Type::indie)) return LicenseState::Type::indie;
|
||||
if (d == getLicenseStateValue (LicenseState::Type::pro)) return LicenseState::Type::pro;
|
||||
return LicenseState::Type::none;
|
||||
}
|
||||
|
||||
static LicenseState licenseStateFromSettings (PropertiesFile& props)
|
||||
{
|
||||
if (auto licenseXml = props.getXmlValue ("license"))
|
||||
{
|
||||
// this is here for backwards compatibility with old-style settings files using XML text elements
|
||||
if (licenseXml->getChildElementAllSubText ("type", {}).isNotEmpty())
|
||||
{
|
||||
auto stateFromOldSettings = [&licenseXml]() -> LicenseState
|
||||
{
|
||||
return { getLicenseTypeFromValue (licenseXml->getChildElementAllSubText ("type", {})),
|
||||
licenseXml->getChildElementAllSubText ("version", "-1").getIntValue(),
|
||||
licenseXml->getChildElementAllSubText ("username", {}),
|
||||
licenseXml->getChildElementAllSubText ("authToken", {}) };
|
||||
}();
|
||||
|
||||
licenseStateToSettings (stateFromOldSettings, props);
|
||||
|
||||
return stateFromOldSettings;
|
||||
}
|
||||
|
||||
return { getLicenseTypeFromValue (licenseXml->getStringAttribute ("type", {})),
|
||||
licenseXml->getIntAttribute ("version", -1),
|
||||
licenseXml->getStringAttribute ("username", {}),
|
||||
licenseXml->getStringAttribute ("authToken", {}) };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
static void licenseStateToSettings (const LicenseState& state, PropertiesFile& props)
|
||||
{
|
||||
props.removeValue ("license");
|
||||
|
||||
if (state.isSignedIn())
|
||||
{
|
||||
XmlElement licenseXml ("license");
|
||||
|
||||
if (auto* typeString = getLicenseStateValue (state.type))
|
||||
licenseXml.setAttribute ("type", typeString);
|
||||
|
||||
licenseXml.setAttribute ("version", state.version);
|
||||
licenseXml.setAttribute ("username", state.username);
|
||||
licenseXml.setAttribute ("authToken", state.authToken);
|
||||
|
||||
props.setValue ("license", &licenseXml);
|
||||
}
|
||||
|
||||
props.saveIfNeeded();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void checkLicense()
|
||||
{
|
||||
if (state.authToken.isNotEmpty() && ! state.isAGPL())
|
||||
{
|
||||
auto completionCallback = [this] (LicenseQueryThread::ErrorMessageAndType error,
|
||||
LicenseState updatedState)
|
||||
{
|
||||
if (error == LicenseQueryThread::ErrorMessageAndType())
|
||||
{
|
||||
setState (updatedState);
|
||||
}
|
||||
else if ((error.second == LicenseQueryThread::ErrorType::busy
|
||||
|| error.second == LicenseQueryThread::ErrorType::cancelled
|
||||
|| error.second == LicenseQueryThread::ErrorType::connectionError)
|
||||
&& ! hasRetriedLicenseCheck)
|
||||
{
|
||||
hasRetriedLicenseCheck = true;
|
||||
startTimer (10000);
|
||||
}
|
||||
};
|
||||
|
||||
licenseQueryThread.checkLicenseValidity (state, std::move (completionCallback));
|
||||
}
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
stopTimer();
|
||||
checkLicense();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
LicenseState state = licenseStateFromSettings (getGlobalProperties());
|
||||
|
||||
ListenerList<LicenseStateListener> stateListeners;
|
||||
LicenseQueryThread licenseQueryThread;
|
||||
bool hasRetriedLicenseCheck = false;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LicenseController)
|
||||
};
|
||||
|
|
@ -1,380 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//==============================================================================
|
||||
namespace LicenseHelpers
|
||||
{
|
||||
inline LicenseState::Type licenseTypeForString (const String& licenseString)
|
||||
{
|
||||
if (licenseString == "juce-pro") return LicenseState::Type::pro;
|
||||
if (licenseString == "juce-indie") return LicenseState::Type::indie;
|
||||
if (licenseString == "juce-edu") return LicenseState::Type::educational;
|
||||
if (licenseString == "juce-personal") return LicenseState::Type::personal;
|
||||
|
||||
jassertfalse; // unknown type
|
||||
return LicenseState::Type::none;
|
||||
}
|
||||
|
||||
using LicenseVersionAndType = std::pair<int, LicenseState::Type>;
|
||||
|
||||
inline LicenseVersionAndType findBestLicense (std::vector<LicenseVersionAndType>&& licenses)
|
||||
{
|
||||
if (licenses.size() == 1)
|
||||
return licenses[0];
|
||||
|
||||
auto getValueForLicenceType = [] (LicenseState::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LicenseState::Type::pro: return 4;
|
||||
case LicenseState::Type::indie: return 3;
|
||||
case LicenseState::Type::educational: return 2;
|
||||
case LicenseState::Type::personal: return 1;
|
||||
case LicenseState::Type::agplv3:
|
||||
case LicenseState::Type::none:
|
||||
default: return -1;
|
||||
}
|
||||
};
|
||||
|
||||
std::sort (licenses.begin(), licenses.end(),
|
||||
[getValueForLicenceType] (const LicenseVersionAndType& l1, const LicenseVersionAndType& l2)
|
||||
{
|
||||
if (l1.first > l2.first)
|
||||
return true;
|
||||
|
||||
if (l1.first == l2.first)
|
||||
return getValueForLicenceType (l1.second) > getValueForLicenceType (l2.second);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
auto findFirstLicense = [&licenses] (bool isPaid)
|
||||
{
|
||||
auto iter = std::find_if (licenses.begin(), licenses.end(),
|
||||
[isPaid] (const LicenseVersionAndType& l)
|
||||
{
|
||||
auto proOrIndie = (l.second == LicenseState::Type::pro || l.second == LicenseState::Type::indie);
|
||||
return isPaid ? proOrIndie : ! proOrIndie;
|
||||
});
|
||||
|
||||
return iter != licenses.end() ? *iter
|
||||
: LicenseVersionAndType();
|
||||
};
|
||||
|
||||
auto newestPaid = findFirstLicense (true);
|
||||
auto newestFree = findFirstLicense (false);
|
||||
|
||||
if (newestPaid.first >= projucerMajorVersion || newestPaid.first >= newestFree.first)
|
||||
return newestPaid;
|
||||
|
||||
return newestFree;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class LicenseQueryThread
|
||||
{
|
||||
public:
|
||||
enum class ErrorType
|
||||
{
|
||||
busy,
|
||||
cancelled,
|
||||
connectionError,
|
||||
webResponseError
|
||||
};
|
||||
|
||||
using ErrorMessageAndType = std::pair<String, ErrorType>;
|
||||
using LicenseQueryCallback = std::function<void (ErrorMessageAndType, LicenseState)>;
|
||||
|
||||
//==============================================================================
|
||||
LicenseQueryThread() = default;
|
||||
|
||||
void checkLicenseValidity (const LicenseState& state, LicenseQueryCallback completionCallback)
|
||||
{
|
||||
if (jobPool.getNumJobs() > 0)
|
||||
{
|
||||
completionCallback ({ {}, ErrorType::busy }, {});
|
||||
return;
|
||||
}
|
||||
|
||||
jobPool.addJob ([this, state, completionCallback]
|
||||
{
|
||||
auto updatedState = state;
|
||||
|
||||
auto result = runTask (std::make_unique<UserLicenseQuery> (state.authToken), updatedState);
|
||||
|
||||
WeakReference<LicenseQueryThread> weakThis (this);
|
||||
MessageManager::callAsync ([weakThis, result, updatedState, completionCallback]
|
||||
{
|
||||
if (weakThis != nullptr)
|
||||
completionCallback (result, updatedState);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void doSignIn (const String& email, const String& password, LicenseQueryCallback completionCallback)
|
||||
{
|
||||
cancelRunningJobs();
|
||||
|
||||
jobPool.addJob ([this, email, password, completionCallback]
|
||||
{
|
||||
LicenseState state;
|
||||
|
||||
auto result = runTask (std::make_unique<UserLogin> (email, password), state);
|
||||
|
||||
if (result == ErrorMessageAndType())
|
||||
result = runTask (std::make_unique<UserLicenseQuery> (state.authToken), state);
|
||||
|
||||
if (result != ErrorMessageAndType())
|
||||
state = {};
|
||||
|
||||
WeakReference<LicenseQueryThread> weakThis (this);
|
||||
MessageManager::callAsync ([weakThis, result, state, completionCallback]
|
||||
{
|
||||
if (weakThis != nullptr)
|
||||
completionCallback (result, state);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void cancelRunningJobs()
|
||||
{
|
||||
jobPool.removeAllJobs (true, 500);
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
struct AccountEnquiryBase
|
||||
{
|
||||
virtual ~AccountEnquiryBase() = default;
|
||||
|
||||
virtual bool isPOSTLikeRequest() const = 0;
|
||||
virtual String getEndpointURLSuffix() const = 0;
|
||||
virtual StringPairArray getParameterNamesAndValues() const = 0;
|
||||
virtual String getExtraHeaders() const = 0;
|
||||
virtual int getSuccessCode() const = 0;
|
||||
virtual String errorCodeToString (int) const = 0;
|
||||
virtual bool parseServerResponse (const String&, LicenseState&) = 0;
|
||||
};
|
||||
|
||||
struct UserLogin final : public AccountEnquiryBase
|
||||
{
|
||||
UserLogin (const String& e, const String& p)
|
||||
: userEmail (e), userPassword (p)
|
||||
{
|
||||
}
|
||||
|
||||
bool isPOSTLikeRequest() const override { return true; }
|
||||
String getEndpointURLSuffix() const override { return "/authenticate/projucer"; }
|
||||
int getSuccessCode() const override { return 200; }
|
||||
|
||||
StringPairArray getParameterNamesAndValues() const override
|
||||
{
|
||||
StringPairArray namesAndValues;
|
||||
namesAndValues.set ("email", userEmail);
|
||||
namesAndValues.set ("password", userPassword);
|
||||
|
||||
return namesAndValues;
|
||||
}
|
||||
|
||||
String getExtraHeaders() const override
|
||||
{
|
||||
return "Content-Type: application/json";
|
||||
}
|
||||
|
||||
String errorCodeToString (int errorCode) const override
|
||||
{
|
||||
switch (errorCode)
|
||||
{
|
||||
case 400: return "Please enter your email and password to sign in.";
|
||||
case 401: return "Your email and password are incorrect.";
|
||||
case 451: return "Access denied.";
|
||||
default: return "Something went wrong, please try again.";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseServerResponse (const String& serverResponse, LicenseState& licenseState) override
|
||||
{
|
||||
auto json = JSON::parse (serverResponse);
|
||||
|
||||
licenseState.authToken = json.getProperty ("token", {}).toString();
|
||||
licenseState.username = json.getProperty ("user", {}).getProperty ("username", {}).toString();
|
||||
|
||||
return (licenseState.authToken.isNotEmpty() && licenseState.username.isNotEmpty());
|
||||
}
|
||||
|
||||
String userEmail, userPassword;
|
||||
};
|
||||
|
||||
struct UserLicenseQuery final : public AccountEnquiryBase
|
||||
{
|
||||
UserLicenseQuery (const String& authToken)
|
||||
: userAuthToken (authToken)
|
||||
{
|
||||
}
|
||||
|
||||
bool isPOSTLikeRequest() const override { return false; }
|
||||
String getEndpointURLSuffix() const override { return "/user/licences/projucer"; }
|
||||
int getSuccessCode() const override { return 200; }
|
||||
|
||||
StringPairArray getParameterNamesAndValues() const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
String getExtraHeaders() const override
|
||||
{
|
||||
return "x-access-token: " + userAuthToken;
|
||||
}
|
||||
|
||||
String errorCodeToString (int errorCode) const override
|
||||
{
|
||||
switch (errorCode)
|
||||
{
|
||||
case 401: return "User not found or could not be verified.";
|
||||
default: return "User licenses info fetch failed (unknown error).";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseServerResponse (const String& serverResponse, LicenseState& licenseState) override
|
||||
{
|
||||
auto json = JSON::parse (serverResponse);
|
||||
|
||||
if (auto* licensesJson = json.getArray())
|
||||
{
|
||||
std::vector<LicenseHelpers::LicenseVersionAndType> licenses;
|
||||
|
||||
for (auto& license : *licensesJson)
|
||||
{
|
||||
auto version = license.getProperty ("product_version", {}).toString().trim();
|
||||
auto type = license.getProperty ("licence_type", {}).toString();
|
||||
auto status = license.getProperty ("status", {}).toString();
|
||||
|
||||
if (status == "active" && type.isNotEmpty() && version.isNotEmpty())
|
||||
licenses.push_back ({ version.getIntValue(), LicenseHelpers::licenseTypeForString (type) });
|
||||
}
|
||||
|
||||
if (! licenses.empty())
|
||||
{
|
||||
auto bestLicense = LicenseHelpers::findBestLicense (std::move (licenses));
|
||||
|
||||
licenseState.version = bestLicense.first;
|
||||
licenseState.type = bestLicense.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String userAuthToken;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static String postDataStringAsJSON (const StringPairArray& parameters)
|
||||
{
|
||||
DynamicObject::Ptr d (new DynamicObject());
|
||||
|
||||
for (auto& key : parameters.getAllKeys())
|
||||
d->setProperty (key, parameters[key]);
|
||||
|
||||
return JSON::toString (var (d.get()));
|
||||
}
|
||||
|
||||
static ErrorMessageAndType runTask (std::unique_ptr<AccountEnquiryBase> accountEnquiryTask, LicenseState& state)
|
||||
{
|
||||
const ErrorMessageAndType cancelledError ("Cancelled.", ErrorType::cancelled);
|
||||
const String endpointURL ("https://api.juce.com/api/v1");
|
||||
|
||||
URL url (endpointURL + accountEnquiryTask->getEndpointURLSuffix());
|
||||
|
||||
auto isPOST = accountEnquiryTask->isPOSTLikeRequest();
|
||||
|
||||
if (isPOST)
|
||||
url = url.withPOSTData (postDataStringAsJSON (accountEnquiryTask->getParameterNamesAndValues()));
|
||||
|
||||
if (ThreadPoolJob::getCurrentThreadPoolJob()->shouldExit())
|
||||
return cancelledError;
|
||||
|
||||
int statusCode = 0;
|
||||
auto urlStream = url.createInputStream (URL::InputStreamOptions (isPOST ? URL::ParameterHandling::inPostData
|
||||
: URL::ParameterHandling::inAddress)
|
||||
.withExtraHeaders (accountEnquiryTask->getExtraHeaders())
|
||||
.withConnectionTimeoutMs (5000)
|
||||
.withStatusCode (&statusCode));
|
||||
|
||||
if (urlStream == nullptr)
|
||||
return { "Failed to connect to the web server.", ErrorType::connectionError };
|
||||
|
||||
if (statusCode != accountEnquiryTask->getSuccessCode())
|
||||
return { accountEnquiryTask->errorCodeToString (statusCode), ErrorType::webResponseError };
|
||||
|
||||
if (ThreadPoolJob::getCurrentThreadPoolJob()->shouldExit())
|
||||
return cancelledError;
|
||||
|
||||
String response;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char buffer [8192] = "";
|
||||
auto num = urlStream->read (buffer, sizeof (buffer));
|
||||
|
||||
if (ThreadPoolJob::getCurrentThreadPoolJob()->shouldExit())
|
||||
return cancelledError;
|
||||
|
||||
if (num <= 0)
|
||||
break;
|
||||
|
||||
response += buffer;
|
||||
}
|
||||
|
||||
if (ThreadPoolJob::getCurrentThreadPoolJob()->shouldExit())
|
||||
return cancelledError;
|
||||
|
||||
if (! accountEnquiryTask->parseServerResponse (response, state))
|
||||
return { "Failed to parse server response.", ErrorType::webResponseError };
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ThreadPool jobPool { ThreadPoolOptions{}.withNumberOfThreads (1) };
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_WEAK_REFERENCEABLE (LicenseQueryThread)
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LicenseQueryThread)
|
||||
};
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct LicenseState
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
none,
|
||||
agplv3,
|
||||
personal,
|
||||
educational,
|
||||
indie,
|
||||
pro
|
||||
};
|
||||
|
||||
LicenseState() = default;
|
||||
|
||||
LicenseState (Type t, int v, String user, String token)
|
||||
: type (t), version (v), username (user), authToken (token)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator== (const LicenseState& other) const noexcept
|
||||
{
|
||||
return type == other.type
|
||||
&& version == other.version
|
||||
&& username == other.username
|
||||
&& authToken == other.authToken;
|
||||
}
|
||||
|
||||
bool operator != (const LicenseState& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
bool isSignedIn() const noexcept { return isAGPL() || (version > 0 && username.isNotEmpty()); }
|
||||
bool isOldLicense() const noexcept { return isSignedIn() && version < projucerMajorVersion; }
|
||||
bool isAGPL() const noexcept { return type == Type::agplv3; }
|
||||
bool isPersonalOrNone() const noexcept { return type == Type::none || type == Type::personal; }
|
||||
|
||||
String getLicenseTypeString() const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::none: return "No license";
|
||||
case Type::agplv3: return "AGPLv3";
|
||||
case Type::personal: return "Personal";
|
||||
case Type::educational: return "Educational";
|
||||
case Type::indie: return "Indie";
|
||||
case Type::pro: return "Pro";
|
||||
default: break;
|
||||
};
|
||||
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
Type type = Type::none;
|
||||
int version = -1;
|
||||
String username, authToken;
|
||||
};
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../../Project/UI/jucer_UserAvatarComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
class LoginFormComponent final : public Component
|
||||
{
|
||||
public:
|
||||
LoginFormComponent (MainWindow& window)
|
||||
: mainWindow (window)
|
||||
{
|
||||
setTitle ("Login");
|
||||
setFocusContainerType (FocusContainerType::focusContainer);
|
||||
|
||||
addAndMakeVisible (emailBox);
|
||||
emailBox.setTextToShowWhenEmpty ("Email", Colours::black.withAlpha (0.2f));
|
||||
emailBox.setJustification (Justification::centredLeft);
|
||||
emailBox.onReturnKey = [this] { submitDetails(); };
|
||||
emailBox.setTitle ("Email");
|
||||
|
||||
addAndMakeVisible (passwordBox);
|
||||
passwordBox.setTextToShowWhenEmpty ("Password", Colours::black.withAlpha (0.2f));
|
||||
passwordBox.setPasswordCharacter ((juce_wchar) 0x2022);
|
||||
passwordBox.setJustification (Justification::centredLeft);
|
||||
passwordBox.onReturnKey = [this] { submitDetails(); };
|
||||
passwordBox.setTitle ("Password");
|
||||
|
||||
addAndMakeVisible (logInButton);
|
||||
logInButton.onClick = [this] { submitDetails(); };
|
||||
|
||||
addAndMakeVisible (enableAGPLButton);
|
||||
enableAGPLButton.onClick = [this]
|
||||
{
|
||||
ProjucerApplication::getApp().getLicenseController().setState (LicenseController::getAGPLState());
|
||||
mainWindow.hideLoginFormOverlay();
|
||||
};
|
||||
|
||||
addAndMakeVisible (userAvatar);
|
||||
|
||||
addAndMakeVisible (createAccountLabel);
|
||||
createAccountLabel.setFont (FontOptions (14.0f, Font::underlined));
|
||||
createAccountLabel.addMouseListener (this, false);
|
||||
createAccountLabel.setMouseCursor (MouseCursor::PointingHandCursor);
|
||||
|
||||
addAndMakeVisible (errorMessageLabel);
|
||||
errorMessageLabel.setMinimumHorizontalScale (1.0f);
|
||||
errorMessageLabel.setFont (FontOptions { 12.0f });
|
||||
errorMessageLabel.setColour (Label::textColourId, Colours::red);
|
||||
errorMessageLabel.setVisible (false);
|
||||
|
||||
dismissButton.setShape (getLookAndFeel().getCrossShape (1.0f), false, true, false);
|
||||
addAndMakeVisible (dismissButton);
|
||||
dismissButton.onClick = [this] { mainWindow.hideLoginFormOverlay(); };
|
||||
dismissButton.setTitle ("Dismiss");
|
||||
|
||||
setWantsKeyboardFocus (true);
|
||||
setOpaque (true);
|
||||
|
||||
updateLookAndFeel();
|
||||
|
||||
setSize (300, 350);
|
||||
}
|
||||
|
||||
~LoginFormComponent() override
|
||||
{
|
||||
ProjucerApplication::getApp().getLicenseController().cancelSignIn();
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto bounds = getLocalBounds().reduced (20);
|
||||
auto spacing = bounds.getHeight() / 20;
|
||||
|
||||
userAvatar.setBounds (bounds.removeFromTop (iconHeight).reduced ((bounds.getWidth() / 2) - (iconHeight / 2), 0));
|
||||
|
||||
errorMessageLabel.setBounds (bounds.removeFromTop (spacing));
|
||||
bounds.removeFromTop (spacing / 2);
|
||||
|
||||
auto textEditorHeight = bounds.getHeight() / 5;
|
||||
|
||||
emailBox.setBounds (bounds.removeFromTop (textEditorHeight));
|
||||
bounds.removeFromTop (spacing);
|
||||
|
||||
passwordBox.setBounds (bounds.removeFromTop (textEditorHeight));
|
||||
bounds.removeFromTop (spacing * 2);
|
||||
|
||||
emailBox.setFont (FontOptions ((float) textEditorHeight / 2.5f));
|
||||
passwordBox.setFont (FontOptions ((float) textEditorHeight / 2.5f));
|
||||
|
||||
logInButton.setBounds (bounds.removeFromTop (textEditorHeight));
|
||||
|
||||
auto slice = bounds.removeFromTop (textEditorHeight);
|
||||
createAccountLabel.setBounds (slice.removeFromLeft (createAccountLabel.getFont().getStringWidth (createAccountLabel.getText()) + 5));
|
||||
slice.removeFromLeft (15);
|
||||
enableAGPLButton.setBounds (slice.reduced (0, 5));
|
||||
|
||||
dismissButton.setBounds (getLocalBounds().reduced (10).removeFromTop (20).removeFromRight (20));
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (findColour (secondaryBackgroundColourId).contrasting (0.1f));
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& event) override
|
||||
{
|
||||
if (event.eventComponent == &createAccountLabel)
|
||||
URL ("https://juce.com/verification/register").launchInDefaultBrowser();
|
||||
}
|
||||
|
||||
void updateLookAndFeel()
|
||||
{
|
||||
enableAGPLButton.setColour (TextButton::buttonColourId, findColour (secondaryButtonBackgroundColourId));
|
||||
}
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
updateLookAndFeel();
|
||||
}
|
||||
|
||||
private:
|
||||
class ProgressButton final : public TextButton,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
ProgressButton (const String& buttonName)
|
||||
: TextButton (buttonName), text (buttonName)
|
||||
{
|
||||
}
|
||||
|
||||
void setBusy (bool shouldBeBusy)
|
||||
{
|
||||
isInProgress = shouldBeBusy;
|
||||
|
||||
if (isInProgress)
|
||||
{
|
||||
setEnabled (false);
|
||||
setButtonText ({});
|
||||
startTimerHz (30);
|
||||
}
|
||||
else
|
||||
{
|
||||
setEnabled (true);
|
||||
setButtonText (text);
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
TextButton::paint (g);
|
||||
|
||||
if (isInProgress)
|
||||
{
|
||||
auto size = getHeight() - 10;
|
||||
auto halfSize = size / 2;
|
||||
|
||||
getLookAndFeel().drawSpinningWaitAnimation (g, Colours::white,
|
||||
(getWidth() / 2) - halfSize, (getHeight() / 2) - halfSize,
|
||||
size, size);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void timerCallback() override
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
|
||||
String text;
|
||||
bool isInProgress = false;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void updateLoginButtonStates (bool isLoggingIn)
|
||||
{
|
||||
logInButton.setBusy (isLoggingIn);
|
||||
|
||||
emailBox.setEnabled (! isLoggingIn);
|
||||
passwordBox.setEnabled (! isLoggingIn);
|
||||
}
|
||||
|
||||
void submitDetails()
|
||||
{
|
||||
auto loginFormError = checkLoginFormsAreValid();
|
||||
|
||||
if (loginFormError.isNotEmpty())
|
||||
{
|
||||
showErrorMessage (loginFormError);
|
||||
return;
|
||||
}
|
||||
|
||||
updateLoginButtonStates (true);
|
||||
|
||||
auto completionCallback = [weakThis = SafePointer<LoginFormComponent> { this }] (const String& errorMessage)
|
||||
{
|
||||
if (weakThis == nullptr)
|
||||
return;
|
||||
|
||||
weakThis->updateLoginButtonStates (false);
|
||||
|
||||
if (errorMessage.isNotEmpty())
|
||||
{
|
||||
weakThis->showErrorMessage (errorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
weakThis->hideErrorMessage();
|
||||
weakThis->mainWindow.hideLoginFormOverlay();
|
||||
ProjucerApplication::getApp().getCommandManager().commandStatusChanged();
|
||||
}
|
||||
};
|
||||
|
||||
ProjucerApplication::getApp().getLicenseController().signIn (emailBox.getText(), passwordBox.getText(),
|
||||
std::move (completionCallback));
|
||||
}
|
||||
|
||||
String checkLoginFormsAreValid() const
|
||||
{
|
||||
auto email = emailBox.getText();
|
||||
|
||||
if (email.isEmpty() || email.indexOfChar ('@') < 0)
|
||||
return "Please enter a valid email.";
|
||||
|
||||
auto password = passwordBox.getText();
|
||||
|
||||
if (password.isEmpty() || password.length() < 8)
|
||||
return "Please enter a valid password.";
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void showErrorMessage (const String& errorMessage)
|
||||
{
|
||||
errorMessageLabel.setText (errorMessage, dontSendNotification);
|
||||
errorMessageLabel.setVisible (true);
|
||||
}
|
||||
|
||||
void hideErrorMessage()
|
||||
{
|
||||
errorMessageLabel.setText ({}, dontSendNotification);
|
||||
errorMessageLabel.setVisible (false);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static constexpr int iconHeight = 50;
|
||||
|
||||
MainWindow& mainWindow;
|
||||
|
||||
TextEditor emailBox, passwordBox;
|
||||
ProgressButton logInButton { "Sign In" };
|
||||
TextButton enableAGPLButton { "Enable AGPLv3 Mode" };
|
||||
ShapeButton dismissButton { {},
|
||||
findColour (treeIconColourId),
|
||||
findColour (treeIconColourId).overlaidWith (findColour (defaultHighlightedTextColourId).withAlpha (0.2f)),
|
||||
findColour (treeIconColourId).overlaidWith (findColour (defaultHighlightedTextColourId).withAlpha (0.4f)) };
|
||||
UserAvatarComponent userAvatar { false };
|
||||
Label createAccountLabel { {}, "Create an account" },
|
||||
errorMessageLabel { {}, {} };
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LoginFormComponent)
|
||||
};
|
||||
|
|
@ -161,7 +161,6 @@ void ProjucerApplication::handleAsyncUpdate()
|
|||
|
||||
void ProjucerApplication::doBasicApplicationSetup()
|
||||
{
|
||||
licenseController = std::make_unique<LicenseController>();
|
||||
LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
|
||||
initCommandManager();
|
||||
icons = std::make_unique<Icons>();
|
||||
|
|
@ -373,8 +372,6 @@ PopupMenu ProjucerApplication::createFileMenu()
|
|||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager.get(), CommandIDs::openInIDE);
|
||||
menu.addCommandItem (commandManager.get(), CommandIDs::saveAndOpenInIDE);
|
||||
menu.addSeparator();
|
||||
menu.addCommandItem (commandManager.get(), CommandIDs::loginLogout);
|
||||
|
||||
#if ! JUCE_MAC
|
||||
menu.addCommandItem (commandManager.get(), CommandIDs::showAboutWindow);
|
||||
|
|
@ -924,8 +921,7 @@ void ProjucerApplication::getAllCommands (Array <CommandID>& commands)
|
|||
CommandIDs::showForum,
|
||||
CommandIDs::showAPIModules,
|
||||
CommandIDs::showAPIClasses,
|
||||
CommandIDs::showTutorials,
|
||||
CommandIDs::loginLogout };
|
||||
CommandIDs::showTutorials };
|
||||
|
||||
commands.addArray (ids, numElementsInArray (ids));
|
||||
}
|
||||
|
|
@ -1031,19 +1027,6 @@ void ProjucerApplication::getCommandInfo (CommandID commandID, ApplicationComman
|
|||
result.setInfo ("JUCE Tutorials", "Shows the JUCE tutorials in a browser", CommandCategories::general, 0);
|
||||
break;
|
||||
|
||||
case CommandIDs::loginLogout:
|
||||
{
|
||||
auto licenseState = licenseController->getCurrentState();
|
||||
|
||||
if (licenseState.isAGPL())
|
||||
result.setInfo ("Disable AGPLv3 mode", "Disables AGPLv3 mode", CommandCategories::general, 0);
|
||||
else
|
||||
result.setInfo (licenseState.isSignedIn() ? String ("Sign out ") + licenseState.username + "..." : String ("Sign in..."),
|
||||
"Sign out of your JUCE account",
|
||||
CommandCategories::general, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
JUCEApplication::getCommandInfo (commandID, result);
|
||||
break;
|
||||
|
|
@ -1074,7 +1057,6 @@ bool ProjucerApplication::perform (const InvocationInfo& info)
|
|||
case CommandIDs::showAPIModules: launchModulesBrowser(); break;
|
||||
case CommandIDs::showAPIClasses: launchClassesBrowser(); break;
|
||||
case CommandIDs::showTutorials: launchTutorialsBrowser(); break;
|
||||
case CommandIDs::loginLogout: doLoginOrLogout(); break;
|
||||
default: return JUCEApplication::perform (info);
|
||||
}
|
||||
|
||||
|
|
@ -1307,26 +1289,6 @@ void ProjucerApplication::launchTutorialsBrowser()
|
|||
tutorialsLink.launchInDefaultBrowser();
|
||||
}
|
||||
|
||||
void ProjucerApplication::doLoginOrLogout()
|
||||
{
|
||||
if (licenseController->getCurrentState().isSignedIn())
|
||||
{
|
||||
licenseController->resetState();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (auto* window = mainWindowList.getMainWindowWithLoginFormOpen())
|
||||
{
|
||||
window->toFront (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWindowList.createWindowIfNoneAreOpen();
|
||||
mainWindowList.getFrontmostWindow()->showLoginFormOverlay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct FileWithTime
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "UserAccount/jucer_LicenseController.h"
|
||||
#include "jucer_MainWindow.h"
|
||||
#include "../Project/Modules/jucer_Modules.h"
|
||||
#include "jucer_AutoUpdater.h"
|
||||
|
|
@ -87,8 +86,6 @@ public:
|
|||
AvailableModulesList& getJUCEPathModulesList() { return jucePathModulesList; }
|
||||
AvailableModulesList& getUserPathsModulesList() { return userPathsModulesList; }
|
||||
|
||||
LicenseController& getLicenseController() { return *licenseController; }
|
||||
|
||||
bool isAutomaticVersionCheckingEnabled() const;
|
||||
void setAutomaticVersionCheckingEnabled (bool shouldBeEnabled);
|
||||
|
||||
|
|
@ -169,9 +166,6 @@ private:
|
|||
void launchClassesBrowser();
|
||||
void launchTutorialsBrowser();
|
||||
|
||||
void doLoginOrLogout();
|
||||
void showLoginForm();
|
||||
|
||||
void enableOrDisableGUIEditor();
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -208,8 +202,6 @@ private:
|
|||
#endif
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<LicenseController> licenseController;
|
||||
|
||||
std::unique_ptr<TooltipWindow> tooltipWindow;
|
||||
AvailableModulesList jucePathModulesList, userPathsModulesList;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,8 +95,6 @@ namespace CommandIDs
|
|||
zoomNormal = 0x300073,
|
||||
spaceBarDrag = 0x300074,
|
||||
|
||||
loginLogout = 0x300090,
|
||||
|
||||
showForum = 0x300100,
|
||||
showAPIModules = 0x300101,
|
||||
showAPIClasses = 0x300102,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include "StartPage/jucer_StartPageComponent.h"
|
||||
#include "../Utility/UI/jucer_JucerTreeViewBase.h"
|
||||
#include "../ProjectSaving/jucer_ProjectSaver.h"
|
||||
#include "UserAccount/jucer_LoginFormComponent.h"
|
||||
#include "../Project/UI/jucer_ProjectContentComponent.h"
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -78,11 +77,6 @@ public:
|
|||
g.drawImage (componentImage, getLocalBounds().toFloat());
|
||||
}
|
||||
|
||||
void inputAttemptWhenModal() override
|
||||
{
|
||||
mainWindow.hideLoginFormOverlay();
|
||||
}
|
||||
|
||||
private:
|
||||
void componentPeerChanged() override {}
|
||||
|
||||
|
|
@ -96,12 +90,6 @@ private:
|
|||
|
||||
void handleAsyncUpdate() override { resized(); }
|
||||
|
||||
void mouseUp (const MouseEvent& event) override
|
||||
{
|
||||
if (event.eventComponent == this)
|
||||
mainWindow.hideLoginFormOverlay();
|
||||
}
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
refreshBackgroundImage();
|
||||
|
|
@ -624,18 +612,6 @@ void MainWindow::showStartPage()
|
|||
getContentComponent()->grabKeyboardFocus();
|
||||
}
|
||||
|
||||
void MainWindow::showLoginFormOverlay()
|
||||
{
|
||||
blurOverlayComponent = std::make_unique<BlurOverlayWithComponent> (*this, std::make_unique<LoginFormComponent> (*this));
|
||||
loginFormOpen = true;
|
||||
}
|
||||
|
||||
void MainWindow::hideLoginFormOverlay()
|
||||
{
|
||||
blurOverlayComponent.reset();
|
||||
loginFormOpen = false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
ApplicationCommandTarget* MainWindow::getNextCommandTarget()
|
||||
{
|
||||
|
|
@ -954,15 +930,6 @@ MainWindow* MainWindowList::getMainWindowForFile (const File& file)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
MainWindow* MainWindowList::getMainWindowWithLoginFormOpen()
|
||||
{
|
||||
for (auto* window : windows)
|
||||
if (window->isShowingLoginForm())
|
||||
return window;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MainWindowList::checkWindowBounds (MainWindow& windowToCheck)
|
||||
{
|
||||
auto avoidSuperimposedWindows = [&]
|
||||
|
|
|
|||
|
|
@ -76,10 +76,6 @@ public:
|
|||
|
||||
void showStartPage();
|
||||
|
||||
void showLoginFormOverlay();
|
||||
void hideLoginFormOverlay();
|
||||
bool isShowingLoginForm() const noexcept { return loginFormOpen; }
|
||||
|
||||
bool isInterestedInFileDrag (const StringArray& files) override;
|
||||
void filesDropped (const StringArray& filenames, int mouseX, int mouseY) override;
|
||||
|
||||
|
|
@ -111,7 +107,6 @@ private:
|
|||
Value projectNameValue;
|
||||
|
||||
std::unique_ptr<Component> blurOverlayComponent;
|
||||
bool loginFormOpen = false;
|
||||
|
||||
ScopedMessageBox messageBox;
|
||||
|
||||
|
|
@ -138,7 +133,6 @@ public:
|
|||
MainWindow* getFrontmostWindow (bool createIfNotFound = true);
|
||||
MainWindow* getOrCreateEmptyWindow();
|
||||
MainWindow* getMainWindowForFile (const File&);
|
||||
MainWindow* getMainWindowWithLoginFormOpen();
|
||||
|
||||
Project* getFrontmostProject();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue