From 71a522f103a41b2f38f5d96ab476384efe3002e8 Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Tue, 24 Jun 2014 08:21:14 -0400
Subject: [PATCH] Separate list of saved searched from addressbooks list

---
 skins/classic/templates/addressbook.html |    1 
 skins/larry/templates/addressbook.html   |    2 
 skins/classic/addressbook.css            |    5 +
 program/steps/addressbook/func.inc       |   43 +++++++++-----
 skins/larry/styles.css                   |   18 +++++-
 skins/larry/addressbook.css              |   60 ++++++++++++++++++--
 program/js/app.js                        |   35 +++++++++--
 7 files changed, 132 insertions(+), 32 deletions(-)

diff --git a/program/js/app.js b/program/js/app.js
index 61698b8..7e67a9c 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -414,6 +414,17 @@
           this.command('list');
         }
 
+        if (this.gui_objects.savedsearchlist) {
+          this.savedsearchlist = new rcube_treelist_widget(this.gui_objects.savedsearchlist, {
+            id_prefix: 'rcmli',
+            id_encode: this.html_identifier_encode,
+            id_decode: this.html_identifier_decode
+          });
+
+          this.savedsearchlist.addEventListener('select', function(node) {
+            ref.triggerEvent('selectfolder', { folder:node.id, prefix:'rcmli' }); });
+        }
+
         this.set_page_buttons();
 
         if (this.env.cid) {
@@ -554,6 +565,7 @@
     // init treelist widget
     if (this.gui_objects.folderlist && window.rcube_treelist_widget) {
       this.treelist = new rcube_treelist_widget(this.gui_objects.folderlist, {
+          selectable: true,
           id_prefix: 'rcmli',
           id_encode: this.html_identifier_encode,
           id_decode: this.html_identifier_decode,
@@ -4760,7 +4772,8 @@
         $(this.gui_objects.addresslist_title).html(this.get_label('contacts'));
     }
 
-    this.select_folder(folder, '', true);
+    if (!this.env.search_id)
+      this.select_folder(folder, '', true);
 
     // load contacts remotely
     if (this.gui_objects.contactslist) {
@@ -5184,7 +5197,7 @@
 
       // find list (UL) element
       if (type == 'contactsearch')
-        ul = this.gui_objects.folderlist;
+        ul = this.gui_objects.savedsearchlist;
       else
         ul = $('ul.groups', this.get_folder_li(this.env.source,'',true));
 
@@ -5285,7 +5298,7 @@
         .html(prop.name);
 
     this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
-    this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, true);
+    this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, 'contactgroup');
 
     this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) });
   };
@@ -5567,7 +5580,7 @@
         .html(name),
       prop = { name:name, id:id };
 
-    this.treelist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch');
+    this.savedsearchlist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch');
     this.select_folder(key,'',true);
     this.enable_command('search-delete', true);
     this.env.search_id = id;
