Refactor lobby terms and conditions UI from 80dbd1f2a3 / D1568 to a new terms dialog UI and reuse that for mod.io and the UserReporter, refs #5257, #5218.

Reuse all existing strings, use a FileExists hack for mod.io until the
new strings are committed.
Rename prelobby/common/terms/terms.js to termslobby.js for easier
distinction from common/terms.js.

Based on patch by: bb
Differential Revision: https://code.wildfiregames.com/D1602
refs https://code.wildfiregames.com/D1601
refs https://github.com/bb-bb/0ad/tree/terms
refs https://github.com/elexis1/0ad/tree/terms

This was SVN commit r21887.
This commit is contained in:
elexis 2018-09-14 15:14:48 +00:00
parent 41395ffe5d
commit da49aa1541
17 changed files with 234 additions and 61 deletions

View File

@ -438,6 +438,7 @@ enabledmods = "mod public"
[modio]
public_key = "RWQBhIRg+dOifTWlwgYHe8RfD8bqoDh1cCvygboAl3GOUKiCo0NlF4fw" ; Public key corresponding to the private key valid mods are signed with
disclaimer = "0" ; Version (hash) of the Disclaimer that the user has accepted
[modio.v1]
baseurl = "https://api.mod.io/v1"
@ -476,6 +477,7 @@ debug = false ; Print error messages each time a translation
[userreport] ; Opt-in online user reporting system
url = "http://feedback.wildfiregames.com/report/upload/v1/"
terms = "0" ; Version (hash) of the UserReporter Terms that the user has accepted
[view] ; Camera control settings
scroll.speed = 120.0

View File

@ -0,0 +1,51 @@
var g_Terms = {};
function initTerms(terms)
{
g_Terms = terms;
}
function openTerms(page)
{
Engine.PushGuiPage("page_termsdialog.xml", {
"file": g_Terms[page].file,
"title": g_Terms[page].title,
"buttons": g_Terms[page].buttons || [],
"page": page,
"callback": "acceptTerms"
});
}
function acceptTerms(data)
{
g_Terms[data.page].accepted = data.accepted;
let value = data.accepted ? getTermsHash(data.page) : "0";
Engine.ConfigDB_CreateValue("user", g_Terms[data.page].config, value);
Engine.ConfigDB_WriteValueToFile("user", g_Terms[data.page].config, value, "config/user.cfg");
if (g_Terms[data.page].callback)
g_Terms[data.page].callback(data);
}
function checkTerms()
{
for (let page in g_Terms)
if (!g_Terms[page].accepted)
return g_Terms[page].instruction || page;
return "";
}
function getTermsHash(page)
{
return Engine.CalculateMD5(
(g_Terms[page].salt ? g_Terms[page].salt() : "") +
(Engine.FileExists(g_Terms[page].file) ? Engine.ReadFile(g_Terms[page].file) : g_Terms[page].file));
}
function loadTermsAcceptance()
{
for (let page in g_Terms)
g_Terms[page].accepted = Engine.ConfigDB_GetValue("user", g_Terms[page].config) == getTermsHash(page);
}

View File

