Changeset 0430323


Ignore:
Timestamp:
Dec 16, 2017 2:16:56 PM (2 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
7164059
Parents:
c2a1d79
Message:

SusiMail?: Sorting cleanups and fixes, only sort when required

Location:
apps/susimail/src/src/i2p/susi
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • apps/susimail/src/src/i2p/susi/util/Folder.java

    rc2a1d79 r0430323  
    4040 *
    4141 * You create a folder object, set the contents with setElements(),
    42  * add Comparators with addSorter(), choose one with sortBy() and
     42 * add Comparators with addSorter(), choose one with setSortBy() and
    4343 * and then fetch the content of the current page with
    4444 * currentPageIterator().
     
    154154        /**
    155155         * Sorts the elements according the order given by @link addSorter()
    156          * and @link sortBy().
    157          */
    158         private void sort()
    159         {
    160                 if( currentSorter != null )
     156         * and @link setSortBy().
     157         *
     158         * @since public since 0.9.33
     159         */
     160        public synchronized void sort()
     161        {
     162                if (currentSorter != null && elements != null && elements.length > 1)
    161163                        Arrays.sort( elements, currentSorter );
    162164        }
     
    165167         * Set the array of objects the folder should manage.
    166168         * Does NOT copy the array.
     169         * Sorts the array if a sorter set.
    167170         *
    168171         * @param elements Array of Os.
     
    172175                if (elements.length > 0) {
    173176                        this.elements = elements;
    174                         if( currentSorter != null )
    175                                 sort();
     177                        sort();
    176178                } else {
    177179                        this.elements = null;
     
    214216         *
    215217         * @param element to add
    216          */
    217         public void addElement(O element) {
    218                 addElements(Collections.singleton(element));
    219         }
    220        
    221         /**
    222          * Add elements only if it they do not already exist
    223          *
    224          * @param elems to adde
     218         * @return true if added
     219         */
     220        public boolean addElement(O element) {
     221                return addElements(Collections.singletonList(element));
     222        }
     223       
     224        /**
     225         * Add elements only if they do not already exist
     226         * Re-sorts the array if a sorter is set and any elements are actually added.
     227         *
     228         * @param elems to add
     229         * @return true if any were added
    225230         */
    226231        @SuppressWarnings("unchecked")
    227         public synchronized void addElements(Collection<O> elems) {
     232        public synchronized boolean addElements(List<O> elems) {
     233                boolean shouldUpdate = false;
    228234                if (elements != null) {
    229                         List<O> list = new ArrayList<O>(Arrays.asList(elements));
    230                         boolean shouldUpdate = false;
     235                        // delay copy until required
     236                        List<O> list = null;
    231237                        for (O e : elems) {
    232                                 if (!list.contains(e)) {
     238                                boolean found = false;
     239                                for (int i = 0; i < elements.length; i++) {
     240                                        if (e.equals(elements[i])) {
     241                                                found = true;
     242                                                break;
     243                                        }
     244                                }
     245                                if (!found) {
     246                                        if (list == null) {
     247                                                list = new ArrayList<O>(Arrays.asList(elements));
     248                                                shouldUpdate = true;
     249                                        }
    233250                                        list.add(e);
    234                                         shouldUpdate = true;
    235251                                }
    236252                        }
    237253                        if (shouldUpdate) {
    238                                 elements = (O[]) list.toArray(new Object[list.size()]);
    239                                 sort();
    240                                 update();
     254                                setElements((O[]) list.toArray(new Object[list.size()]));
    241255                        }
    242                 }
     256                } else if (!elems.isEmpty()) {
     257                        setElements((O[]) (elems.toArray(new Object[elems.size()])));
     258                        shouldUpdate = true;
     259                }
     260                return shouldUpdate;
    243261        }
    244262       
     
    304322        /**
    305323         * Adds a new sorter to the folder. You can sort the folder by
    306          * calling sortBy() and choose the given id there.
    307          *
    308          * @param id ID to identify the Comparator with @link sortBy()
     324         * calling setSortBy() and choose the given id there.
     325         *
     326         * @param id ID to identify the Comparator with @link setSortBy()
    309327         * @param sorter a Comparator to sort the Array given by @link setElements()
    310328         */
     
    318336         * match the one, which the Comparator has been stored in the
    319337         * folder with @link addSorter().
     338         * Sets the sorting direction of the folder.
     339         *
     340         * Warning, this does not do the actual sort, only addElements() and setElements() does a sort.
    320341         *
    321342         * @param id ID to identify the Comparator stored with @link addSorter()
    322          */
    323         public synchronized void sortBy( String id )
    324         {
     343         * @param direction UP or DOWN. UP is reverse sort.
     344         */
     345        public synchronized void setSortBy(String id, SortOrder direction)
     346        {
     347                sortingDirection = direction;
    325348                currentSorter = sorter.get( id );
    326349                if (currentSorter != null) {
    327350                        if (sortingDirection == SortOrder.UP)
    328351                                currentSorter = Collections.reverseOrder(currentSorter);
    329                                 currentSortID = id;
     352                        currentSortID = id;
    330353                } else {
    331354                        currentSortID = null;
     
    368391****/
    369392
    370         /**
    371          * Sets the sorting direction of the folder.
    372          * Does not re-sort. Caller must call sortBy()
    373          *
    374          * @param direction UP or DOWN
    375          */
    376         public synchronized void setSortingDirection(SortOrder direction)
    377         {
    378                 sortingDirection = direction;
    379         }
    380        
    381393        /**
    382394         * Returns the first element of the sorted folder.
  • apps/susimail/src/src/i2p/susi/webmail/MailCache.java

    rc2a1d79 r0430323  
    9191         * Will not include any marked for deletion.
    9292         *
     93         * @return non-null
    9394         * @since 0.9.13
    9495         */
  • apps/susimail/src/src/i2p/susi/webmail/WebMail.java

    rc2a1d79 r0430323  
    192192        private static final String SORT_SIZE = "size";
    193193        private static final String SORT_DEFAULT = SORT_DATE;
     194        private static final SortOrder SORT_ORDER_DEFAULT = SortOrder.UP;
    194195        // for XSS
    195196        private static final List<String> VALID_SORTS = Arrays.asList(new String[] {
     
    481482                        if (mc != null && f != null) {
    482483                                String[] uidls = mc.getUIDLs();
    483                                 f.setElements(uidls);
     484                                f.addElements(Arrays.asList(uidls));
    484485                        }
    485486                }
     
    562563                StringBuilder buf = new StringBuilder(128);
    563564                buf.append(label).append("&nbsp;&nbsp;");
     565                // UP is reverse sort. DOWN is normal sort.
    564566                if (name.equals(currentName) && currentOrder == SortOrder.UP) {
    565567                        buf.append("<img class=\"sort\" src=\"").append(imgPath).append("3up.png\" border=\"0\" alt=\"^\">\n");
    566568                } else {
    567                         buf.append("<a class=\"sort\" href=\"").append(myself).append("?page=").append(page).append("&amp;sort=").append(name).append("\">");
     569                        buf.append("<a class=\"sort\" href=\"").append(myself).append("?page=").append(page).append("&amp;sort=-").append(name).append("\">");
    568570                        buf.append("<img class=\"sort\" src=\"").append(imgPath).append("3up.png\" border=\"0\" alt=\"^\" style=\"opacity: 0.4;\">");
    569571                        buf.append("</a>\n");
     
    572574                        buf.append("<img class=\"sort\" src=\"").append(imgPath).append("3down.png\" border=\"0\" alt=\"v\">");
    573575                } else {
    574                         buf.append("<a class=\"sort\" href=\"").append(myself).append("?page=").append(page).append("&amp;sort=-").append(name).append("\">");
     576                        buf.append("<a class=\"sort\" href=\"").append(myself).append("?page=").append(page).append("&amp;sort=").append(name).append("\">");
    575577                        buf.append("<img class=\"sort\" src=\"").append(imgPath).append("3down.png\" border=\"0\" alt=\"v\" style=\"opacity: 0.4;\">");
    576578                        buf.append("</a>");
     
    864866                                                if (!offline) {
    865867                                                        // prime the cache, request all headers at once
    866                                                         // otherwise they are pulled one at a time by sortBy() below
     868                                                        // otherwise they are pulled one at a time
     869                                                        // during the sort in folder.setElements() below
    867870                                                        mc.getMail(MailCache.FetchMode.HEADER);
    868871                                                }
    869                                                 // get through cache so we have the disk-only ones too
    870                                                 String[] uidls = mc.getUIDLs();
    871                                                 sessionObject.folder.setElements(uidls);
    872872                                               
     873                                                // setElements() sorts, so configure the sorting first
    873874                                                //sessionObject.folder.addSorter( SORT_ID, new IDSorter( sessionObject.mailCache ) );
    874875                                                sessionObject.folder.addSorter( SORT_SENDER, new SenderSorter( sessionObject.mailCache ) );
     
    877878                                                sessionObject.folder.addSorter( SORT_SIZE, new SizeSorter( sessionObject.mailCache ) );
    878879                                                // reverse sort, latest mail first
    879                                                 sessionObject.folder.setSortingDirection(SortOrder.UP);
    880                                                 sessionObject.folder.sortBy(SORT_DEFAULT);
     880                                                // TODO get user defaults from config
     881                                                sessionObject.folder.setSortBy(SORT_DEFAULT, SORT_ORDER_DEFAULT);
     882                                                // get through cache so we have the disk-only ones too
     883                                                String[] uidls = mc.getUIDLs();
     884                                                sessionObject.folder.setElements(uidls);
     885
    881886                                                sessionObject.reallyDelete = false;
    882887                                                if (offline)
     
    12381243                        String[] uidls = sessionObject.mailCache.getUIDLs();
    12391244                        if (uidls != null)
    1240                                 sessionObject.folder.setElements(uidls);
     1245                                sessionObject.folder.addElements(Arrays.asList(uidls));
    12411246                        sessionObject.pageChanged = true;
    12421247                }
     
    15371542        private static void processSortingButtons(SessionObject sessionObject, RequestWrapper request)
    15381543        {
     1544                // GET param
    15391545                String str = request.getParameter(SORT);
     1546                // POST param
     1547                if (str == null)
     1548                        str = request.getParameter(CURRENT_SORT);
    15401549                if (str != null && VALID_SORTS.contains(str)) {
    15411550                        SortOrder order;
     1551                        // UP is reverse sort. DOWN is normal sort.
    15421552                        if (str.startsWith("-")) {
    1543                                 order = SortOrder.DOWN;
     1553                                order = SortOrder.UP;
    15441554                                str = str.substring(1);
    15451555                        } else {
    1546                                 order = SortOrder.UP;
    1547                         }
    1548                         // TODO don't store in session
    1549                         sessionObject.folder.setSortingDirection(order);
    1550                         sessionObject.folder.sortBy(str);
     1556                                order = SortOrder.DOWN;
     1557                        }
     1558                        // Store in session. processRequest() will re-sort if necessary.
     1559                        sessionObject.folder.setSortBy(str, order);
    15511560                }
    15521561        }
     
    18011810                                        }
    18021811                                }
    1803                                 // sort buttons are GETs
    1804                                 processSortingButtons( sessionObject, request );
    1805                                 for( Iterator<String> it = sessionObject.folder.currentPageIterator(); it != null && it.hasNext(); ) {
    1806                                         String uidl = it.next();
    1807                                         Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FetchMode.HEADER );
    1808                                         if( mail != null && mail.error.length() > 0 ) {
    1809                                                 sessionObject.error += mail.error;
    1810                                                 mail.error = "";
    1811                                         }
    1812                                 }
    18131812                        }
    18141813                       
     
    18671866                        /*
    18681867                         * update folder content
     1868                         * We need a valid and sorted folder for SHOW also, for the previous/next buttons
    18691869                         */
    18701870                        Folder<String> folder = sessionObject.folder;
    1871                         if( state == State.LIST ) {
     1871                        if (state == State.LIST || state == State.SHOW) {
     1872                                // sort buttons are GETs
     1873                                String oldSort = folder.getCurrentSortBy();
     1874                                SortOrder oldOrder = folder.getCurrentSortingDirection();
     1875                                processSortingButtons( sessionObject, request );
     1876                                if (state == State.LIST) {
     1877                                        for (Iterator<String> it = sessionObject.folder.currentPageIterator(); it != null && it.hasNext(); ) {
     1878                                                String uidl = it.next();
     1879                                                Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FetchMode.HEADER );
     1880                                                if( mail != null && mail.error.length() > 0 ) {
     1881                                                        sessionObject.error += mail.error;
     1882                                                        mail.error = "";
     1883                                                }
     1884                                        }
     1885                                }
     1886
    18721887                                // get through cache so we have the disk-only ones too
    18731888                                String[] uidls = sessionObject.mailCache.getUIDLs();
    1874                                 if (uidls != null) {
    1875                                         // TODO why every time?
    1876                                         folder.setElements(uidls);
     1889                                if (folder.addElements(Arrays.asList(uidls))) {
     1890                                        // we added elements, so it got sorted
     1891                                } else {
     1892                                        // check for changed sort
     1893                                        String curSort = folder.getCurrentSortBy();
     1894                                        SortOrder curOrder = folder.getCurrentSortingDirection();
     1895                                        if (oldOrder != curOrder || !oldSort.equals(curSort))
     1896                                                folder.sort();
    18771897                                }
    18781898                        }
     
    19641984                                                out.println("<input type=\"hidden\" name=\"" + CUR_PAGE + "\" value=\"" + page + "\">");
    19651985                                        }
     1986                                }
     1987                                if (state == State.SHOW || state == State.NEW || state == State.LIST) {
    19661988                                        // Save sort order in case it changes later
    19671989                                        String curSort = folder.getCurrentSortBy();
    19681990                                        SortOrder curOrder = folder.getCurrentSortingDirection();
    1969                                         String fullSort = curOrder == SortOrder.DOWN ? '-' + curSort : curSort;
     1991                                        // UP is reverse sort. DOWN is normal sort.
     1992                                        String fullSort = curOrder == SortOrder.UP ? '-' + curSort : curSort;
    19701993                                        out.println("<input type=\"hidden\" name=\"" + CURRENT_SORT + "\" value=\"" + fullSort + "\">");
    19711994                                }
     
    19972020                                out.println( "</form><div class=\"footer\"><p class=\"footer\">susimail &copy; 2004-2005 susi</p></div></div></body>\n</html>");
    19982021                                out.flush();
    1999                 }
     2022                }  // synch sessionObject
    20002023        }
    20012024
     
    24502473                out.println("</div>");
    24512474
    2452 
    2453                 SortOrder curOrder;
    2454                 String curSort = request.getParameter(SORT);
    2455                 String fullSort;
    2456                 if (curSort == null)
    2457                         curSort = request.getParameter(CURRENT_SORT);
    2458                 if (curSort != null && VALID_SORTS.contains(curSort)) {
    2459                         fullSort = curSort;
    2460                         if (curSort.startsWith("-")) {
    2461                                 curSort = curSort.substring(1);
    2462                                 curOrder = SortOrder.DOWN;
    2463                         } else {
    2464                                 curOrder = SortOrder.UP;
    2465                         }
    2466                         // TODO don't store in session
    2467                         if (curOrder != folder.getCurrentSortingDirection() || !curSort.equals(folder.getCurrentSortBy())) {
    2468                             folder.setSortingDirection(curOrder);
    2469                             folder.sortBy(curSort);
    2470                         }
    2471                 } else {
    2472                         curSort = folder.getCurrentSortBy();
    2473                         curOrder = folder.getCurrentSortingDirection();
    2474                         fullSort = curOrder == SortOrder.DOWN ? '-' + curSort : curSort;
    2475                 }
    2476                 out.println("<input type=\"hidden\" name=\"" + CURRENT_SORT + "\" value=\"" + fullSort + "\">");
    2477                 if (curSort.startsWith("-"))
    2478                         curSort = curSort.substring(1);
     2475                String curSort = folder.getCurrentSortBy();
     2476                SortOrder curOrder = folder.getCurrentSortingDirection();
    24792477                out.println("<table id=\"mailbox\" cellspacing=\"0\" cellpadding=\"5\">\n" +
    24802478                        "<tr><td colspan=\"9\"><hr></td></tr>\n<tr><th title=\"" + _t("Mark for deletion") + "\">&nbsp;</th>" +
Note: See TracChangeset for help on using the changeset viewer.