@@ -5593,7 +5606,7 @@
   this.remove_search_item = function(id)
   {
     var li, key = 'S'+id;
-    if (this.treelist.remove(key)) {
+    if (this.savedsearchlist.remove(key)) {
       this.triggerEvent('search_delete', { id:id, li:li });
     }
 
@@ -5613,7 +5626,13 @@
     }
 
     this.reset_qsearch();
-    this.select_folder('S'+id, '', true);
+
+    if (this.savedsearchlist) {
+      this.treelist.select('');
+      this.savedsearchlist.select('S'+id);
+    }
+    else
+      this.select_folder('S'+id, '', true);
 
     // reset vars
     this.env.current_page = 1;
@@ -6478,6 +6497,10 @@
   // mark a mailbox as selected and set environment variable
   this.select_folder = function(name, prefix, encode)
   {
+    if (this.savedsearchlist) {
+      this.savedsearchlist.select('');
+    }
+
     if (this.treelist) {
       this.treelist.select(name);
     }
diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc
index 8955488..f09deeb 100644
--- a/program/steps/addressbook/func.inc
+++ b/program/steps/addressbook/func.inc
@@ -112,7 +112,7 @@
 // register UI objects
 $OUTPUT->add_handlers(array(
     'directorylist'       => 'rcmail_directory_list',
-//  'groupslist'          => 'rcmail_contact_groups',
+    'savedsearchlist'     => 'rcmail_savedsearch_list',
     'addresslist'         => 'rcmail_contacts_list',
     'addresslisttitle'    => 'rcmail_contacts_list_title',
     'addressframe'        => 'rcmail_contact_frame',
@@ -251,6 +251,26 @@
         $out .= '</li>';
     }
 
+    $OUTPUT->set_env('contactgroups', $jsdata);
+    $OUTPUT->set_env('collapsed_abooks', (string)$RCMAIL->config->get('collapsed_abooks',''));
+    $OUTPUT->add_gui_object('folderlist', $attrib['id']);
+    $OUTPUT->include_script('treelist.js');
+
+    // add some labels to client
+    $OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember');
+
+    return html::tag('ul', $attrib, $out, html::$common_attrib);
+}
+
+
+function rcmail_savedsearch_list($attrib)
+{
+    global $RCMAIL, $OUTPUT;
+
+    if (!$attrib['id'])
+        $attrib['id'] = 'rcmsavedsearchlist';
+
+    $out = '';
     $line_templ = html::tag('li', array(
         'id' => 'rcmli%s', 'class' => '%s'),
         html::a(array('href' => '#', 'rel' => 'S%s',
@@ -263,26 +283,19 @@
         $js_id = rcube::JQ($id);
 
         // set class name(s)
-        $class_name = 'contactsearch';
-        if ($current === $id)
-            $class_name .= ' selected';
-        if ($source['class_name'])
-            $class_name .= ' ' . $source['class_name'];
+        $classes = array('contactsearch');
+        if (!empty($source['class_name']))
+            $classes[] = $source['class_name'];
 
         $out .= sprintf($line_templ,
             rcube_utils::html_identifier('S'.$id, true),
-            $class_name,
+            join(' ', $classes),
             $id,
-            $js_id, (!empty($source['name']) ? rcube::Q($source['name']) : rcube::Q($id)));
+            $js_id, (!empty($source['name']) ? rcube::Q($source['name']) : rcube::Q($id))
+        );
     }
 
-    $OUTPUT->set_env('contactgroups', $jsdata);
-    $OUTPUT->set_env('collapsed_abooks', (string)$RCMAIL->config->get('collapsed_abooks',''));
-    $OUTPUT->add_gui_object('folderlist', $attrib['id']);
-    $OUTPUT->include_script('treelist.js');
-
-    // add some labels to client
-    $OUTPUT->add_label('deletegroupconfirm', 'groupdeleting', 'addingmember', 'removingmember');
+    $OUTPUT->add_gui_object('savedsearchlist', $attrib['id']);
 
     return html::tag('ul', $attrib, $out, html::$common_attrib);
 }
diff --git a/skins/classic/addressbook.css b/skins/classic/addressbook.css
index 3005258..b118353 100644
--- a/skins/classic/addressbook.css
+++ b/skins/classic/addressbook.css
@@ -144,7 +144,8 @@
   width: 280px;
 }
 
-#directorylist li a
+#directorylist li a,
+#savedsearchlist li a
 {
   cursor: default;
   display: block;
@@ -169,7 +170,7 @@
   background-position: 22px -143px;
 }
 
-#directorylist li.contactsearch a
+#savedsearchlist li.contactsearch a
 {
   background-position: 6px -162px;
 }
diff --git a/skins/classic/templates/addressbook.html b/skins/classic/templates/addressbook.html
index 5399586..0af5e43 100644
--- a/skins/classic/templates/addressbook.html
+++ b/skins/classic/templates/addressbook.html
@@ -61,6 +61,7 @@
 <div id="directorylist-title" class="boxtitle"><roundcube:label name="groups" /></div>
 <div id="directorylist-content" class="boxlistcontent">
   <roundcube:object name="directorylist" id="directorylist" class="treelist" />
+  <roundcube:object name="savedsearchlist" id="savedsearchlist" class="treelist" />
 </div>
 <div id="directorylist-footer" class="boxfooter">
   <roundcube:button command="group-create" type="link" title="newgroup" class="buttonPas addgroup" classAct="button addgroup" content=" " />
diff --git a/skins/larry/addressbook.css b/skins/larry/addressbook.css
index 0583ce0..bf704f7 100644
--- a/skins/larry/addressbook.css
+++ b/skins/larry/addressbook.css
@@ -66,6 +66,7 @@
 }
 
 #directorylist li a,
+.treelist li.contactsearch a,
 #contacts-table .contact td.name {
 	background-image: url(images/listicons.png);
 	background-position: -100px 0;
@@ -74,46 +75,93 @@
 	text-overflow: ellipsis;
 }
 
