mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-28 11:39:21 +03:00
Support RFC 6855 / RFC 5738 (UTF8)
This commit is contained in:
parent
c9a497eb9d
commit
299ec7faf8
25 changed files with 249 additions and 505 deletions
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
});
|
||||
}
|
||||
|
|
|
|||
2
dev/External/User/ko.js
vendored
2
dev/External/User/ko.js
vendored
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue