From 3cb61e7528c2a8544083bf14e02ea4b9387671fb Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Wed, 16 Jul 2014 11:08:11 +0200 Subject: Collapsible (and iconized) folders tree in folder manager (#1489648) --- program/steps/settings/edit_folder.inc | 36 +++++------ program/steps/settings/folders.inc | 112 +++++++++++++++++++++------------ program/steps/settings/func.inc | 17 +++-- program/steps/settings/save_folder.inc | 10 ++- 4 files changed, 101 insertions(+), 74 deletions(-) (limited to 'program/steps') diff --git a/program/steps/settings/edit_folder.inc b/program/steps/settings/edit_folder.inc index 51f4d8d72..172a953ff 100644 --- a/program/steps/settings/edit_folder.inc +++ b/program/steps/settings/edit_folder.inc @@ -38,22 +38,20 @@ function rcmail_folder_form($attrib) $storage = $RCMAIL->get_storage(); // edited folder name (empty in create-folder mode) - $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true); - $mbox_imap = rcube_charset::convert($mbox, RCUBE_CHARSET, 'UTF7-IMAP'); + $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true); // predefined path for new folder - $parent = rcube_utils::get_input_value('_path', rcube_utils::INPUT_GPC, true); - $parent_imap = rcube_charset::convert($parent, RCUBE_CHARSET, 'UTF7-IMAP'); + $parent = rcube_utils::get_input_value('_path', rcube_utils::INPUT_GPC, true); $threading_supported = $storage->get_capability('THREAD'); $delimiter = $storage->get_hierarchy_delimiter(); // Get mailbox parameters if (strlen($mbox)) { - $options = rcmail_folder_options($mbox_imap); + $options = rcmail_folder_options($mbox); $namespace = $storage->get_namespace(); - $path = explode($delimiter, $mbox_imap); + $path = explode($delimiter, $mbox); $folder = array_pop($path); $path = implode($delimiter, $path); $folder = rcube_charset::convert($folder, 'UTF7-IMAP'); @@ -62,7 +60,7 @@ function rcmail_folder_form($attrib) } else { $options = array(); - $path = $parent_imap; + $path = $parent; // allow creating subfolders of INBOX folder if ($path == 'INBOX') { @@ -88,7 +86,7 @@ function rcmail_folder_form($attrib) // Location (name) if ($options['protected']) { - $foldername = str_replace($delimiter, ' » ', rcube::Q($RCMAIL->localize_folderpath($mbox_imap))); + $foldername = str_replace($delimiter, ' » ', rcube::Q($RCMAIL->localize_folderpath($mbox))); } else if ($options['norename']) { $foldername = rcube::Q($folder); @@ -101,7 +99,7 @@ function rcmail_folder_form($attrib) $foldername = $foldername->show($folder); if ($options['special']) { - $foldername .= ' (' . rcube::Q($RCMAIL->localize_foldername($mbox_imap)) .')'; + $foldername .= ' (' . rcube::Q($RCMAIL->localize_foldername($mbox)) .')'; } } @@ -122,7 +120,7 @@ function rcmail_folder_form($attrib) } else { $selected = isset($_POST['_parent']) ? $_POST['_parent'] : $path_id; - $exceptions = array($mbox_imap); + $exceptions = array($mbox); // Exclude 'prefix' namespace from parent folders list (#1488349) // If INBOX. namespace exists, folders created as INBOX subfolders @@ -154,7 +152,7 @@ function rcmail_folder_form($attrib) ); // Settings: threading - if ($threading_supported && ($mbox_imap == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) { + if ($threading_supported && ($mbox == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) { $select = new html_select(array('name' => '_viewmode', 'id' => '_viewmode')); $select->add($RCMAIL->gettext('list'), 0); $select->add($RCMAIL->gettext('threads'), 1); @@ -162,11 +160,11 @@ function rcmail_folder_form($attrib) if (isset($_POST['_viewmode'])) { $value = (int) $_POST['_viewmode']; } - else if (strlen($mbox_imap)) { + else if (strlen($mbox)) { $a_threaded = $RCMAIL->config->get('message_threading', array()); $default_mode = $RCMAIL->config->get('default_list_mode', 'list'); - $value = (int) (isset($a_threaded[$mbox_imap]) ? $a_threaded[$mbox_imap] : $default_mode == 'threads'); + $value = (int) (isset($a_threaded[$mbox]) ? $a_threaded[$mbox] : $default_mode == 'threads'); } $form['props']['fieldsets']['settings']['content']['viewmode'] = array( @@ -213,14 +211,14 @@ function rcmail_folder_form($attrib) 'content' => array() ); - if ((!$options['noselect'] && !$options['is_root']) || $mbox_imap == 'INBOX') { - $msgcount = $storage->count($mbox_imap, 'ALL', true, false); + if ((!$options['noselect'] && !$options['is_root']) || $mbox == 'INBOX') { + $msgcount = $storage->count($mbox, 'ALL', true, false); // Size if ($msgcount) { // create link with folder-size command $onclick = sprintf("return %s.command('folder-size', '%s', this)", - rcmail_output::JS_OBJECT_NAME, rcube::JQ($mbox_imap)); + rcmail_output::JS_OBJECT_NAME, rcube::JQ($mbox)); $size = html::a(array('href' => '#', 'onclick' => $onclick, 'id' => 'folder-size'), $RCMAIL->gettext('getfoldersize')); } @@ -250,7 +248,7 @@ function rcmail_folder_form($attrib) // Allow plugins to modify folder form content $plugin = $RCMAIL->plugins->exec_hook('folder_form', array('form' => $form, 'options' => $options, - 'name' => $mbox_imap, 'parent_name' => $parent_imap)); + 'name' => $mbox, 'parent_name' => $parent)); $form = $plugin['form']; @@ -290,8 +288,8 @@ function rcmail_folder_form($attrib) $RCMAIL->output->set_env('messagecount', (int) $msgcount); - if ($mbox_imap !== null && empty($_POST)) { - $RCMAIL->output->command('parent.set_quota', $RCMAIL->quota_content(null, $mbox_imap)); + if ($mbox !== null && empty($_POST)) { + $RCMAIL->output->command('parent.set_quota', $RCMAIL->quota_content(null, $mbox)); } return $out; diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc index ad5f37d95..19c4457a1 100644 --- a/program/steps/settings/folders.inc +++ b/program/steps/settings/folders.inc @@ -20,14 +20,12 @@ +-----------------------------------------------------------------------+ */ -// WARNING: folder names in UI are encoded with RCUBE_CHARSET - // init IMAP connection $STORAGE = $RCMAIL->get_storage(); // subscribe mailbox if ($RCMAIL->action == 'subscribe') { - $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true, 'UTF7-IMAP'); + $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); if (strlen($mbox)) { $result = $STORAGE->subscribe(array($mbox)); @@ -58,7 +56,8 @@ if ($RCMAIL->action == 'subscribe') { } // unsubscribe mailbox else if ($RCMAIL->action == 'unsubscribe') { - $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true, 'UTF7-IMAP'); + $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); + if (strlen($mbox)) { $result = $STORAGE->unsubscribe(array($mbox)); if ($result) @@ -69,8 +68,7 @@ else if ($RCMAIL->action == 'unsubscribe') { } // delete an existing mailbox else if ($RCMAIL->action == 'delete-folder') { - $mbox_utf8 = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); - $mbox = rcube_charset::convert($mbox_utf8, RCUBE_CHARSET, 'UTF7-IMAP'); + $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); if (strlen($mbox)) { $plugin = $RCMAIL->plugins->exec_hook('folder_delete', array('name' => $mbox)); @@ -90,7 +88,7 @@ else if ($RCMAIL->action == 'delete-folder') { if ($OUTPUT->ajax_call && $deleted) { // Remove folder and subfolders rows - $OUTPUT->command('remove_folder_row', $mbox_utf8, true); + $OUTPUT->command('remove_folder_row', $mbox); $OUTPUT->show_message('folderdeleted', 'confirmation'); // Clear content frame $OUTPUT->command('subscription_select'); @@ -102,13 +100,10 @@ else if ($RCMAIL->action == 'delete-folder') { } // rename an existing mailbox else if ($RCMAIL->action == 'rename-folder') { - $name_utf8 = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true)); - $oldname_utf8 = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true); - - if (strlen($name_utf8) && strlen($oldname_utf8)) { - $name = rcube_charset::convert($name_utf8, RCUBE_CHARSET, 'UTF7-IMAP'); - $oldname = rcube_charset::convert($oldname_utf8, RCUBE_CHARSET, 'UTF7-IMAP'); + $name = trim(rcube_utils::get_input_value('_folder_newname', rcube_utils::INPUT_POST, true)); + $oldname = rcube_utils::get_input_value('_folder_oldname', rcube_utils::INPUT_POST, true); + if (strlen($name) && strlen($oldname)) { $rename = rcmail_rename_folder($oldname, $name); } @@ -121,8 +116,7 @@ else if ($RCMAIL->action == 'rename-folder') { } // clear mailbox else if ($RCMAIL->action == 'purge') { - $mbox_utf8 = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); - $mbox = rcube_charset::convert($mbox_utf8, RCUBE_CHARSET, 'UTF7-IMAP'); + $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); $delimiter = $STORAGE->get_hierarchy_delimiter(); $trash_mbox = $RCMAIL->config->get('trash_mbox'); $trash_regexp = '/^' . preg_quote($trash . $delimiter, '/') . '/'; @@ -150,7 +144,7 @@ else if ($RCMAIL->action == 'purge') { $OUTPUT->show_message('messagemoved', 'confirmation'); } $_SESSION['unseen_count'][$mbox] = 0; - $OUTPUT->command('show_folder', $mbox_utf8, null, true); + $OUTPUT->command('show_folder', $mbox, null, true); } else { $RCMAIL->display_server_error('errorsaving'); @@ -270,6 +264,7 @@ function rcube_subscription_form($attrib) $js_folders = array(); $folders = array(); + $collapsed = $RCMAIL->config->get('collapsed_folders'); // create list of available folders foreach ($list_folders as $i => $folder) { @@ -278,11 +273,10 @@ function rcube_subscription_form($attrib) $subscribed = $sub_key !== false; $protected = $protect_default && isset($special_folders[$folder['id']]); $noselect = false; - $classes = array('listitem'); + $classes = array(); $folder_utf8 = rcube_charset::convert($folder['id'], 'UTF7-IMAP'); - $display_folder = str_repeat('    ', $folder['level']) - . rcube::Q($protected ? $RCMAIL->localize_foldername($folder['id']) : $folder['name']); + $display_folder = rcube::Q($protected ? $RCMAIL->localize_foldername($folder['id']) : $folder['name']); if ($folder['virtual']) { $classes[] = 'virtual'; @@ -338,45 +332,85 @@ function rcube_subscription_form($attrib) } } - $row_id = 'rcmli' . $idx; - $folders[$row_id] = array( + $is_collapsed = strpos($collapsed, '&'.rawurlencode($folder['id']).'&') !== false; + $folder_id = rcube_utils::html_identifier($folder['id'], true); + + if ($folder_class = $RCMAIL->folder_classname($folder['id'])) { + $classes[] = $folder_class; + } + + $folders[$folder['id']] = array( + 'idx' => $folder_id, + 'folder_imap' => $folder['id'], 'folder' => $folder_utf8, 'display' => $display_folder, + 'protected' => $protected || $folder['virtual'], 'class' => join(' ', $classes), - 'folder_imap' => $folder['id'], 'subscribed' => $subscribed, - 'protected' => $protected || $folder['virtual'], - 'content' => html::a(array('class' => 'name', 'href' => '#_' . $row_id), $display_folder) - . $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''), - array('value' => $folder_utf8, 'disabled' => $disabled ? 'disabled' : '')) + 'level' => $folder['level'], + 'collapsed' => $is_collapsed, + 'content' => html::a(array('href' => '#'), $display_folder) + . $checkbox_subscribe->show(($subscribed ? $folder['id'] : ''), + array('value' => $folder['id'], 'disabled' => $disabled ? 'disabled' : '')) ); } $plugin = $RCMAIL->plugins->exec_hook('folders_list', array('list' => $folders)); // add drop-target representing 'root' - $roots = array( - 'mailboxroot' => array( - 'folder' => '', - 'display' => '', - 'protected' => true, - 'class' => 'root', - 'content' => html::span('name', ' ') - ) + $root = array( + 'idx' => rcube_utils::html_identifier('*', true), + 'folder_imap' => '*', + 'folder' => '', + 'display' => '', + 'protected' => true, + 'class' => 'root', + 'content' => ' ', ); - $folders = array_merge($roots, $plugin['list']); - while (list($key, $data) = each($folders)) { - $js_folders[$key] = array($data['folder'], $data['display'], $data['protected']); - $folders[$key] = html::tag('li', array('id' => $key, 'class' => $data['class']), $data['content']); + $folders = array(); + $plugin['list'] = array_values($plugin['list']); + + array_unshift($plugin['list'], $root); + + for ($i = 0, $length = count($plugin['list'])-1; $i<$length; $i++) { + $folders[] = rcmail_folder_tree_element($plugin['list'], $i, $js_folders); } $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); $OUTPUT->set_env('subscriptionrows', $js_folders); $OUTPUT->set_env('defaultfolders', array_keys($special_folders)); + $OUTPUT->set_env('collapsed_folders', $collapsed); $OUTPUT->set_env('delimiter', $delimiter); - return $form_start . html::tag('ul', $attrib, implode("\n", $folders)) . $form_end; + return $form_start . html::tag('ul', $attrib, implode('', $folders), html::$common_attrib) . $form_end; +} + +function rcmail_folder_tree_element($folders, &$key, &$js_folders) +{ + $data = $folders[$key]; + $idx = 'rcmli' . $data['idx']; + + $js_folders[$data['folder_imap']] = array($data['folder'], $data['display'], $data['protected']); + $content = $data['content']; + $attribs = array( + 'id' => $idx, + 'class' => trim($data['class'] . ' mailbox') + ); + + $children = array(); + while ($folders[$key+1] && $folders[$key+1]['level'] > $data['level']) { + $key++; + $children[] = rcmail_folder_tree_element($folders, $key, $js_folders); + } + + if (!empty($children)) { + $content .= html::div('treetoggle ' . ($data['collapsed'] ? 'collapsed' : 'expanded'), ' ') + . html::tag('ul', array('style' => ($data['collapsed'] ? "display:none" : null)), + implode("\n", $children)); + } + + return html::tag('li', $attribs, $content); } function rcmail_folder_frame($attrib) diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 8a96ada6b..619710f32 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -1302,23 +1302,20 @@ function rcmail_update_folder_row($name, $oldname=null, $subscribe=false, $class $protect_folders = $RCMAIL->config->get('protect_default_folders'); $storage = $RCMAIL->get_storage(); $delimiter = $storage->get_hierarchy_delimiter(); - $name_utf8 = rcube_charset::convert($name, 'UTF7-IMAP'); - $protected = $protect_folders && $storage->is_special_folder($name); + $name_utf8 = rcube_charset::convert($name, 'UTF7-IMAP'); + $protected = $protect_folders && $storage->is_special_folder($name); $foldersplit = explode($delimiter, $storage->mod_folder($name)); $level = count($foldersplit) - 1; - $display_name = str_repeat('    ', $level) - . rcube::Q($protected ? $RCMAIL->localize_foldername($name) : rcube_charset::convert($foldersplit[$level], 'UTF7-IMAP')); - - $class_name = trim($class_name . ' listitem'); + $display_name = $protected ? $RCMAIL->localize_foldername($name) : rcube_charset::convert($foldersplit[$level], 'UTF7-IMAP'); + $class_name = trim($class_name . ' mailbox'); if ($oldname === null) { - $OUTPUT->command('add_folder_row', $name_utf8, $display_name, $protected, $subscribe, - false, $class_name); + $OUTPUT->command('add_folder_row', $name, $name_utf8, $display_name, $protected, $subscribe, + $class_name); } else { - $OUTPUT->command('replace_folder_row', rcube_charset::convert($oldname, 'UTF7-IMAP'), - $name_utf8, $display_name, $protected, $class_name); + $OUTPUT->command('replace_folder_row', $oldname, $name, $name_utf8, $display_name, $protected, $class_name); } } diff --git a/program/steps/settings/save_folder.inc b/program/steps/settings/save_folder.inc index a054224f1..9bb6bf3ab 100644 --- a/program/steps/settings/save_folder.inc +++ b/program/steps/settings/save_folder.inc @@ -24,12 +24,10 @@ // init IMAP connection $STORAGE = $RCMAIL->get_storage(); -$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true)); -$old = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); -$path = rcube_utils::get_input_value('_parent', rcube_utils::INPUT_POST, true); - +$name = trim(rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true)); +$path = rcube_utils::get_input_value('_parent', rcube_utils::INPUT_POST, true); +$old_imap = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST, true); $name_imap = rcube_charset::convert($name, RCUBE_CHARSET, 'UTF7-IMAP'); -$old_imap = rcube_charset::convert($old, RCUBE_CHARSET, 'UTF7-IMAP'); // $path is in UTF7-IMAP already $delimiter = $STORAGE->get_hierarchy_delimiter(); @@ -96,7 +94,7 @@ else { } // create a new mailbox -if (!$error && !strlen($old)) { +if (!$error && !strlen($old_imap)) { $folder['subscribe'] = true; $plugin = $RCMAIL->plugins->exec_hook('folder_create', array('record' => $folder)); -- cgit v1.2.3