+#directorylist li.virtual {
+	background-image: none !important;
+}
+
+#directorylist li.virtual > a {
+	color: #aaa;
+	background-image: none;
+	height: 16px;
+	padding-top: 3px;
+	padding-bottom: 3px;
+}
+
+#directorylist li.virtual > .treetoggle {
+	top: 6px !important;
+}
+
+#directorylist ul li.virtual > .treetoggle {
+}
+
 #directorylist li.addressbook a {
 	background-position: 6px -766px;
 }
 
+#directorylist ul li.addressbook a {
+	background-position: 32px -766px;
+}
+
+#directorylist ul ul li.addressbook a {
+	background-position: 58px -766px;
+}
+
 #directorylist li.addressbook.selected > a {
+	background-color: transparent;
 	background-position: 6px -791px;
 }
 
-#directorylist li.addressbook ul.groups li {
-	width: 100%;
+#directorylist ul li.addressbook.selected > a {
+	background-position: 32px -791px;
+}
+
+#directorylist ul ul li.addressbook.selected > a {
+	background-position: 58px -791px;
 }
 
 #directorylist li.contactgroup a {
 	background-position: 32px -1555px;
 }
 
+#directorylist ul ul li.contactgroup a {
+	background-position: 58px -1555px;
+}
+
+#directorylist ul ul ul li.contactgroup a {
+	background-position: 84px -1555px;
+}
+
 #directorylist li.contactgroup.selected a {
 	background-position: 32px -1579px;
+}
+
+#directorylist ul ul li.contactgroup.selected a {
+	background-position: 58px -1579px;
+}
+
+#directorylist ul ul ul li.contactgroup.selected a {
+	background-position: 84px -1579px;
 }
 
 #directorylist li.contactgroup input {
 	margin-left: 36px;
 }
 
-#directorylist li.contactsearch a {
+.treelist li.contactsearch a {
 	background-position: 6px -1651px;
 }
 
-#directorylist li.contactsearch.selected a {
+.treelist li.contactsearch.selected a {
 	background-position: 6px -1675px;
 }
 
-#directorylist li.contactsearch input {
+.treelist li.contactsearch input {
 	margin-left: 8px;
 }
 
 #directorylist li.addressbook div.collapsed,
 #directorylist li.addressbook div.expanded {
 	top: 15px;
-	left: 20px;
 }
 
 #contacts-table .contact.readonly td {
diff --git a/skins/larry/styles.css b/skins/larry/styles.css
index 313455b..e4a5c67 100644
--- a/skins/larry/styles.css
+++ b/skins/larry/styles.css
@@ -1334,8 +1334,16 @@
 	padding-left: 36px;
 }
 
-ul.treelist.iconized li ul li a {
+ul.treelist.iconized ul li a {
 	padding-left: 62px;
+}
+
+ul.treelist.iconized ul ul li a {
+	padding-left: 88px;
+}
+
+ul.treelist.iconized ul ul ul li a {
+	padding-left: 114px;
 }
 
 ul.treelist li div.treetoggle {
@@ -1357,8 +1365,12 @@
 	left: 19px;
 }
 
-ul.treelist.iconized li ul li div.treetoggle {
-	left: 35px;
+ul.treelist.iconized ul li div.treetoggle {
+	left: 45px;
+}
+
+ul.treelist.iconized ul ul li div.treetoggle {
+	left: 71px;
 }
 
 ul.treelist li div.treetoggle.expanded {
diff --git a/skins/larry/templates/addressbook.html b/skins/larry/templates/addressbook.html
index 60ea355..424e965 100644
--- a/skins/larry/templates/addressbook.html
+++ b/skins/larry/templates/addressbook.html
@@ -65,6 +65,8 @@
 <h2 id="directorylist-header" class="boxtitle"><roundcube:label name="groups" /></h2>
 <div id="directorylist-content" class="scroller withfooter">
 	<roundcube:object name="directorylist" id="directorylist" class="treelist listing iconized" />
+	<h3 class="boxtitle voice"><roundcube:label name="savedsearches" /></h3>
+	<roundcube:object name="savedsearchlist" id="savedsearchlist" class="treelist listing iconized" />
 </div>
 <div id="directorylist-footer" class="boxfooter">
 	<roundcube:button command="group-create" type="link" title="newgroup" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="addgroup" /><roundcube:button name="groupoptions" id="groupoptionslink" type="link" title="moreactions" class="listbutton groupactions" onclick="return UI.toggle_popup('groupoptions',event)" innerClass="inner" label="arialabelabookgroupoptions" aria-haspopup="true" aria-expanded="false" aria-owns="groupoptionsmenu" />

--
Gitblit v1.9.1