@@ -774,7 +774,7 @@ function rcube_webmail() {
774774 var body_mouseup = function ( e ) {
775775 // Stop dragging in sortable list if the mouseup event happens over an iframe.
776776 if ( ref . gui_objects . subscriptionlist && e . target . ownerDocument !== ref . gui_objects . subscriptionlist . ownerDocument ) {
777- $ ( ref . gui_objects . subscriptionlist ) . trigger ( 'mouseup' ) ;
777+ ref . subscription_list . sortable_cancel ( ) ;
778778 }
779779 return ref . doc_mouse_up ( e ) ;
780780 } ;
@@ -7802,6 +7802,7 @@ function rcube_webmail() {
78027802 } ) ;
78037803
78047804 this . subscription_list
7805+ . sortable_init ( )
78057806 . addEventListener ( 'select' , function ( node ) {
78067807 ref . subscription_select ( node . id ) ;
78077808 } )
@@ -7816,100 +7817,15 @@ function rcube_webmail() {
78167817 ref . subscription_select ( ) ;
78177818 }
78187819 } ) ;
7819-
7820- this . make_folder_lists_sortable ( ) ;
7821- } ;
7822-
7823- // TODO: In the receive callback, can we wait for the confirmation dialog without introducing async/await and Promises?
7824- this . make_folder_lists_sortable = ( ) => {
7825- const mainFolderList = this . gui_objects . subscriptionlist ;
7826- $folderLists = $ ( 'ul' , mainFolderList . parentElement ) ;
7827- $folderLists . sortable ( {
7828- axis : 'y' ,
7829- // We can't use `li.mailbox.protected` here because that would disable moving elements out of protected
7830- // folders. jQuery UI uses `closest()` with this selector, which makes it impossible to keep main list items
7831- // and sub-list items apart. We disable sorting protected items via a `mousedown` event in treelist.js.
7832- cancel : 'input, div.treetoggle, .custom-control' ,
7833- helper : 'clone' , // a clone doesn't have the borders, which looks nicer.
7834- items : '> li.mailbox' , // handle only the directly descending items, not those of sub-lists (they get they own instance of $.sortable()
7835- connectWith : `#${ mainFolderList . id } , #${ mainFolderList . id } ul` ,
7836- forcePlaceholderSize : true , // Make the placeholder displace the neighboring elements.
7837- placeholder : 'placeholder' , // Class name for the placeholder
7838- change : ( event , ui ) => {
7839- // Prevent sortable folders being sorted in between (technically: before) protected folders. There is no
7840- // technical reason for this, we just want it from a UX perspective.
7841- if ( ui . placeholder . next ( ) . is ( '.protected' ) ) {
7842- ui . placeholder . hide ( ) ;
7843- } else {
7844- ui . placeholder . show ( ) ;
7845- }
7846- } ,
7847- over : ( event , ui ) => {
7848- // Highlight the list that the dragged element is hovering over.
7849- $ ( '.hover' , $folderLists ) . removeClass ( 'hover' ) ;
7850- if ( event . target !== mainFolderList ) {
7851- $ ( event . target ) . closest ( 'li' ) . addClass ( 'hover' ) ;
7852- }
7853- } ,
7854- receive : async ( event , ui ) => {
7855- $ ( '.hover' , $folderLists ) . removeClass ( 'hover' ) ;
7856- const folderId = ui . item . attr ( 'id' ) ;
7857- const folderName = ref . folder_id2name ( folderId ) ;
7858- const folderAttribs = ref . env . subscriptionrows [ folderName ] ;
7859-
7860- let destName ;
7861- if ( event . target === mainFolderList ) {
7862- destName = '*' ;
7863- } else {
7864- const destId = event . target . parentElement . id ;
7865- destName = ref . folder_id2name ( destId ) ;
7866- }
7867-
7868- if ( ! (
7869- folderAttribs && ! folderAttribs [ 2 ]
7870- && destName != folderName . replace ( ref . last_sub_rx , '' )
7871- && ! destName . startsWith ( folderName + ref . env . delimiter )
7872- ) ) {
7873- ui . sender . sortable ( 'cancel' ) ;
7874- }
7875-
7876- const result = await ref . subscription_move_folder ( folderName , destName ) ;
7877- if ( ! result ) {
7878- ui . sender . sortable ( 'cancel' ) ;
7879- }
7880- } ,
7881- stop : ( event , ui ) => {
7882- $ ( '.hover' , $folderLists ) . removeClass ( 'hover' ) ;
7883- if ( ui . item . next ( ) . is ( '.protected' ) ) {
7884- ui . item . parent ( ) . sortable ( 'cancel' ) ;
7885- return false ;
7886- }
7887- } ,
7888- update : ( event , ui ) => {
7889- // Save the order if the item was moved only within its list. In case it was moved into a (different)
7890- // sub-list, the order-saving function gets called from the server's response after the relevant folder
7891- // rows have been re-rendered, and we can save one HTTP request. We don't skip the other function call
7892- // because in this moment here we don't know yet if the confirmation dialog about moving the folder will
7893- // be confirmed or cancelled.
7894- if ( ui . item [ 0 ] . parentElement === event . target ) {
7895- ref . save_reordered_folder_list ( ) ;
7896- }
7897- } ,
7898- } ) ;
78997820 } ;
79007821
79017822 this . save_reordered_folder_list = ( ) => {
7902- const mainList = ref . subscription_list . container . sortable ( 'toArray' ) ;
7903- const subLists = ref . subscription_list . container . find ( '.ui-sortable' ) . map ( ( i , elem ) => ( {
7904- parentId : elem . parentElement . id ,
7905- elems : $ ( elem ) . sortable ( 'toArray' ) ,
7906- } ) ) . toArray ( ) ;
7907- // Sort sub-lists after their their parent element, so the sorting for the settings page doesn't get confused
7908- // (which will hook child-folders onto wrong parents if we don't do this).
7909- subLists . forEach ( ( subList ) => {
7910- mainList . splice ( mainList . indexOf ( subList . parentId ) + 1 , 0 , ...subList . elems ) ;
7911- } ) ;
7912- params = mainList . map ( ( e ) => e . replace ( / ^ r c m l i / , 'folderorder[]=' ) ) . join ( '&' ) ;
7823+ const items = ref . subscription_list . sortable_get_items ( ) ;
7824+ if ( ! items ) {
7825+ console . error ( 'Failed to get sorted items from folder list, cannot save.' ) ;
7826+ return false ;
7827+ }
7828+ const params = items . map ( ( e ) => e . replace ( / ^ r c m l i / , 'folderorder[]=' ) ) . join ( '&' ) ;
79137829 this . http_post ( 'folder-reorder' , params , this . display_message ( '' , 'loading' ) ) ;
79147830 } ;
79157831
@@ -7999,8 +7915,18 @@ function rcube_webmail() {
79997915 }
80007916 } ;
80017917
8002- this . subscription_move_folder = function ( from , to ) {
8003- if ( from && to !== null && from != to && to != from . replace ( this . last_sub_rx , '' ) ) {
7918+ this . subscription_move_folder = function ( folderId , destId ) {
7919+ const from = rcmail . folder_id2name ( folderId ) ;
7920+ const fromAttribs = rcmail . env . subscriptionrows [ from ] ;
7921+
7922+ let to ;
7923+ if ( destId === '*' ) {
7924+ to = '*' ;
7925+ } else {
7926+ to = rcmail . folder_id2name ( destId ) ;
7927+ }
7928+
7929+ if ( from && fromAttribs && ! fromAttribs [ 2 ] && to !== null && ! to . startsWith ( from + rcmail . env . delimiter ) && from != to && to != from . replace ( this . last_sub_rx , '' ) ) {
80047930 var path = from . split ( this . env . delimiter ) ,
80057931 basename = path . pop ( ) ,
80067932 newname = to === '' || to === '*' ? basename : to + this . env . delimiter + basename ;
0 commit comments