jsdialog: move About dialog to separate file

- converted to TS
- will be later extended with additional functionality

Signed-off-by: Szymon Kłos <szymon.klos@collabora.com>
Change-Id: I883da61018808d79d616d7346e86dadf9fa7079e
This commit is contained in:
Szymon Kłos 2024-05-27 11:00:56 +02:00 committed by Szymon Kłos
parent f846e66c4b
commit 0a9b7b6b82
4 changed files with 270 additions and 159 deletions

View file

@ -314,6 +314,7 @@ COOL_JS_LST =\
src/map/handler/Map.StateChanges.js \
src/map/handler/Map.WOPI.js \
src/layer/marker/Marker.Drag.js \
src/control/Control.AboutDialog.ts \
src/control/Control.Toolbar.js \
src/control/Control.Command.js \
src/control/Control.js \
@ -764,6 +765,7 @@ pot:
admin/src/Util.js \
js/global.js \
src/control/ColorPicker.ts \
src/control/Control.AboutDialog.ts \
src/control/Control.AlertDialog.js \
src/control/Control.Command.js \
src/control/Control.ContextMenu.js \

View file

@ -0,0 +1,265 @@
/*
* Copyright the Collabora Online contributors.
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* AboutDialog - implements Help - About dialog with version and warnings
*/
declare var JSDialog: any;
declare var brandProductName: any;
declare var brandProductURL: any;
declare var sanitizeUrl: any;
class AboutDialog {
map: any;
constructor(map: any) {
this.map = map;
}
private aboutDialogClickHandler(e: any) {
if (e.detail === 3) {
this.map._debug.toggle();
}
}
public show() {
const windowAny = window as any;
// Just as a test to exercise the Async Trace Event functionality, uncomment this
// line and the asyncTraceEvent.finish() below.
// var asyncTraceEvent = app.socket.createAsyncTraceEvent('cool-showLOAboutDialog');
const aboutDialogId = 'about-dialog';
// Move the div sitting in 'body' as content and make it visible
const content: HTMLElement = document
.getElementById(aboutDialogId)
.cloneNode(true) as HTMLElement;
content.style.display = 'block';
// fill product-name and product-string
let productName;
if (windowAny.ThisIsAMobileApp) {
productName = windowAny.MobileAppName;
} else {
productName =
typeof brandProductName !== 'undefined'
? brandProductName
: 'Collabora Online Development Edition (unbranded)';
}
var productURL =
typeof brandProductURL !== 'undefined'
? brandProductURL
: 'https://collaboraonline.github.io/';
const productNameElement = content.querySelector(
'#product-name',
) as HTMLElement;
productNameElement.innerText = productName;
content.classList.add(
'product-' +
productName
.split(/[ ()]+/)
.join('-')
.toLowerCase(),
);
var productString = _('This version of %productName is powered by');
var productNameWithURL;
if (!windowAny.ThisIsAMobileApp)
productNameWithURL =
'<a href="' +
sanitizeUrl(productURL) +
'" target="_blank">' +
productName +
'</a>';
else productNameWithURL = productName;
const productStringElement = content.querySelector(
'#product-string',
) as HTMLElement;
if (productStringElement)
productStringElement.innerText = productString.replace(
'%productName',
productNameWithURL,
);
const slowProxyElement = content.querySelector(
'#slow-proxy',
) as HTMLElement;
if (windowAny.socketProxy) slowProxyElement.innerText = _('"Slow Proxy"');
const routeTokenElement = content.querySelector(
'#routeToken',
) as HTMLElement;
if (windowAny.indirectSocket)
routeTokenElement.innerText = 'RouteToken: ' + windowAny.routeToken;
this.map.uiManager.showYesNoButton(
aboutDialogId + '-box',
productName,
'',
_('OK'),
null,
null,
null,
true,
);
var box = document.getElementById(aboutDialogId + '-box');
var innerDiv = L.DomUtil.create('div', '', null);
box.insertBefore(innerDiv, box.firstChild);
innerDiv.innerHTML = content.outerHTML;
var form = document.getElementById('about-dialog-box');
form.addEventListener('click', this.aboutDialogClickHandler.bind(this));
form.addEventListener('keyup', this.aboutDialogKeyHandler.bind(this));
form.querySelector('#coolwsd-version').querySelector('a').focus();
var copyversion = L.DomUtil.create(
'button',
'ui-pushbutton jsdialog',
null,
);
copyversion.setAttribute('id', 'modal-dialog-about-dialog-box-copybutton');
copyversion.setAttribute(
'title',
_('Copy all version information in English'),
);
var img = L.DomUtil.create('img', null, null);
L.LOUtil.setImage(img, 'lc_copy.svg', this.map);
copyversion.innerHTML =
'<img src="' + sanitizeUrl(img.src) + '" width="18px" height="18px">';
copyversion.addEventListener(
'click',
this.copyVersionInfoToClipboard.bind(this),
);
this.map.uiManager.enableTooltip(copyversion);
var aboutok = document.getElementById(
'modal-dialog-about-dialog-box-yesbutton',
);
if (aboutok) {
aboutok.before(copyversion);
}
}
private aboutDialogKeyHandler(e: KeyboardEvent) {
if (e.key === 'd') {
this.map._debug.toggle();
} else if (e.key === 'l') {
// L toggges the Online logging level between the default (whatever
// is set in coolwsd.xml or on the coolwsd command line) and the
// most verbose a client is allowed to set (which also can be set in
// coolwsd.xml or on the coolwsd command line).
//
// In a typical developer "make run" setup, the default is "trace"
// so there is nothing more verbose. But presumably it is different
// in production setups.
app.socket.threadLocalLoggingLevelToggle =
!app.socket.threadLocalLoggingLevelToggle;
const newLogLevel = app.socket.threadLocalLoggingLevelToggle
? 'verbose'
: 'default';
app.socket.sendMessage('loggingleveloverride ' + newLogLevel);
let logLevelInformation;
if (newLogLevel === 'default')
logLevelInformation = 'default (from coolwsd.xml)';
else if (newLogLevel === 'verbose')
logLevelInformation = 'most verbose (from coolwsd.xml)';
else if (newLogLevel === 'terse')
logLevelInformation = 'least verbose (from coolwsd.xml)';
else logLevelInformation = newLogLevel;
console.debug('Log level: ' + logLevelInformation);
}
}
private copyVersionInfoToClipboard() {
let text =
'COOLWSD version: ' +
this.getVersionInfoFromClass('coolwsd-version') +
'\n';
text +=
'LOKit version: ' + this.getVersionInfoFromClass('lokit-version') + '\n';
text += 'Served by: ' + document.getElementById('os-info').innerText + '\n';
text +=
'Server ID: ' + document.getElementById('coolwsd-id').innerText + '\n';
text = text.replace(/\u00A0/g, ' ');
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard
.writeText(text)
.then(
function () {
window.console.log('Text copied to clipboard');
this.contentHasBeenCopiedShowSnackbar();
}.bind(this),
)
.catch(function (error) {
window.console.error('Error copying text to clipboard:', error);
});
} else {
var textArea = document.createElement('textarea');
textArea.style.position = 'absolute';
textArea.style.opacity = '0';
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
window.console.log('Text copied to clipboard');
this.contentHasBeenCopiedShowSnackbar();
} catch (error) {
window.console.error('Error copying text to clipboard:', error);
} finally {
document.body.removeChild(textArea);
}
}
}
private contentHasBeenCopiedShowSnackbar() {
const timeout = 1000;
this.map.uiManager.showSnackbar(
'Version information has been copied',
null,
null,
timeout,
);
const copybutton = document.querySelector(
'#modal-dialog-about-dialog-box-copybutton > img',
);
L.LOUtil.setImage(copybutton, 'lc_clipboard-check.svg', this.map);
setTimeout(() => {
L.LOUtil.setImage(copybutton, 'lc_copy.svg', this.map);
}, timeout);
}
private getVersionInfoFromClass(className: string) {
const versionElement = document.getElementById(className);
let versionInfo = versionElement.innerText;
const gitHashIndex = versionInfo.indexOf('git hash');
if (gitHashIndex > -1) {
versionInfo =
versionInfo.slice(0, gitHashIndex) +
'(' +
versionInfo.slice(gitHashIndex) +
')';
}
return versionInfo;
}
}
// Initiate the class.
JSDialog.aboutDialog = (map: any) => {
return new AboutDialog(map);
};

