mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Reimplement dialog helpers
In a Dialog class with static members. No tests for these yet as I'm still trying to work out how best to test code that relies on the DOM and custom elements and their APIs.
This commit is contained in:
+1
-1
@@ -1108,6 +1108,6 @@ namespace loot {
|
||||
|
||||
void Handler::SendProgressUpdate(CefRefPtr<CefFrame> frame, const std::string& message) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Sending progress update: " << message;
|
||||
frame->ExecuteJavaScript("showProgress('" + message + "');", frame->GetURL(), 0);
|
||||
frame->ExecuteJavaScript("loot.Dialog.showProgress('" + message + "');", frame->GetURL(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ html /deep/ ::-webkit-scrollbar-track {
|
||||
html /deep/ ::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.26);
|
||||
}
|
||||
paper-button[autofocus] {
|
||||
html /deep/ paper-button[autofocus] {
|
||||
color: #64B5F6;
|
||||
}
|
||||
.hidden {
|
||||
|
||||
@@ -16,74 +16,62 @@ was pressed.
|
||||
<link rel="import" href="../../../../bower_components/paper-button/paper-button.html">
|
||||
<link rel="import" href="loot-dialog.html">
|
||||
|
||||
<polymer-element name="loot-message-dialog" extends="loot-dialog">
|
||||
<polymer-element name="loot-message-dialog">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
#dialog {
|
||||
max-width: 50%;
|
||||
}
|
||||
</style>
|
||||
<shadow></shadow>
|
||||
<loot-dialog id="dialog">
|
||||
<content></content>
|
||||
<paper-button id="confirm" affirmative autofocus>OK</paper-button>
|
||||
<paper-button id="dismiss" dismissive>Cancel</paper-button>
|
||||
</loot-dialog>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
closeCallback: undefined,
|
||||
|
||||
setButtonText: function(accept, cancel) {
|
||||
this.getElementsByClassName('accept')[0].textContent = accept;
|
||||
this.getElementsByClassName('cancel')[0].textContent = cancel;
|
||||
setConfirmText: function(confirmText) {
|
||||
this.shadowRoot.getElementById('confirm').textContent = confirmText;
|
||||
},
|
||||
|
||||
if (!cancel) {
|
||||
this.getElementsByClassName('cancel')[0].classList.toggle('hidden', true);
|
||||
} else {
|
||||
this.getElementsByClassName('cancel')[0].classList.toggle('hidden', false);
|
||||
}
|
||||
setDismissable: function(isDialogDismissable) {
|
||||
this.shadowRoot.getElementById('dismiss').classList.toggle('hidden', !isDialogDismissable);
|
||||
},
|
||||
|
||||
onButtonClick: function(evt) {
|
||||
if (evt.target.parentElement.closeCallback) {
|
||||
evt.target.parentElement.closeCallback(evt.target.classList.contains('accept'));
|
||||
evt.target.parentElement.closeCallback(evt.target.id === 'confirm');
|
||||
}
|
||||
evt.target.parentElement.addEventListener('core-overlay-close-completed', function(evt){
|
||||
evt.target.parentElement.parentNode.host.addEventListener('core-overlay-close-completed', function(evt){
|
||||
evt.target.parentElement.removeChild(evt.target);
|
||||
}, false);
|
||||
},
|
||||
|
||||
showModal: function(title, text, closeCallback) {
|
||||
this.heading = title;
|
||||
this.querySelector('.message').textContent = text;
|
||||
this.getElementsByClassName('message')[0].textContent = text;
|
||||
|
||||
this.closeCallback = closeCallback;
|
||||
this.super();
|
||||
this.shadowRoot.getElementById('dialog').showModal();
|
||||
},
|
||||
|
||||
created: function() {
|
||||
var p = document.createElement('p');
|
||||
p.className = 'message';
|
||||
this.appendChild(p);
|
||||
|
||||
var accept = document.createElement('paper-button');
|
||||
accept.className = 'accept';
|
||||
accept.setAttribute('affirmative', true);
|
||||
accept.setAttribute('autofocus', true);
|
||||
accept.textContent = 'Apply';
|
||||
this.appendChild(accept);
|
||||
|
||||
var cancel = document.createElement('paper-button');
|
||||
cancel.className = 'cancel';
|
||||
cancel.setAttribute('dismissive', true);
|
||||
cancel.textContent = 'Cancel';
|
||||
this.appendChild(cancel);
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
this.getElementsByClassName('accept')[0].addEventListener('click', this.onButtonClick, false);
|
||||
this.getElementsByClassName('cancel')[0].addEventListener('click', this.onButtonClick, false);
|
||||
this.shadowRoot.getElementById('confirm').addEventListener('click', this.onButtonClick, false);
|
||||
this.shadowRoot.getElementById('dismiss').addEventListener('click', this.onButtonClick, false);
|
||||
},
|
||||
|
||||
detached: function() {
|
||||
this.getElementsByClassName('accept')[0].removeEventListener('click', this.onButtonClick, false);
|
||||
this.getElementsByClassName('cancel')[0].removeEventListener('click', this.onButtonClick, false);
|
||||
this.shadowRoot.getElementById('confirm').removeEventListener('click', this.onButtonClick, false);
|
||||
this.shadowRoot.getElementById('dismiss').removeEventListener('click', this.onButtonClick, false);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
@@ -315,6 +315,7 @@
|
||||
<script src="../../../bower_components/marked/lib/marked.js"></script>
|
||||
<script src="../../../bower_components/Jed/jed.js"></script>
|
||||
<script src="../../../bower_components/jed-gettext-parser/jedGettextParser.js"></script>
|
||||
<script src="js/dialog.js"></script>
|
||||
<script src="js/events.js"></script>
|
||||
<script src="js/filters.js"></script>
|
||||
<script src="js/game.js"></script>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
(function exportModule(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory);
|
||||
} else {
|
||||
// Browser globals
|
||||
root.loot = root.loot || {};
|
||||
root.loot.Dialog = factory();
|
||||
}
|
||||
}(this, () => {
|
||||
return class Dialog {
|
||||
static showProgress(text) {
|
||||
const progressDialog = document.getElementById('progressDialog');
|
||||
progressDialog.getElementsByTagName('p')[0].textContent = text;
|
||||
if (!progressDialog.opened) {
|
||||
progressDialog.showModal();
|
||||
}
|
||||
}
|
||||
|
||||
static closeProgress() {
|
||||
const progressDialog = document.getElementById('progressDialog');
|
||||
if (progressDialog.opened) {
|
||||
progressDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
static showMessage(title, text) {
|
||||
const dialog = document.createElement('loot-message-dialog');
|
||||
dialog.setDismissable(false);
|
||||
dialog.showModal(title, text);
|
||||
document.body.appendChild(dialog);
|
||||
}
|
||||
|
||||
static askQuestion(title, text, confirmText, closeCallback) {
|
||||
const dialog = document.createElement('loot-message-dialog');
|
||||
dialog.setConfirmText(confirmText);
|
||||
dialog.showModal(title, text, closeCallback);
|
||||
document.body.appendChild(dialog);
|
||||
}
|
||||
|
||||
static showNotification(text) {
|
||||
const toast = document.getElementById('toast');
|
||||
toast.text = text;
|
||||
toast.show();
|
||||
}
|
||||
};
|
||||
}));
|
||||
+19
-19
@@ -110,7 +110,7 @@ function onChangeGame(evt) {
|
||||
}
|
||||
|
||||
/* Send off a CEF query with the folder name of the new game. */
|
||||
showProgress(loot.l10n.translate('Loading game data...'));
|
||||
loot.Dialog.showProgress(loot.l10n.translate('Loading game data...'));
|
||||
loot.query('changeGame', evt.currentTarget.getAttribute('value')).then(function(result){
|
||||
/* Filters should be re-applied on game change, except the conflicts
|
||||
filter. Don't need to deactivate the others beforehand. Strictly not
|
||||
@@ -144,7 +144,7 @@ function onChangeGame(evt) {
|
||||
console.log('changeGame response: ' + result);
|
||||
}
|
||||
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onOpenReadme(evt) {
|
||||
@@ -174,16 +174,16 @@ function updateMasterlistNoProgress() {
|
||||
/* Hack to stop cards overlapping. */
|
||||
document.getElementById('main').lastElementChild.updateSize();
|
||||
|
||||
toast(loot.l10n.translate('Masterlist updated to revision %s.', loot.game.masterlist.revision));
|
||||
loot.Dialog.showNotification(loot.l10n.translate('Masterlist updated to revision %s.', loot.game.masterlist.revision));
|
||||
} else {
|
||||
toast(loot.l10n.translate('No masterlist update was necessary.'));
|
||||
loot.Dialog.showNotification(loot.l10n.translate('No masterlist update was necessary.'));
|
||||
}
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onUpdateMasterlist(evt) {
|
||||
showProgress(loot.l10n.translate('Updating masterlist...'));
|
||||
loot.Dialog.showProgress(loot.l10n.translate('Updating masterlist...'));
|
||||
updateMasterlistNoProgress().then(function(result){
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onSortPlugins(evt) {
|
||||
@@ -205,7 +205,7 @@ function onSortPlugins(evt) {
|
||||
promise = promise.then(updateMasterlistNoProgress());
|
||||
}
|
||||
promise.then(function(){
|
||||
showProgress(loot.l10n.translate('Sorting plugins...'));
|
||||
loot.Dialog.showProgress(loot.l10n.translate('Sorting plugins...'));
|
||||
loot.query('sortPlugins').then(JSON.parse).then(function(result){
|
||||
if (result) {
|
||||
loot.game.oldLoadOrder = loot.game.plugins;
|
||||
@@ -251,7 +251,7 @@ function onSortPlugins(evt) {
|
||||
|
||||
/* Disable changing game. */
|
||||
document.getElementById('gameMenu').setAttribute('disabled', '');
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
}
|
||||
}).catch(processCefError);
|
||||
}).catch(processCefError);
|
||||
@@ -301,16 +301,16 @@ function onRedatePlugins(evt) {
|
||||
return;
|
||||
}
|
||||
|
||||
showMessageDialog(loot.l10n.translate('Redate Plugins?'), loot.l10n.translate('This feature is provided so that modders using the Creation Kit may set the load order it uses. A side-effect is that any subscribed Steam Workshop mods will be re-downloaded by Steam. Do you wish to continue?'), loot.l10n.translate('Redate'), function(result){
|
||||
loot.Dialog.askQuestion(loot.l10n.translate('Redate Plugins?'), loot.l10n.translate('This feature is provided so that modders using the Creation Kit may set the load order it uses. A side-effect is that any subscribed Steam Workshop mods will be re-downloaded by Steam. Do you wish to continue?'), loot.l10n.translate('Redate'), function(result){
|
||||
if (result) {
|
||||
loot.query('redatePlugins').then(function(response){
|
||||
toast('Plugins were successfully redated.');
|
||||
loot.Dialog.showNotification('Plugins were successfully redated.');
|
||||
}).catch(processCefError);
|
||||
}
|
||||
});
|
||||
}
|
||||
function onClearAllMetadata(evt) {
|
||||
showMessageDialog('', loot.l10n.translate('Are you sure you want to clear all existing user-added metadata from all plugins?'), loot.l10n.translate('Clear'), function(result){
|
||||
loot.Dialog.askQuestion('', loot.l10n.translate('Are you sure you want to clear all existing user-added metadata from all plugins?'), loot.l10n.translate('Clear'), function(result){
|
||||
if (result) {
|
||||
loot.query('clearAllMetadata').then(JSON.parse).then(function(result){
|
||||
if (result) {
|
||||
@@ -332,7 +332,7 @@ function onClearAllMetadata(evt) {
|
||||
}
|
||||
});
|
||||
|
||||
toast(loot.l10n.translate('All user-added metadata has been cleared.'));
|
||||
loot.Dialog.showNotification(loot.l10n.translate('All user-added metadata has been cleared.'));
|
||||
}
|
||||
}).catch(processCefError);
|
||||
}
|
||||
@@ -384,7 +384,7 @@ function onCopyContent(evt) {
|
||||
messages: messages,
|
||||
plugins: plugins
|
||||
}).then(function(){
|
||||
toast(loot.l10n.translate("LOOT's content has been copied to the clipboard."));
|
||||
loot.Dialog.showNotification(loot.l10n.translate("LOOT's content has been copied to the clipboard."));
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onCopyLoadOrder(evt) {
|
||||
@@ -399,7 +399,7 @@ function onCopyLoadOrder(evt) {
|
||||
}
|
||||
|
||||
loot.query('copyLoadOrder', plugins).then(function(){
|
||||
toast(loot.l10n.translate("The load order has been copied to the clipboard."));
|
||||
loot.Dialog.showNotification(loot.l10n.translate("The load order has been copied to the clipboard."));
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onSwitchSidebarTab(evt) {
|
||||
@@ -590,11 +590,11 @@ function onConflictsFilter(evt) {
|
||||
}
|
||||
function onCopyMetadata(evt) {
|
||||
loot.query('copyMetadata', evt.target.getName()).then(function(){
|
||||
toast(loot.l10n.translate('The metadata for "%s" has been copied to the clipboard.', evt.target.getName()));
|
||||
loot.Dialog.showNotification(loot.l10n.translate('The metadata for "%s" has been copied to the clipboard.', evt.target.getName()));
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onClearMetadata(evt) {
|
||||
showMessageDialog('', loot.l10n.translate('Are you sure you want to clear all existing user-added metadata from "%s"?', evt.target.getName()), loot.l10n.translate('Clear'), function(result){
|
||||
loot.Dialog.askQuestion('', loot.l10n.translate('Are you sure you want to clear all existing user-added metadata from "%s"?', evt.target.getName()), loot.l10n.translate('Clear'), function(result){
|
||||
if (result) {
|
||||
loot.query('clearPluginMetadata', evt.target.getName()).then(JSON.parse).then(function(result){
|
||||
if (result) {
|
||||
@@ -613,7 +613,7 @@ function onClearMetadata(evt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
toast(loot.l10n.translate('The user-added metadata for "%s" has been cleared.', evt.target.getName()));
|
||||
loot.Dialog.showNotification(loot.l10n.translate('The user-added metadata for "%s" has been cleared.', evt.target.getName()));
|
||||
/* Now perform search again. If there is no current search, this won't
|
||||
do anything. */
|
||||
document.getElementById('searchBar').search();
|
||||
@@ -649,7 +649,7 @@ function onJumpToGeneralInfo(evt) {
|
||||
}
|
||||
function onContentRefresh(evt) {
|
||||
/* Send a query for updated load order and plugin header info. */
|
||||
showProgress(loot.l10n.translate('Refreshing data...'));
|
||||
loot.Dialog.showProgress(loot.l10n.translate('Refreshing data...'));
|
||||
loot.query('getGameData').then(function(result){
|
||||
/* Parse the data sent from C++. */
|
||||
try {
|
||||
@@ -711,7 +711,7 @@ function onContentRefresh(evt) {
|
||||
/* Reapply filters. */
|
||||
setFilteredUIData();
|
||||
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
}).catch(processCefError);
|
||||
}
|
||||
function onSearchOpen(evt) {
|
||||
|
||||
@@ -4,8 +4,8 @@ function processCefError(err) {
|
||||
info than just the error message. Also, this can be used to catch any
|
||||
promise errors, not just CEF errors. */
|
||||
console.log(err.stack);
|
||||
closeProgressDialog();
|
||||
showMessageBox(loot.l10n.translate('Error'), err.message);
|
||||
loot.Dialog.closeProgress();
|
||||
loot.Dialog.showMessage(loot.l10n.translate('Error'), err.message);
|
||||
}
|
||||
|
||||
function showElement(element) {
|
||||
@@ -18,41 +18,8 @@ function hideElement(element) {
|
||||
element.classList.toggle('hidden', true);
|
||||
}
|
||||
}
|
||||
function toast(text) {
|
||||
var toast = document.getElementById('toast');
|
||||
toast.text = text;
|
||||
toast.show();
|
||||
}
|
||||
function showMessageDialog(title, text, positiveText, closeCallback) {
|
||||
var dialog = document.createElement('loot-message-dialog');
|
||||
dialog.setButtonText(positiveText, loot.l10n.translate('Cancel'));
|
||||
dialog.showModal(title, text, closeCallback);
|
||||
document.body.appendChild(dialog);
|
||||
}
|
||||
function showMessageBox(title, text) {
|
||||
var dialog = document.createElement('loot-message-dialog');
|
||||
dialog.setButtonText(loot.l10n.translate('OK'));
|
||||
dialog.showModal(title, text);
|
||||
document.body.appendChild(dialog);
|
||||
}
|
||||
|
||||
function showProgress(message) {
|
||||
var progressDialog = document.getElementById('progressDialog');
|
||||
if (message) {
|
||||
progressDialog.getElementsByTagName('p')[0].textContent = message;
|
||||
}
|
||||
if (!progressDialog.opened) {
|
||||
progressDialog.showModal();
|
||||
}
|
||||
}
|
||||
function closeProgressDialog() {
|
||||
var progressDialog = document.getElementById('progressDialog');
|
||||
if (progressDialog.opened) {
|
||||
progressDialog.close();
|
||||
}
|
||||
}
|
||||
function handleUnappliedChangesClose(change) {
|
||||
showMessageDialog('', loot.l10n.translate('You have not yet applied or cancelled your %s. Are you sure you want to quit?', change), loot.l10n.translate('Quit'), function(result){
|
||||
loot.Dialog.askQuestion('', loot.l10n.translate('You have not yet applied or cancelled your %s. Are you sure you want to quit?', change), loot.l10n.translate('Quit'), function(result){
|
||||
if (result) {
|
||||
/* Cancel any sorting and close any editors. Cheat by sending a
|
||||
cancelSort query for as many times as necessary. */
|
||||
@@ -77,7 +44,7 @@ function getConflictingPlugins(pluginName) {
|
||||
}
|
||||
|
||||
/* Now get conflicts for the plugin. */
|
||||
showProgress(loot.l10n.translate('Checking if plugins have been loaded...'));
|
||||
loot.Dialog.showProgress(loot.l10n.translate('Checking if plugins have been loaded...'));
|
||||
|
||||
return loot.query('getConflictingPlugins', pluginName).then(JSON.parse).then((result) => {
|
||||
if (result) {
|
||||
@@ -100,10 +67,10 @@ function getConflictingPlugins(pluginName) {
|
||||
}
|
||||
}
|
||||
}
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
return conflicts;
|
||||
}
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
return [pluginName];
|
||||
}).catch(processCefError);
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ function initVars() {
|
||||
loot.query('getSettings'),
|
||||
];
|
||||
|
||||
showProgress('Initialising user interface...');
|
||||
loot.Dialog.showProgress('Initialising user interface...');
|
||||
Promise.all(parallelPromises).then(function(results) {
|
||||
try {
|
||||
loot.gameTypes = JSON.parse(results[0]);
|
||||
@@ -197,7 +197,7 @@ function initVars() {
|
||||
}).then(function(){
|
||||
if (result) {
|
||||
return new Promise(function(resolve, reject){
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
document.getElementById('settingsButton').click();
|
||||
resolve('');
|
||||
});
|
||||
@@ -214,7 +214,7 @@ function initVars() {
|
||||
|
||||
setTimeout(function() {
|
||||
document.getElementById('cardsNav').updateSize();
|
||||
closeProgressDialog();
|
||||
loot.Dialog.closeProgress();
|
||||
}, 100);
|
||||
|
||||
return '';
|
||||
|
||||
@@ -106,6 +106,18 @@
|
||||
pluginItem.getElementById('editorIsOpenTooltip').textContent = l10n.translate('Editor Is Open');
|
||||
}
|
||||
|
||||
function translateMessageDialogTemplate(l10n) {
|
||||
/* Plugin List Item Template */
|
||||
let messageDialog = document.querySelector('link[rel="import"][href$="loot-message-dialog.html"]');
|
||||
if (messageDialog) {
|
||||
messageDialog = messageDialog.import.querySelector('template').content;
|
||||
} else {
|
||||
messageDialog = document.querySelector('polymer-element[name="loot-message-dialog"]').querySelector('template').content;
|
||||
}
|
||||
messageDialog.getElementById('confirm').textContent = l10n.translate('OK');
|
||||
messageDialog.getElementById('dismiss').textContent = l10n.translate('Cancel');
|
||||
}
|
||||
|
||||
function translateFileRowTemplate(l10n) {
|
||||
/* File row template */
|
||||
let fileRow = document.querySelector('link[rel="import"][href$="editable-table.html"]');
|
||||
@@ -312,6 +324,7 @@
|
||||
translatePluginCardTemplate(l10n);
|
||||
translatePluginEditorTemplate(l10n);
|
||||
translatePluginListItemTemplate(l10n);
|
||||
translateMessageDialogTemplate(l10n);
|
||||
|
||||
translateFileRowTemplate(l10n);
|
||||
translateMessageRowTemplate(l10n);
|
||||
|
||||
Reference in New Issue
Block a user