@ -60,6 +60,7 @@ var g_ColorDependenciesNotMet = "255 100 100";
function init(data, hotloadData)
{
g_InstalledMods = data && data.installedMods || hotloadData && hotloadData.installedMods || [];
initMods();
initGUIButtons(data);
}
@ -305,23 +306,6 @@ function isDependencyMet(dependency)
(!operator || versionSatisfied(g_Mods[folder].version, operator[0], version)));
}
function modIo()
{
messageBox(500, 250,
translate("You are about to connect to the mod.io online service. This provides easy access to community-made mods, but is not under the control of Wildfire Games.\n\nWhile we have taken care to make this secure, we cannot guarantee with absolute certainty that this is not a security risk.\n\nDo you really want to connect?"),
translate("Connect to mod.io?"),
[translate("Cancel"), translateWithContext("mod.io connection message box", "Connect")],
[
null,
() => {
Engine.PushGuiPage("page_modio.xml", {
"callback": "initMods"
});
}
]
);
}
/**
* Compares the given versions using the given operator.
* '-' or '_' is ignored. Only numbers are supported.

View File

@ -192,7 +192,7 @@
<object type="button" style="ModernButtonRed" size="100%-606 100%-44 100%-412 100%-16">
<translatableAttribute id="caption">Download Mods</translatableAttribute>
<action on="Press">modIo();</action>
<action on="Press">downloadModsButton();</action>
</object>
<object name="saveConfigurationButton" type="button" style="ModernButtonRed" size="100%-408 100%-44 100%-214 100%-16">

View File

@ -0,0 +1,22 @@
function downloadModsButton()
{
initTerms({
"Disclaimer": {
"title": translate("Download Mods"),
"file": translate("You are about to connect to the mod.io online service. This provides easy access to community-made mods, but is not under the control of Wildfire Games.\n\nWhile we have taken care to make this secure, we cannot guarantee with absolute certainty that this is not a security risk.\n\nDo you really want to connect?"),
"config": "modio.disclaimer",
"accepted": false,
"callback": openModIo
}
});
openTerms("Disclaimer");
}
function openModIo(data)
{
if (data.accepted)
Engine.PushGuiPage("page_modio.xml", {
"callback": "initMods"
});
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<page>
<include>common/modern/setup.xml</include>
<include>common/modern/styles.xml</include>
<include>common/modern/sprites.xml</include>
<include>termsdialog/termsdialog.xml</include>
</page>

View File

@ -0,0 +1,21 @@
var g_TermsPage = "";
function init(data)
{
g_TermsPage = data.page;
Engine.GetGUIObjectByName("title").caption = data.title;
Engine.GetGUIObjectByName("mainText").caption =
Engine.FileExists(data.file) ?
Engine.TranslateLines(Engine.ReadFile(data.file)) :
data.file;
}
function closeTerms(accepted)
{
Engine.PopGuiPageCB({
"page": g_TermsPage,
"accepted": accepted
});
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<objects>
<script directory="gui/common/"/>
<script directory="gui/termsdialog/"/>
<object type="image" z="0" sprite="ModernFade"/>
<object type="image" style="ModernDialog" size="50%-360 50%-290 50%+360 50%+290">
<object name="title" style="ModernLabelText" type="text" size="50%-128 -18 50%+128 14"/>
<object size="20 20 100%-20 100%-50">
<object name="mainTextPanel" type="image" sprite="ModernFade" size="0 0 100% 100%">
<object name="mainText" type="text" style="ModernTextPanel"/>
</object>
</object>
<object size="100%-355 100%-44 100% 100%-16">
<object type="button" style="ModernButtonRed" size="0 0 160 100%" hotkey="cancel">
<translatableAttribute id="caption">Cancel</translatableAttribute>
<action on="Press">closeTerms(false);</action>
</object>
<object type="button" style="ModernButtonRed" size="170 0 330 100%">
<translatableAttribute id="caption" context="mod.io connection message box">Connect</translatableAttribute>
<action on="Press">closeTerms(true);</action>
</object>
</object>
</object>
</objects>

View File

@ -1,3 +1,16 @@
var g_TermsUserReport = {
"TermsAndConditions": {
"title": translate("Technical Details"),
"instruction": "",
"file": "gui/manual/userreport.txt",
"config": "userreport.terms",
"callback": data => {
setUserReportEnabled(data.accepted);
},
"accepted": false
}
};
var g_UserReportStatusFormat = {
"disabled": data => translate("disabled"),
"proxy": data => translate("connecting to server"),
@ -17,7 +30,10 @@ var g_UserReportStatusFormat = {
function initUserReport()
{
setUserReportEnabled(Engine.IsUserReportEnabled());
initTerms(g_TermsUserReport);
loadTermsAcceptance();
setUserReportEnabled(!checkTerms() && Engine.IsUserReportEnabled());
}
function setUserReportEnabled(enabled)
@ -28,18 +44,19 @@ function setUserReportEnabled(enabled)
function updateUserReportButtons()
{
let termsFeedback = checkTerms();
let userReportEnableButton = Engine.GetGUIObjectByName("userReportEnableButton");
userReportEnableButton.caption = Engine.IsUserReportEnabled() ? translate("Disable Feedback") : translate("Enable Feedback");
userReportEnableButton.enabled = !termsFeedback;
userReportEnableButton.tooltip = termsFeedback;
userReportEnableButton.onPress = () => {
setUserReportEnabled(!Engine.IsUserReportEnabled());
};
let userReportTermsButton = Engine.GetGUIObjectByName("userReportTermsButton");
userReportTermsButton.onPress = () => {
Engine.PushGuiPage("page_manual.xml", {
"page": "manual/userreport",
"title": translate("Technical Details")
});
openTerms("TermsAndConditions");
};
}

View File

@ -4,12 +4,15 @@
<object name="feedback" type="text" size="50 0 100%-50 60" style="ModernLabelText" textcolor="red"/>
<object name="cancel" type="button" size="18 65 50%-5 93" style="ModernButtonRed" hotkey="cancel">
<translatableAttribute id="caption">Cancel</translatableAttribute>
<action on="Press">cancelButton();</action>
</object>
<object size="18 65 100%-18 93">
<object name="continue" hotkey="confirm" type="button" size="50%+5 65 100%-18 93" style="ModernButtonRed" enabled="false">
<action on="Press">continueButton();</action>
<object name="cancel" type="button" size="0 0 50%-5 100%" style="ModernButtonRed" hotkey="cancel">
<translatableAttribute id="caption">Cancel</translatableAttribute>
<action on="Press">cancelButton();</action>
</object>
<object name="continue" hotkey="confirm" type="button" size="50%+5 0 100% 100%" style="ModernButtonRed" enabled="false">
<action on="Press">continueButton();</action>
</object>
</object>
</object>

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<object>
<object type="button" size="20 0 100%-20 28" style="ModernButtonRed">
<translatableAttribute id="caption">Terms of Service</translatableAttribute>
<action on="Press">openTerms("Service");</action>
</object>
<object type="button" size="20 40 100%-20 68" style="ModernButtonRed">
<translatableAttribute id="caption">Terms of Use</translatableAttribute>
<action on="Press">openTerms("Use");</action>
</object>
<object type="text" size="20 80 100%-80 110" style="ModernLabelText">
<translatableAttribute id="caption">I have read and agree to the Terms of Service and Terms of Use:</translatableAttribute>
</object>
<object name="agreeTerms" type="checkbox" size="100%-60 85 100%-20 110" style="ModernTickBox" enabled="false">
<action on="Press">updateFeedback();</action>
</object>
</object>

View File

@ -0,0 +1,44 @@
var g_TermsButtonHeight = 40;
function initLobbyTerms()
{
let terms = {
"Service": {
"title": translate("Terms of Service"),
"instruction": translate("Please read the Terms of Service"),
"file": "gui/prelobby/common/terms/Terms_of_Service.txt",
"config": "lobby.terms_of_service",
"salt": () => Engine.GetGUIObjectByName("username").caption,
"accepted": false,
"callback": updateFeedback
},
"Use": {
"title": translate("Terms of Use"),
"instruction": translate("Please read the Terms of Use"),
"file": "gui/prelobby/common/terms/Terms_of_Use.txt",
"config": "lobby.terms_of_use",
"salt": () => Engine.GetGUIObjectByName("username").caption,
"accepted": false,
"callback": updateFeedback
}
};
Object.keys(terms).forEach((page, i) => {
let button = Engine.GetGUIObjectByName("termsButton[" + i + "]");
button.caption = terms[page].title;
button.onPress = () => {
openTerms(page);
};
let size = button.size;
size.top = i * g_TermsButtonHeight;
size.bottom = i * g_TermsButtonHeight + 28;
button.size = size;
});
initTerms(terms);
loadTermsAcceptance();
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<object>
<repeat count="2" var="n">
<object name="termsButton[n]" type="button" size="20 0 100%-20 28" style="ModernButtonRed"/>
</repeat>
</object>

View File

@ -8,7 +8,8 @@ function init()
Engine.GetGUIObjectByName("username").caption = Engine.ConfigDB_GetValue("user", "lobby.login");
Engine.GetGUIObjectByName("password").caption = Engine.ConfigDB_GetValue("user", "lobby.password").substr(0, 10);
loadTermsAcceptance();
initLobbyTerms();
initRememberPassword();
updateFeedback();
@ -43,7 +44,6 @@ function continueButton()
function onLogin(message)
{
saveCredentials();
saveTermsAcceptance();
Engine.SwitchGuiPage("page_lobby.xml", {
"dialog": false

View File

@ -7,7 +7,7 @@
<script directory="gui/prelobby/common/terms/"/>
<script directory="gui/prelobby/login/"/>
<object type="image" style="ModernDialog" size="50%-230 50%-180 50%+230 50%+180">
<object type="image" style="ModernDialog" size="50%-230 50%-160 50%+230 50%+160">
<object style="ModernLabelText" type="text" size="50%-128 -18 50%+128 14">
<translatableAttribute id="caption">Connect to the game lobby</translatableAttribute>
@ -21,11 +21,11 @@
<include file="gui/prelobby/common/credentials/rememberpassword.xml"/>
</object>
<object size="0 130 100% 240">
<include file="gui/prelobby/common/terms/terms.xml"/>
<object size="0 140 100% 210">
<include file="gui/prelobby/common/terms/termslobby.xml"/>
</object>
<object size="0 250 100% 350">
<object size="0 210 100% 310">
<include file="gui/prelobby/common/feedback/feedback.xml"/>
</object>

View File

@ -4,6 +4,8 @@ function init()
Engine.GetGUIObjectByName("continue").caption = translate("Register");
initLobbyTerms();
initRememberPassword();
updateFeedback();
@ -33,7 +35,6 @@ function continueButton()
function onRegistered()
{
saveCredentials();
saveTermsAcceptance();
setFeedback(translate("Registered"));

View File

@ -7,7 +7,7 @@
<script directory="gui/prelobby/common/terms/"/>
<script directory="gui/prelobby/register/"/>
<object type="image" style="ModernDialog" size="50%-230 50%-205 50%+230 50%+205">
<object type="image" style="ModernDialog" size="50%-230 50%-185 50%+230 50%+185">
<object style="ModernLabelText" type="text" size="50%-128 -18 50%+128 14">
<translatableAttribute id="caption">Registration</translatableAttribute>
@ -25,11 +25,11 @@
<include file="gui/prelobby/common/credentials/rememberpassword.xml"/>
</object>
<object size="0 180 100% 290">
<include file="gui/prelobby/common/terms/terms.xml"/>
<object size="0 180 100% 260">
<include file="gui/prelobby/common/terms/termslobby.xml"/>
</object>
<object size="0 300 100% 400">
<object size="0 260 100% 400">
<include file="gui/prelobby/common/feedback/feedback.xml"/>
</object>