fix(office): add UI when office document is locked from missing rtChannel

This commit is contained in:
yflory 2026-03-20 17:54:13 +01:00
parent 4388b974c1
commit d6af2e7740
6 changed files with 123 additions and 16 deletions

View File

@ -134,7 +134,10 @@ define(req, function(AppConfig, Default, Language) {
}
};
Messages.oo_rtChannelMissing = 'An error occured while loading your document, blocking access to the latest changes. To preserve data integrity, the document is in read-only mode. Please contact support and send the following content to fix your document:';
// XXX
Messages.oo_rtChannelMissing = 'An error occured while loading your document. It is now read-only to prevent data being corrupted or lost. Please create a support ticket with the following information and a support agent will assist you.';
Messages.oo_rtChannelMissingNoSupport = 'An error occured while loading your document. It is now read-only to prevent data being corrupted or lost. Please send the following information to your instance administrator.';
Messages.oo_rtChannelMissingDate = "Message sent on {0}";
return Messages;

View File

@ -116,6 +116,31 @@
box-sizing: border-box;
}
.cp-pre-copy-container {
position: relative;
padding: 10px 5px;
color: @cryptpad_text_col;
background: @cp_loading-msg-bg;
border-radius: @variables_radius;
.cp-pre-copy-button {
cursor: pointer;
position: absolute;
right: 5px;
top: 5px;
svg {
height: 1.5rem;
width: 1.5rem;
}
&:hover, &:not(:disabled):active, &:focus {
color: @cp_loading-color;
}
}
pre.cp-pre-copy {
color: @cryptpad_text_col;
margin: 0;
}
}
.dialog {
padding: 12px;
/*

View File

@ -147,7 +147,6 @@ const factory = (Feedback) => {
// Keep only metadata messages for the current channel
if (parsed.channel && parsed.channel !== channel) { return; }
// Ignore the metadata message
if (parsed.validateKey && parsed.channel) {
if (!chan.validateKey) {
@ -165,15 +164,13 @@ const factory = (Feedback) => {
// If rtChannel deleted with placeholder, abort and make
// document read-only
chan.wc?.leave();
Feedback.send('RTCHANNEL_DELETED');
Feedback.send('RTCHANNEL_DELETED', true);
return ctx.emit('ERROR', { error: 'EDELETED', reason: parsed.message }, chan.clients);
}
if (parsed.error === "EUNKNOWN") {
// If rtChannel deleted with placeholder, abort and make
// document read-only
chan.wc?.leave();
Feedback.send('RTCHANNEL_EUNKNOWN');
return ctx.emit('ERROR', { error: 'EUNKOWN' }, chan.clients);
Feedback.send('RTCHANNEL_EUNKNOWN', true);
return ctx.emit('ERROR', { error: 'EUNKNOWN' }, chan.clients);
}
ctx.emit('READY', chan.clients, chan.clients);
return;

View File

@ -23,6 +23,7 @@ define([
'/common/hyperscript.js',
'/customize/loading.js',
'/common/common-icons.js',
'/common/clipboard.js',
//'/common/test.js',
'/lib/jquery-ui/jquery-ui.min.js', // autocomplete widget
@ -30,7 +31,7 @@ define([
'css!/lib/tippy/tippy.css',
'css!/lib/jquery-ui/jquery-ui.min.css'
], function ($, Messages, Util, Hash, Notifier, AppConfig,
Alertify, Tippy, h, Loading, Icons /*, Test */) {
Alertify, Tippy, h, Loading, Icons, Clipboard /*, Test */) {
var UI = {};
/*
@ -1625,6 +1626,22 @@ define([
};
};
UI.getPreCopy = (content) => {
let copy = h('div.cp-pre-copy-button', [
Icons.get('copy')
]);
Util.onClickEnter($(copy), () => {
Clipboard.copy(content, (err) => {
if (err) { return UI.warn(Messages.error); }
UI.log(Messages.genericCopySuccess);
});
});
return h('div.cp-pre-copy-container', [
copy,
h('pre.cp-pre-copy', content)
]);
};
/* QR code generation is synchronous once the library is loaded
so this could be syncronous if we load the library separately. */
UI.createQRCode = function (data, _cb) {

View File

@ -17,6 +17,7 @@ define([
'/api/config',
'/customize/application_config.js',
'/customize/messages.js',
'/support/ui.js',
'/components/chainpad/chainpad.dist.js',
'/file/file-crypto.js',
'/common/onlyoffice/history.js',
@ -47,6 +48,7 @@ define([
ApiConfig,
AppConfig,
Messages,
Support,
ChainPad,
FileCrypto,
History,
@ -873,18 +875,77 @@ define([
});
};
const sendDebugSupportTicket = (message) => {
const title = "[Automatic] Office document locked";
APP.supportModule.execCommand('MAKE_TICKET', {
channel: Hash.createChannelId(),
title,
ticket: APP.support.getDebuggingData({
title,
message
})
}, () => {});
};
const onRtChannelError = (err) => {
const wasReadOnly = readOnly;
readOnly = true;
offline = true;
const message = JSON.stringify({
error: err?.error,
reason: err?.reason,
channel: privateData.channel,
rtChannel: content.channel
}, 0, 2);
let txt = Messages.oo_rtChannelMissing;
let value;
let f = UI.confirm;
let cb = (yes) => {
if (!yes) { return; }
// Set flag if support has already been contacted
content.missingRtChannel = +new Date();
readOnly = wasReadOnly;
APP.onLocal();
readOnly = true;
sendDebugSupportTicket(message);
};
let btnText = content.missingRtChannel ? Messages.sent : Messages.support_formButton;
let opts = {
ok: [
Icons.get('send'),
h('span', btnText)
],
cancel: Messages.filePicker_close
};
if (content.missingRtChannel) {
value = h('strong', Messages._getKey('oo_rtChannelMissingDate', [
new Date(content.missingRtChannel).toLocaleDateString()
]));
setTimeout(() => {
const $b = UI.findOKButton();
$b.attr('disabled', 'disabled');
});
}
if (!ApiConfig.supportMailboxKey) {
txt = Messages.oo_rtChannelMissingNoSupport;
value = UI.getPreCopy(message);
f = UI.alert;
opts = undefined;
cb = undefined;
}
let div = h('div', [
h('p', Messages.oo_rtChannelMissing),
h('code', {style: 'white-space:pre-wrap;'}, JSON.stringify({
error: err?.error,
reason: err?.reason,
channel: content.channel
}, 0, 2))
h('p', txt),
value
]);
UI.alert(div);
f(div, cb, opts);
};
var openRtChannel = function (cb) {
@ -2049,6 +2110,8 @@ define([
//getEditor().setViewModeDisconnect(); // can't be used anymore, display an OO error popup
} else {
setEditable(true);
delete content.missingRtChannel;
APP.onLocal();
deleteOfflineLocks();
handleNewLocks({}, content.locks);
if (APP.unsavedChanges) {
@ -4039,6 +4102,8 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
//noTemplates: true
});
}).nThen(function (/*waitFor*/) {
APP.supportModule = common.makeUniversal('support');
APP.support = Support.create(common, false);
andThen(common);
});
};

File diff suppressed because one or more lines are too long