View file

@ -236,6 +236,7 @@ L.Control.UIManager = L.Control.extend({
this.map.addControl(L.control.contextMenu());
this.map.userList = L.control.userList();
this.map.addControl(this.map.userList);
this.map.aboutDialog = JSDialog.aboutDialog(this.map);
var openBusyPopup = function(label) {
this.busyPopupTimer = setTimeout(function() {

View file

@ -12,7 +12,7 @@
* Toolbar handler
*/
/* global app $ window sanitizeUrl brandProductName brandProductURL _ */
/* global app $ window brandProductName _ */
L.Map.include({
// a mapping of uno commands to more readable toolbar items
@ -724,165 +724,8 @@ L.Map.include({
});
},
aboutDialogKeyHandler: function(event) {
if (event.key === 'd') {
this._debug.toggle();
} else if (event.key === 'l') {
// L toggges the Online logging level between the default (whatever
// is set in coolwsd.xml or on the coolwsd command line) and the
// most verbose a client is allowed to set (which also can be set in
// coolwsd.xml or on the coolwsd command line).
//
// In a typical developer "make run" setup, the default is "trace"
// so there is nothing more verbose. But presumably it is different
// in production setups.
app.socket.threadLocalLoggingLevelToggle = !app.socket.threadLocalLoggingLevelToggle;
var newLogLevel = (app.socket.threadLocalLoggingLevelToggle ? 'verbose' : 'default');
app.socket.sendMessage('loggingleveloverride ' + newLogLevel);
var logLevelInformation;
if (newLogLevel === 'default')
logLevelInformation = 'default (from coolwsd.xml)';
else if (newLogLevel === 'verbose')
logLevelInformation = 'most verbose (from coolwsd.xml)';
else if (newLogLevel === 'terse')
logLevelInformation = 'least verbose (from coolwsd.xml)';
else
logLevelInformation = newLogLevel;
console.debug('Log level: ' + logLevelInformation);
}
},
aboutDialogClickHandler: function(event) {
if (event.detail === 3) {
this._debug.toggle();
}
},
showLOAboutDialog: function() {
// Just as a test to exercise the Async Trace Event functionality, uncomment this
// line and the asyncTraceEvent.finish() below.
// var asyncTraceEvent = app.socket.createAsyncTraceEvent('cool-showLOAboutDialog');
var aboutDialogId = 'about-dialog';
// Move the div sitting in 'body' as content and make it visible
var content = document.getElementById(aboutDialogId).cloneNode(true);
content.style.display = 'block';
// fill product-name and product-string
var productName;
if (window.ThisIsAMobileApp) {
productName = window.MobileAppName;
} else {
productName = (typeof brandProductName !== 'undefined') ? brandProductName : 'Collabora Online Development Edition (unbranded)';
}
var productURL = (typeof brandProductURL !== 'undefined') ? brandProductURL : 'https://collaboraonline.github.io/';
content.querySelector('#product-name').innerText = productName;
content.classList.add('product-' + productName.split(/[ ()]+/).join('-').toLowerCase());
var productString = _('This version of %productName is powered by');
var productNameWithURL;
if (!window.ThisIsAMobileApp)
productNameWithURL = '<a href="' + sanitizeUrl(productURL) +
'" target="_blank">' + productName + '</a>';
else
productNameWithURL = productName;
if (content.querySelector('#product-string'))
content.querySelector('#product-string').innerText = productString.replace('%productName', productNameWithURL);
if (window.socketProxy)
content.querySelector('#slow-proxy').innerText = _('"Slow Proxy"');
var map = this;
if (window.indirectSocket)
content.querySelector('#routeToken').innerText = 'RouteToken: ' + window.routeToken;
map.uiManager.showYesNoButton(aboutDialogId + '-box', productName, '', _('OK'), null, null, null, true);
var box = document.getElementById(aboutDialogId + '-box');
var innerDiv = L.DomUtil.create('div', '', null);
box.insertBefore(innerDiv, box.firstChild);
innerDiv.innerHTML = content.outerHTML;
var form = document.getElementById('about-dialog-box');
form.addEventListener('click', this.aboutDialogClickHandler.bind(this));
form.addEventListener('keyup', this.aboutDialogKeyHandler.bind(this));
form.querySelector('#coolwsd-version').querySelector('a').focus();
var copyversion = L.DomUtil.create('button', 'ui-pushbutton jsdialog', null);
copyversion.setAttribute('id', 'modal-dialog-about-dialog-box-copybutton');
copyversion.setAttribute('title', _('Copy all version information in English'));
var img = L.DomUtil.create('img', null, null);
L.LOUtil.setImage(img, 'lc_copy.svg', map);
copyversion.innerHTML = '<img src="' + img.src +'" width="18px" height="18px">';
copyversion.addEventListener('click', this.copyVersionInfoToClipboard.bind(this));
map.uiManager.enableTooltip(copyversion);
var aboutok = document.getElementById('modal-dialog-about-dialog-box-yesbutton');
if (aboutok) {
aboutok.before(copyversion);
}
},
getVersionInfoFromClass: function(className) {
var versionElement = document.getElementById(className);
var versionInfo = versionElement.innerText;
var gitHashIndex = versionInfo.indexOf('git hash');
if (gitHashIndex > -1) {
versionInfo = versionInfo.slice(0, gitHashIndex) + '(' + versionInfo.slice(gitHashIndex) + ')';
}
return versionInfo;
},
copyVersionInfoToClipboard: function() {
var text = 'COOLWSD version: ' + this.getVersionInfoFromClass('coolwsd-version') + '\n';
text += 'LOKit version: ' + this.getVersionInfoFromClass('lokit-version') + '\n';
text += 'Served by: ' + document.getElementById('os-info').innerText + '\n';
text += 'Server ID: ' + document.getElementById('coolwsd-id').innerText + '\n';
text = text.replace(/\u00A0/g, ' ');
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text)
.then(function() {
window.console.log('Text copied to clipboard');
this.contentHasBeenCopiedShowSnackbar();
}.bind(this))
.catch(function(error) {
window.console.error('Error copying text to clipboard:', error);
});
} else {
var textArea = document.createElement('textarea');
textArea.style.position = 'absolute';
textArea.style.opacity = 0;
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
window.console.log('Text copied to clipboard');
this.contentHasBeenCopiedShowSnackbar();
} catch (error) {
window.console.error('Error copying text to clipboard:', error);
} finally {
document.body.removeChild(textArea);
}
}
},
contentHasBeenCopiedShowSnackbar: function() {
var timeout = 1000;
this.uiManager.showSnackbar('Version information has been copied', null, null, timeout);
var copybutton = document.querySelector('#modal-dialog-about-dialog-box-copybutton > img');
L.LOUtil.setImage(copybutton, 'lc_clipboard-check.svg', this);
setTimeout(function () {
L.LOUtil.setImage(copybutton, 'lc_copy.svg', this);
}.bind(this), timeout);
this.aboutDialog.show();
},
extractContent: function(html) {