Support RFC 6855 / RFC 5738 (UTF8)

This commit is contained in:
djmaze 2021-11-22 21:01:30 +01:00
parent c9a497eb9d
commit 299ec7faf8
25 changed files with 249 additions and 505 deletions

View file

@ -299,8 +299,8 @@ class AppUser extends AbstractApp {
}
]);
} else if (oMoveFolder) {
this.messagesMoveHelper(sFromFolderFullNameRaw, oMoveFolder.fullNameRaw, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove, oMoveFolder.fullNameRaw);
this.messagesMoveHelper(sFromFolderFullNameRaw, oMoveFolder.fullName, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove, oMoveFolder.fullName);
}
}
@ -317,12 +317,12 @@ class AppUser extends AbstractApp {
if (oFromFolder && oToFolder) {
if (undefined === bCopy ? false : !!bCopy) {
this.messagesCopyHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove);
this.messagesCopyHelper(oFromFolder.fullName, oToFolder.fullName, aUidForMove);
} else {
this.messagesMoveHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove);
this.messagesMoveHelper(oFromFolder.fullName, oToFolder.fullName, aUidForMove);
}
MessageUserStore.removeMessagesFromList(oFromFolder.fullNameRaw, aUidForMove, oToFolder.fullNameRaw, bCopy);
MessageUserStore.removeMessagesFromList(oFromFolder.fullName, aUidForMove, oToFolder.fullName, bCopy);
return true;
}
}
@ -487,12 +487,12 @@ class AppUser extends AbstractApp {
folderFromCache.messageCountUnread(result.MessageUnseenCount);
if (unreadCountChange) {
MessageFlagsCache.clearFolder(folderFromCache.fullNameRaw);
MessageFlagsCache.clearFolder(folderFromCache.fullName);
}
if (result.Flags.length) {
result.Flags.forEach(flags =>
MessageFlagsCache.storeByFolderAndUid(folderFromCache.fullNameRaw, flags.Uid.toString(), [
MessageFlagsCache.storeByFolderAndUid(folderFromCache.fullName, flags.Uid.toString(), [
!!flags.IsUnseen,
!!flags.IsFlagged,
!!flags.IsAnswered,
@ -505,15 +505,15 @@ class AppUser extends AbstractApp {
}
MessageUserStore.initUidNextAndNewMessages(
folderFromCache.fullNameRaw,
folderFromCache.fullName,
result.UidNext,
result.NewMessages
);
if (!hash || unreadCountChange || result.Hash !== hash) {
if (folderFromCache.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()) {
if (folderFromCache.fullName === FolderUserStore.currentFolderFullNameRaw()) {
this.reloadMessageList();
} else if (getFolderInboxName() === folderFromCache.fullNameRaw) {
} else if (getFolderInboxName() === folderFromCache.fullName) {
Remote.messageList(null, {Folder: getFolderInboxName()}, true);
}
}
@ -551,17 +551,17 @@ class AppUser extends AbstractApp {
folder.messageCountUnread(item.MessageUnseenCount);
if (unreadCountChange) {
MessageFlagsCache.clearFolder(folder.fullNameRaw);
MessageFlagsCache.clearFolder(folder.fullName);
}
if (!hash || item.Hash !== hash) {
if (folder.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()) {
if (folder.fullName === FolderUserStore.currentFolderFullNameRaw()) {
this.reloadMessageList();
}
} else if (unreadCountChange
&& folder.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()
&& folder.fullName === FolderUserStore.currentFolderFullNameRaw()
&& MessageUserStore.list.length) {
this.folderInformation(folder.fullNameRaw, MessageUserStore.list());
this.folderInformation(folder.fullName, MessageUserStore.list());
}
}
});

View file

@ -200,14 +200,14 @@ folderListOptionsBuilder = (
folders.forEach(oItem => {
if (showUnsubscribed || oItem.hasSubscriptions() || !oItem.exists) {
aResult.push({
id: oItem.fullNameRaw,
id: oItem.fullName,
name:
sDeepPrefix.repeat(oItem.deep) +
fRenameCallback(oItem),
system: false,
disabled: !bNoSelectSelectable && (
!oItem.selectable() ||
aDisabled.includes(oItem.fullNameRaw) ||
aDisabled.includes(oItem.fullName) ||
fDisableCallback(oItem))
});
}

View file

@ -145,7 +145,7 @@ ko.bindingHandlers.dropmessages = {
if ('messages' === getDragAction(e) && ['move','copy'].includes(e.dataTransfer.effectAllowed)) {
let data = dragData.data;
if (folder && data && data.folder && isArray(data.uids)) {
rl.app.moveMessagesToFolder(data.folder, data.uids, folder.fullNameRaw, data.copy && e.ctrlKey);
rl.app.moveMessagesToFolder(data.folder, data.uids, folder.fullName, data.copy && e.ctrlKey);
}
}
});

View file

@ -69,7 +69,7 @@ export class FolderCollectionModel extends AbstractCollectionModel
}
return super.reviveFromJson(object, oFolder => {
let oCacheFolder = Cache.getFolderFromCacheList(oFolder.FullNameRaw);
let oCacheFolder = Cache.getFolderFromCacheList(oFolder.FullName);
if (oCacheFolder) {
oFolder.SubFolders = FolderCollectionModel.reviveFromJson(oFolder.SubFolders);
@ -79,14 +79,14 @@ export class FolderCollectionModel extends AbstractCollectionModel
if (!oCacheFolder)
return null;
if (1 == SystemFolders.indexOf(oFolder.FullNameRaw)) {
if (1 == SystemFolders.indexOf(oFolder.FullName)) {
oCacheFolder.type(FolderType.Inbox);
Cache.setFolderInboxName(oFolder.FullNameRaw);
Cache.setFolderInboxName(oFolder.FullName);
}
Cache.setFolder(oCacheFolder.fullNameHash, oFolder.FullNameRaw, oCacheFolder);
Cache.setFolder(oCacheFolder.fullNameHash, oFolder.FullName, oCacheFolder);
}
let type = SystemFolders.indexOf(oFolder.FullNameRaw);
let type = SystemFolders.indexOf(oFolder.FullName);
if (1 < type) {
oCacheFolder.type(type);
}
@ -97,7 +97,7 @@ export class FolderCollectionModel extends AbstractCollectionModel
if (oFolder.Extended) {
if (oFolder.Extended.Hash) {
Cache.setFolderHash(oCacheFolder.fullNameRaw, oFolder.Extended.Hash);
Cache.setFolderHash(oCacheFolder.fullName, oFolder.Extended.Hash);
}
if (null != oFolder.Extended.MessageCount) {
@ -196,7 +196,6 @@ export class FolderModel extends AbstractModel {
super();
this.fullName = '';
this.fullNameRaw = '';
this.fullNameHash = '';
this.delimiter = '';
this.namespace = '';
@ -244,7 +243,7 @@ export class FolderModel extends AbstractModel {
static reviveFromJson(json) {
const folder = super.reviveFromJson(json);
if (folder) {
folder.deep = json.FullNameRaw.split(folder.delimiter).length - 1;
folder.deep = json.FullName.split(folder.delimiter).length - 1;
let type = (folder.metadata[FolderMetadataKeys.KolabFolderType]
|| folder.metadata[FolderMetadataKeys.KolabFolderTypeShared]

View file

@ -19,10 +19,19 @@ import { AbstractFetchRemote } from 'Remote/AbstractFetch';
import { FolderCollectionModel } from 'Model/FolderCollection';
const urlSafeJSON = data => btoa(JSON.stringify(data))
// unescape(encodeURIComponent()) makes the UTF-16 DOMString to an UTF-8 string
const urlSafeJSON = data => btoa(unescape(encodeURIComponent(JSON.stringify(data))))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
/* Withous deprecated 'unescape':
const urlSafeJSON = data => btoa(encodeURIComponent(JSON.stringify(data)).replace(
/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode('0x' + p1)
))
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
*/
class RemoteUserFetch extends AbstractFetchRemote {

View file

@ -73,11 +73,11 @@ export class FoldersUserSettings /*extends AbstractViewSettings*/ {
Local.set(ClientSideKeyName.FoldersLashHash, '');
rl.app.foldersPromisesActionHelper(
Remote.folderRename(folder.fullNameRaw, nameToEdit),
Remote.folderRename(folder.fullName, nameToEdit),
Notification.CantRenameFolder
);
removeFolderFromCacheList(folder.fullNameRaw);
removeFolderFromCacheList(folder.fullName);
folder.name(nameToEdit);
}
@ -120,11 +120,11 @@ export class FoldersUserSettings /*extends AbstractViewSettings*/ {
// rl.app.foldersPromisesActionHelper
Remote.abort('Folders')
.folderDelete(folderToRemove.fullNameRaw)
.folderDelete(folderToRemove.fullName)
.then(
() => {
folderToRemove.selectable(false)
removeFolderFromCacheList(folderToRemove.fullNameRaw);
removeFolderFromCacheList(folderToRemove.fullName);
FolderUserStore.folderList(FolderUserStore.folderList.filter(folder => folder !== folderToRemove));
},
error => {
@ -143,20 +143,20 @@ export class FoldersUserSettings /*extends AbstractViewSettings*/ {
toggleFolderKolabType(folder, event) {
let type = event.target.value;
// TODO: append '.default' ?
Remote.folderSetMetadata(null, folder.fullNameRaw, FolderMetadataKeys.KolabFolderType, type);
Remote.folderSetMetadata(null, folder.fullName, FolderMetadataKeys.KolabFolderType, type);
folder.kolabType(type);
}
toggleFolderSubscription(folder) {
let subscribe = !folder.subscribed();
Local.set(ClientSideKeyName.FoldersLashHash, '');
Remote.folderSetSubscribe(null, folder.fullNameRaw, subscribe);
Remote.folderSetSubscribe(null, folder.fullName, subscribe);
folder.subscribed(subscribe);
}
toggleFolderCheckable(folder) {
let checkable = !folder.checkable();
Remote.folderSetCheckable(null, folder.fullNameRaw, checkable);
Remote.folderSetCheckable(null, folder.fullName, checkable);
folder.checkable(checkable);
}
}

View file

@ -58,7 +58,7 @@ export const FolderUserStore = new class {
draftFolderNotEnabled: () => !self.draftFolder() || UNUSED_OPTION_VALUE === self.draftFolder(),
currentFolderFullNameRaw: () => (self.currentFolder() ? self.currentFolder().fullNameRaw : ''),
currentFolderFullNameRaw: () => (self.currentFolder() ? self.currentFolder().fullName : ''),
currentFolderFullName: () => (self.currentFolder() ? self.currentFolder().fullName : ''),
currentFolderFullNameHash: () => (self.currentFolder() ? self.currentFolder().fullNameHash : ''),
@ -136,7 +136,7 @@ export const FolderUserStore = new class {
timeout > folder.expires &&
(folder.isSystemFolder() || (folder.subscribed() && (folder.checkable() || !bDisplaySpecSetting)))
) {
timeouts.push([folder.expires, folder.fullNameRaw]);
timeouts.push([folder.expires, folder.fullName]);
}
if (folder && folder.subFolders.length) {

View file

@ -308,7 +308,7 @@ export const MessageUserStore = new class {
}
if (toFolder) {
if (trashFolder === toFolder.fullNameRaw || spamFolder === toFolder.fullNameRaw) {
if (trashFolder === toFolder.fullName || spamFolder === toFolder.fullName) {
unseenCount = 0;
}
@ -661,13 +661,13 @@ export const MessageUserStore = new class {
if (null != collection.MessageUnseenCount) {
if (pInt(folder.messageCountUnread()) !== pInt(collection.MessageUnseenCount)) {
unreadCountChange = true;
MessageFlagsCache.clearFolder(folder.fullNameRaw);
MessageFlagsCache.clearFolder(folder.fullName);
}
folder.messageCountUnread(collection.MessageUnseenCount);
}
this.initUidNextAndNewMessages(folder.fullNameRaw, collection.UidNext, collection.NewMessages);
this.initUidNextAndNewMessages(folder.fullName, collection.UidNext, collection.NewMessages);
}
this.listCount(iCount);
@ -688,7 +688,7 @@ export const MessageUserStore = new class {
clearNewMessageCache();
if (folder && (cached || unreadCountChange || SettingsUserStore.useThreads())) {
rl.app.folderInformation(folder.fullNameRaw, collection);
rl.app.folderInformation(folder.fullName, collection);
}
} else {
this.listCount(0);

View file

@ -52,7 +52,7 @@ class FolderClearPopupView extends AbstractViewPopup {
folderToClear.messageCountAll(0);
folderToClear.messageCountUnread(0);
setFolderHash(folderToClear.fullNameRaw, '');
setFolderHash(folderToClear.fullName, '');
Remote.folderClear(iError => {
this.clearingProcess(false);
@ -62,7 +62,7 @@ class FolderClearPopupView extends AbstractViewPopup {
rl.app.reloadMessageList(true);
this.cancelCommand();
}
}, folderToClear.fullNameRaw);
}, folderToClear.fullName);
}
}

View file

@ -30,7 +30,7 @@ class FolderCreatePopupView extends AbstractViewPopup {
oItem =>
oItem ? (oItem.isSystemFolder() ? oItem.name() + ' ' + oItem.manageFolderSystemName() : oItem.name()) : '',
FolderUserStore.namespace
? item => FolderUserStore.namespace !== item.fullNameRaw.substr(0, FolderUserStore.namespace.length)
? item => FolderUserStore.namespace !== item.fullName.substr(0, FolderUserStore.namespace.length)
: null,
true
)

View file

@ -88,7 +88,7 @@ export class MailFolderList extends AbstractViewLeft {
rl.app.moveMessagesToFolder(
FolderUserStore.currentFolderFullNameRaw(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(),
folder.fullNameRaw,
folder.fullName,
event.ctrlKey
);
} else {
@ -96,8 +96,8 @@ export class MailFolderList extends AbstractViewLeft {
MessageUserStore.message(null);
}
if (folder.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()) {
setFolderHash(folder.fullNameRaw, '');
if (folder.fullName === FolderUserStore.currentFolderFullNameRaw()) {
setFolderHash(folder.fullName, '');
}
rl.route.setHash(