Support 'maxLength' property in MLTEV; Enforce this by default, to 500 characters for AP messages. WIP optional subjects, some new configuration

This commit is contained in:
Bryan Ashby 2023-02-04 11:51:47 -07:00
parent 1065f14c2e
commit a8e867a4bb
No known key found for this signature in database
GPG Key ID: C2C1B501E4EFD994
8 changed files with 76 additions and 6 deletions

View File

@ -94,6 +94,7 @@ module.exports = class Activity extends ActivityPubObject {
return postJson(actorUrl, activityJson, reqOpts, cb); return postJson(actorUrl, activityJson, reqOpts, cb);
} }
// :TODO: we need dp/support a bit more here...
recipientIds() { recipientIds() {
const ids = []; const ids = [];

View File

@ -413,6 +413,18 @@ module.exports = () => {
}, },
}, },
// General ActivityPub integration configuration
activityPub: {
// Mimics Mastodon max 500 characters for *outgoing* Notes
// (messages destined for ActivityPub); This is a soft limit;
// Implementations including Mastodon should still display
// longer messages, but this keeps us as a "good citizen"
autoSignatures: false,
// by default, don't include auto-signatures in AP outgoing
maxMessageLength: 500,
},
infoExtractUtils: { infoExtractUtils: {
Exiftool2Desc: { Exiftool2Desc: {
cmd: `${__dirname}/../util/exiftool2desc.js`, // ensure chmod +x cmd: `${__dirname}/../util/exiftool2desc.js`, // ensure chmod +x

View File

@ -18,6 +18,7 @@ const { stripMciColorCodes, controlCodesToAnsi } = require('./color_codes.js');
const Config = require('./config.js').get; const Config = require('./config.js').get;
const { const {
getAddressedToInfo, getAddressedToInfo,
messageInfoFromAddressedToInfo,
setExternalAddressedToInfo, setExternalAddressedToInfo,
copyExternalAddressedToInfo, copyExternalAddressedToInfo,
} = require('./mail_util.js'); } = require('./mail_util.js');
@ -424,12 +425,17 @@ exports.FullScreenEditorModule =
// //
// Append auto-signature, if enabled for the area & the user has one // Append auto-signature, if enabled for the area & the user has one
// //
if (false != area.autoSignatures) { const msgInfo = messageInfoFromAddressedToInfo(
getAddressedToInfo(headerValues.to)
);
if (false !== msgInfo.autoSignatures) {
if (false !== area.autoSignatures) {
const sig = this.client.user.getProperty(UserProps.AutoSignature); const sig = this.client.user.getProperty(UserProps.AutoSignature);
if (sig) { if (sig) {
messageBody += `\r\n-- \r\n${sig}`; messageBody += `\r\n-- \r\n${sig}`;
} }
} }
}
// finally, create the message // finally, create the message
msgOpts.message = messageBody; msgOpts.message = messageBody;
@ -1391,6 +1397,13 @@ exports.FullScreenEditorModule =
} }
switchToBody() { switchToBody() {
const to = this.getView('header', MciViewIds.header.to).getData();
const msgInfo = messageInfoFromAddressedToInfo(getAddressedToInfo(to));
if (msgInfo.maxMessageLength > 0) {
const bodyView = this.getView('body', MciViewIds.body.message);
bodyView.maxLength = msgInfo.maxMessageLength;
}
this.viewControllers.header.setFocus(false); this.viewControllers.header.setFocus(false);
this.viewControllers.body.switchFocus(1); this.viewControllers.body.switchFocus(1);

View File

@ -5,10 +5,15 @@ const EnigmaAssert = require('./enigma_assert.js');
const Address = require('./ftn_address.js'); const Address = require('./ftn_address.js');
const MessageConst = require('./message_const'); const MessageConst = require('./message_const');
const { getQuotePrefix } = require('./ftn_util'); const { getQuotePrefix } = require('./ftn_util');
const Config = require('./config').get;
// deps
const { get } = require('lodash');
exports.getAddressedToInfo = getAddressedToInfo; exports.getAddressedToInfo = getAddressedToInfo;
exports.setExternalAddressedToInfo = setExternalAddressedToInfo; exports.setExternalAddressedToInfo = setExternalAddressedToInfo;
exports.copyExternalAddressedToInfo = copyExternalAddressedToInfo; exports.copyExternalAddressedToInfo = copyExternalAddressedToInfo;
exports.messageInfoFromAddressedToInfo = messageInfoFromAddressedToInfo;
exports.getQuotePrefixFromName = getQuotePrefixFromName; exports.getQuotePrefixFromName = getQuotePrefixFromName;
const EMAIL_REGEX = const EMAIL_REGEX =
@ -148,6 +153,24 @@ function copyExternalAddressedToInfo(fromMessage, toMessage) {
toMessage.setExternalFlavor(fromMessage.meta.System[sm.ExternalFlavor]); toMessage.setExternalFlavor(fromMessage.meta.System[sm.ExternalFlavor]);
} }
function messageInfoFromAddressedToInfo(addressInfo) {
switch (addressInfo.flavor) {
case MessageConst.AddressFlavor.ActivityPub: {
const config = Config();
const maxMessageLength = get(config, 'activityPub.maxMessageLength', 500);
const autoSignatures = get(config, 'activityPub.autoSignatures', false);
// Additionally, it's ot necessary to supply a subject
// (aka summary) with a 'Note' Activity
return { subjectOptional: true, maxMessageLength, autoSignatures };
}
default:
// autoSignatures: null = varies by additional config
return { subjectOptional: false, maxMessageLength: 0, autoSignatures: null };
}
}
function getQuotePrefixFromName(name) { function getQuotePrefixFromName(name) {
const addrInfo = getAddressedToInfo(name); const addrInfo = getAddressedToInfo(name);
return getQuotePrefix(addrInfo.name || name); return getQuotePrefix(addrInfo.name || name);

View File

@ -113,6 +113,7 @@ function MultiLineEditTextView(options) {
this.textLines = []; this.textLines = [];
this.topVisibleIndex = 0; this.topVisibleIndex = 0;
this.mode = options.mode || 'edit'; // edit | preview | read-only this.mode = options.mode || 'edit'; // edit | preview | read-only
this.maxLength = 0; // no max by default
if ('preview' === this.mode) { if ('preview' === this.mode) {
this.autoScroll = options.autoScroll || true; this.autoScroll = options.autoScroll || true;
@ -317,6 +318,15 @@ function MultiLineEditTextView(options) {
return text; return text;
}; };
this.getCharacterLength = function () {
// :TODO: FSE needs re-write anyway, but this should just be known all the time vs calc. Too much of a mess right now...
let len = 0;
this.textLines.forEach(tl => {
len += tl.text.length;
});
return len;
};
this.replaceCharacterInText = function (c, index, col) { this.replaceCharacterInText = function (c, index, col) {
self.textLines[index].text = strUtil.replaceAt( self.textLines[index].text = strUtil.replaceAt(
self.textLines[index].text, self.textLines[index].text,
@ -664,6 +674,10 @@ function MultiLineEditTextView(options) {
}; };
this.keyPressCharacter = function (c) { this.keyPressCharacter = function (c) {
if (this.maxLength > 0 && this.getCharacterLength() + 1 >= this.maxLength) {
return;
}
var index = self.getTextLinesIndex(); var index = self.getTextLinesIndex();
// //
@ -1170,6 +1184,12 @@ MultiLineEditTextView.prototype.setPropertyValue = function (propName, value) {
this.specialKeyMap.next = this.specialKeyMap.next || []; this.specialKeyMap.next = this.specialKeyMap.next || [];
this.specialKeyMap.next.push('tab'); this.specialKeyMap.next.push('tab');
break; break;
case 'maxLength':
if (_.isNumber(value)) {
this.maxLength = value;
}
break;
} }
MultiLineEditTextView.super_.prototype.setPropertyValue.call(this, propName, value); MultiLineEditTextView.super_.prototype.setPropertyValue.call(this, propName, value);

View File

@ -150,7 +150,7 @@ View.prototype.setPosition = function (pos) {
this.position.col = parseInt(arguments[1], 10); this.position.col = parseInt(arguments[1], 10);
} }
// sanatize // sanitize
this.position.row = Math.max(this.position.row, 1); this.position.row = Math.max(this.position.row, 1);
this.position.col = Math.max(this.position.col, 1); this.position.col = Math.max(this.position.col, 1);
this.position.row = Math.min(this.position.row, this.client.term.termHeight); this.position.row = Math.min(this.position.row, this.client.term.termHeight);

View File

@ -226,6 +226,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule {
enter() { enter() {
this.client.stopIdleMonitor(); this.client.stopIdleMonitor();
this._applyOpVisibility(); this._applyOpVisibility();
Events.on( Events.on(
Events.getSystemEvents().ClientDisconnected, Events.getSystemEvents().ClientDisconnected,
this._clientDisconnected.bind(this) this._clientDisconnected.bind(this)
@ -240,7 +241,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule {
Events.removeListener( Events.removeListener(
Events.getSystemEvents().ClientDisconnected, Events.getSystemEvents().ClientDisconnected,
this._clientDisconnected this._clientDisconnected.bind(this)
); );
this._restoreOpVisibility(); this._restoreOpVisibility();