From 7beacff0281aeef1b46b69d4bd61dbbfb4117aa1 Mon Sep 17 00:00:00 2001 From: jrandom Date: Thu, 8 Dec 2005 00:50:32 +0000 Subject: [PATCH] 2005-12-07 jrandom * Added a first pass at a blog view in Syndie --- .../syndie/NewestEntryFirstComparator.java | 20 ++++ .../i2p/syndie/NewestNodeFirstComparator.java | 30 ++++++ .../src/net/i2p/syndie/ThreadNodeImpl.java | 2 +- .../net/i2p/syndie/WritableThreadIndex.java | 40 -------- .../i2p/syndie/data/FilteredThreadIndex.java | 22 +++-- .../i2p/syndie/sml/ThreadedHTMLRenderer.java | 31 ++++-- .../src/net/i2p/syndie/web/BaseServlet.java | 37 ++++++-- .../net/i2p/syndie/web/ProfileServlet.java | 14 ++- .../src/net/i2p/syndie/web/RSSServlet.java | 2 +- .../net/i2p/syndie/web/ViewBlogsServlet.java | 95 +++++++++++++++++++ .../i2p/syndie/web/ViewThreadedServlet.java | 4 +- apps/syndie/jsp/web.xml | 9 ++ history.txt | 5 +- 13 files changed, 239 insertions(+), 72 deletions(-) create mode 100644 apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java create mode 100644 apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java create mode 100644 apps/syndie/java/src/net/i2p/syndie/web/ViewBlogsServlet.java diff --git a/apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java b/apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java new file mode 100644 index 000000000..21304ef7a --- /dev/null +++ b/apps/syndie/java/src/net/i2p/syndie/NewestEntryFirstComparator.java @@ -0,0 +1,20 @@ +package net.i2p.syndie; + +import java.util.*; +import net.i2p.data.*; +import net.i2p.syndie.data.*; + +/** sort BlogURI instances with the highest entryId first */ +public class NewestEntryFirstComparator implements Comparator { + public int compare(Object lhs, Object rhs) { + BlogURI left = (BlogURI)lhs; + BlogURI right = (BlogURI)rhs; + if (left.getEntryId() > right.getEntryId()) { + return -1; + } else if (left.getEntryId() == right.getEntryId()) { + return DataHelper.compareTo(left.getKeyHash().getData(), right.getKeyHash().getData()); + } else { + return 1; + } + } +} diff --git a/apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java b/apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java new file mode 100644 index 000000000..6046bf0c7 --- /dev/null +++ b/apps/syndie/java/src/net/i2p/syndie/NewestNodeFirstComparator.java @@ -0,0 +1,30 @@ +package net.i2p.syndie; + +import java.util.*; +import net.i2p.data.*; + +/** sort ThreadNodeImpl instances with the highest entryId first */ +public class NewestNodeFirstComparator implements Comparator { + public int compare(Object lhs, Object rhs) { + ThreadNodeImpl left = (ThreadNodeImpl)lhs; + ThreadNodeImpl right = (ThreadNodeImpl)rhs; + long l = left.getMostRecentPostDate(); + long r = right.getMostRecentPostDate(); + if (l > r) { + return -1; + } else if (l == r) { + // ok, the newest responses match, so lets fall back and compare the roots themselves + l = left.getEntry().getEntryId(); + r = right.getEntry().getEntryId(); + if (l > r) { + return -1; + } else if (l == r) { + return DataHelper.compareTo(left.getEntry().getKeyHash().getData(), right.getEntry().getKeyHash().getData()); + } else { + return 1; + } + } else { + return 1; + } + } +} diff --git a/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java b/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java index 891d1f5b6..406ca10e4 100644 --- a/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java +++ b/apps/syndie/java/src/net/i2p/syndie/ThreadNodeImpl.java @@ -80,7 +80,7 @@ class ThreadNodeImpl implements ThreadNode { } // now reorder the children - TreeSet ordered = new TreeSet(new WritableThreadIndex.NewestNodeFirstComparator()); + TreeSet ordered = new TreeSet(new NewestNodeFirstComparator()); for (int i = 0; i < _children.size(); i++) { ThreadNodeImpl kid = (ThreadNodeImpl)_children.get(i); ordered.add(kid); diff --git a/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java b/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java index 224e03710..06ffc8e35 100644 --- a/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java +++ b/apps/syndie/java/src/net/i2p/syndie/WritableThreadIndex.java @@ -136,44 +136,4 @@ class WritableThreadIndex extends ThreadIndex { buf.append("\n"); return buf.toString(); } - - /** sort BlogURI instances with the highest entryId first */ - private class NewestEntryFirstComparator implements Comparator { - public int compare(Object lhs, Object rhs) { - BlogURI left = (BlogURI)lhs; - BlogURI right = (BlogURI)rhs; - if (left.getEntryId() > right.getEntryId()) { - return -1; - } else if (left.getEntryId() == right.getEntryId()) { - return DataHelper.compareTo(left.getKeyHash().getData(), right.getKeyHash().getData()); - } else { - return 1; - } - } - } - /** sort ThreadNodeImpl instances with the highest entryId first */ - public static class NewestNodeFirstComparator implements Comparator { - public int compare(Object lhs, Object rhs) { - ThreadNodeImpl left = (ThreadNodeImpl)lhs; - ThreadNodeImpl right = (ThreadNodeImpl)rhs; - long l = left.getMostRecentPostDate(); - long r = right.getMostRecentPostDate(); - if (l > r) { - return -1; - } else if (l == r) { - // ok, the newest responses match, so lets fall back and compare the roots themselves - l = left.getEntry().getEntryId(); - r = right.getEntry().getEntryId(); - if (l > r) { - return -1; - } else if (l == r) { - return DataHelper.compareTo(left.getEntry().getKeyHash().getData(), right.getEntry().getKeyHash().getData()); - } else { - return 1; - } - } else { - return 1; - } - } - } } diff --git a/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java b/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java index fb9dde971..eeaa9ee80 100644 --- a/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java +++ b/apps/syndie/java/src/net/i2p/syndie/data/FilteredThreadIndex.java @@ -16,11 +16,12 @@ public class FilteredThreadIndex extends ThreadIndex { private List _roots; private List _ignoredAuthors; private Collection _filteredAuthors; + private boolean _filterAuthorsByRoot; public static final String GROUP_FAVORITE = "Favorite"; public static final String GROUP_IGNORE = "Ignore"; - public FilteredThreadIndex(User user, Archive archive, Collection tags, Collection authors) { + public FilteredThreadIndex(User user, Archive archive, Collection tags, Collection authors, boolean filterAuthorsByRoot) { super(); _user = user; _archive = archive; @@ -31,6 +32,7 @@ public class FilteredThreadIndex extends ThreadIndex { _filteredAuthors = authors; if (_filteredAuthors == null) _filteredAuthors = Collections.EMPTY_SET; + _filterAuthorsByRoot = filterAuthorsByRoot; _ignoredAuthors = new ArrayList(); for (Iterator iter = user.getPetNameDB().iterator(); iter.hasNext(); ) { @@ -53,12 +55,12 @@ public class FilteredThreadIndex extends ThreadIndex { _roots = new ArrayList(_baseIndex.getRootCount()); for (int i = 0; i < _baseIndex.getRootCount(); i++) { ThreadNode node = _baseIndex.getRoot(i); - if (!isIgnored(node, _ignoredAuthors, _filteredTags, _filteredAuthors)) + if (!isIgnored(node, _ignoredAuthors, _filteredTags, _filteredAuthors, _filterAuthorsByRoot)) _roots.add(node); } } - private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors) { + private boolean isIgnored(ThreadNode node, List ignoredAuthors, Collection requestedTags, Collection filteredAuthors, boolean filterAuthorsByRoot) { if (filteredAuthors.size() <= 0) { boolean allAuthorsIgnored = true; for (Iterator iter = node.getRecursiveAuthorIterator(); iter.hasNext(); ) { @@ -75,9 +77,16 @@ public class FilteredThreadIndex extends ThreadIndex { boolean filteredAuthorMatches = false; for (Iterator iter = filteredAuthors.iterator(); iter.hasNext(); ) { Hash author = (Hash)iter.next(); - if (node.containsAuthor(author)) { - filteredAuthorMatches = true; - break; + if (filterAuthorsByRoot) { + if (node.getEntry().getKeyHash().equals(author)) { + filteredAuthorMatches = true; + break; + } + } else { + if (node.containsAuthor(author)) { + filteredAuthorMatches = true; + break; + } } } if (!filteredAuthorMatches) @@ -107,4 +116,5 @@ public class FilteredThreadIndex extends ThreadIndex { public ThreadNode getNode(BlogURI uri) { return _baseIndex.getNode(uri); } public Collection getFilteredTags() { return _filteredTags; } public Collection getFilteredAuthors() { return _filteredAuthors; } + public boolean getFilterAuthorsByRoot() { return _filterAuthorsByRoot; } } diff --git a/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java b/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java index ad21c196b..f981214ea 100644 --- a/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java +++ b/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java @@ -41,7 +41,10 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { /** index into the nav tree to start displaying */ public static final String PARAM_OFFSET = "offset"; public static final String PARAM_TAGS = "tags"; + /** only show threads that the given author participates in */ public static final String PARAM_AUTHOR = "author"; + /** only show threads started by the given author */ + public static final String PARAM_THREAD_AUTHOR = "threadAuthorOnly"; /** search back through the blog for entries this many days */ public static final String PARAM_DAYS_BACK = "daysBack"; // parameters for editing one's profile @@ -94,7 +97,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { return buf.toString(); } - public static String getNavLink(String uri, String viewPost, String viewThread, String tags, String author, int offset) { + public static String getNavLink(String uri, String viewPost, String viewThread, String tags, String author, boolean authorOnly, int offset) { StringBuffer buf = new StringBuffer(64); buf.append(uri); buf.append('?'); @@ -106,8 +109,11 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { if (!empty(tags)) buf.append(PARAM_TAGS).append('=').append(tags).append('&'); - if (!empty(author)) + if (!empty(author)) { buf.append(PARAM_AUTHOR).append('=').append(author).append('&'); + if (authorOnly) + buf.append(PARAM_THREAD_AUTHOR).append("=true&"); + } buf.append(PARAM_OFFSET).append('=').append(offset).append('&'); @@ -115,7 +121,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { } public static String getViewPostLink(String uri, ThreadNode node, User user, boolean isPermalink, - String offset, String tags, String author) { + String offset, String tags, String author, boolean authorOnly) { StringBuffer buf = new StringBuffer(64); buf.append(uri); if (node.getChildCount() > 0) { @@ -137,15 +143,19 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { buf.append(PARAM_OFFSET).append('=').append(offset).append('&'); if (!empty(tags)) buf.append(PARAM_TAGS).append('=').append(tags).append('&'); - if (!empty(author)) - buf.append(PARAM_AUTHOR).append('=').append(author).append('&'); } + if (authorOnly && !empty(author)) { + buf.append(PARAM_AUTHOR).append('=').append(author).append('&'); + buf.append(PARAM_THREAD_AUTHOR).append("=true&"); + } else if (!isPermalink && !empty(author)) + buf.append(PARAM_AUTHOR).append('=').append(author).append('&'); + return buf.toString(); } public static String getViewPostLink(String uri, BlogURI post, User user, boolean isPermalink, - String offset, String tags, String author) { + String offset, String tags, String author, boolean authorOnly) { StringBuffer buf = new StringBuffer(64); buf.append(uri); buf.append('?').append(PARAM_VISIBLE).append('='); @@ -160,8 +170,11 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { buf.append(PARAM_OFFSET).append('=').append(offset).append('&'); if (!empty(tags)) buf.append(PARAM_TAGS).append('=').append(tags).append('&'); - if (!empty(author)) + if (!empty(author)) { buf.append(PARAM_AUTHOR).append('=').append(author).append('&'); + if (authorOnly) + buf.append(PARAM_THREAD_AUTHOR).append("=true&"); + } } return buf.toString(); @@ -174,7 +187,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { */ public void render(User user, Writer out, Archive archive, BlogURI post, boolean inlineReply, ThreadIndex index, String baseURI, String replyHiddenFields, - String offset, String requestTags, String filteredAuthor) throws IOException { + String offset, String requestTags, String filteredAuthor, boolean authorOnly) throws IOException { EntryContainer entry = archive.getEntry(post); if (entry == null) return; _entry = entry; @@ -255,7 +268,7 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { } out.write("\npermalink\n"); diff --git a/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java index 8c5c80991..65e7e078e 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java @@ -152,12 +152,20 @@ public abstract class BaseServlet extends HttpServlet { FilteredThreadIndex index = (FilteredThreadIndex)req.getSession().getAttribute("threadIndex"); + boolean authorOnly = Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue(); + if ( (index != null) && (authorOnly != index.getFilterAuthorsByRoot()) ) + forceNewIndex = true; + Collection tags = getFilteredTags(req); Collection filteredAuthors = getFilteredAuthors(req); boolean tagsChanged = ( (index != null) && (!index.getFilteredTags().equals(tags)) ); boolean authorsChanged = ( (index != null) && (!index.getFilteredAuthors().equals(filteredAuthors)) ); + + if (_log.shouldLog(Log.DEBUG)) + _log.debug("authorOnly=" + authorOnly + " forceNewIndex? " + forceNewIndex + " authors=" + filteredAuthors); + if (forceNewIndex || (index == null) || (tagsChanged) || (authorsChanged) ) { - index = new FilteredThreadIndex(user, BlogManager.instance().getArchive(), getFilteredTags(req), filteredAuthors); + index = new FilteredThreadIndex(user, BlogManager.instance().getArchive(), getFilteredTags(req), filteredAuthors, authorOnly); req.getSession().setAttribute("threadIndex", index); if (_log.shouldLog(Log.INFO)) _log.info("New filtered index created (forced? " + forceNewIndex + ", tagsChanged? " + tagsChanged + ", authorsChanged? " + authorsChanged + ")"); @@ -561,7 +569,7 @@ public abstract class BaseServlet extends HttpServlet { //out.write("\n"); out.write("\n"); out.write("\n"); - out.write("Home "); + out.write("Home Blogs "); if (user.getAuthenticated() && (user.getBlog() != null) ) { out.write("Logged in as "); out.write(user.getUsername()); @@ -933,22 +941,25 @@ public abstract class BaseServlet extends HttpServlet { return ThreadedHTMLRenderer.getViewPostLink(req.getRequestURI(), node, user, isPermalink, req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET), req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS), - req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR)); + req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR), + Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue()); } protected String getViewPostLink(HttpServletRequest req, BlogURI post, User user) { return ThreadedHTMLRenderer.getViewPostLink(req.getRequestURI(), post, user, false, req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET), req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS), - req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR)); + req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR), + Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue()); } protected String getViewThreadLink(HttpServletRequest req, ThreadNode node, User user) { return getViewThreadLink(req.getRequestURI(), node, user, req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET), req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS), - req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR)); + req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR), + Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue()); } protected static String getViewThreadLink(String uri, ThreadNode node, User user, String offset, - String tags, String author) { + String tags, String author, boolean authorOnly) { StringBuffer buf = new StringBuffer(64); buf.append(uri); BlogURI expandTo = node.getEntry(); @@ -975,8 +986,11 @@ public abstract class BaseServlet extends HttpServlet { if (!empty(tags)) buf.append(ThreadedHTMLRenderer.PARAM_TAGS).append('=').append(tags).append('&'); - if (!empty(author)) + if (!empty(author)) { buf.append(ThreadedHTMLRenderer.PARAM_AUTHOR).append('=').append(author).append('&'); + if (authorOnly) + buf.append(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR).append("=true&"); + } buf.append("#").append(node.getEntry().toString()); return buf.toString(); @@ -990,6 +1004,7 @@ public abstract class BaseServlet extends HttpServlet { req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_THREAD), req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS), req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR), + Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue(), offset); } @@ -1014,7 +1029,13 @@ public abstract class BaseServlet extends HttpServlet { } protected Collection getFilteredAuthors(HttpServletRequest req) { - String authors = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR); + List rv = new ArrayList(); + rv.addAll(getAuthors(req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR))); + //rv.addAll(getAuthors(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR))); + return rv; + } + + private Collection getAuthors(String authors) { if (authors != null) { StringTokenizer tok = new StringTokenizer(authors, "\n\t "); ArrayList rv = new ArrayList(); diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java index 0432298d3..2e82b6fb7 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/ProfileServlet.java @@ -103,14 +103,13 @@ public class ProfileServlet extends BaseServlet { } private void renderProfile(User user, String baseURI, PrintWriter out, Hash author, Archive archive) throws IOException { - out.write("Profile for View their blog or "); + out.write("= dayBegin) { + age = "today"; + } else if (postId >= dayBegin - 24*60*60*1000) { + age = "yesterday"; + } else { + int daysAgo = (int)((dayBegin - postId + 24*60*60*1000-1)/(24*60*60*1000)); + age = daysAgo + " days ago"; + } + + out.write(""); + out.write(HTMLRenderer.sanitizeString(tag, 32)); + out.write(" "); + } + out.write("\n"); + } + + protected String getTitle() { return "Syndie :: View blogs"; } +} diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java index ce6c3c86d..23b4ea0d2 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java @@ -36,13 +36,15 @@ public class ViewThreadedServlet extends BaseServlet { String off = req.getParameter(ThreadedHTMLRenderer.PARAM_OFFSET); String tags = req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS); String author = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR); + + boolean authorOnly = Boolean.valueOf(req.getParameter(ThreadedHTMLRenderer.PARAM_THREAD_AUTHOR)).booleanValue(); for (int i = 0; i < posts.size(); i++) { BlogURI post = (BlogURI)posts.get(i); boolean inlineReply = (posts.size() == 1); //if (true) // inlineReply = true; - renderer.render(user, out, archive, post, inlineReply, index, uri, getAuthActionFields(), off, tags, author); + renderer.render(user, out, archive, post, inlineReply, index, uri, getAuthActionFields(), off, tags, author, authorOnly); } } diff --git a/apps/syndie/jsp/web.xml b/apps/syndie/jsp/web.xml index d4d7ea68e..6a57e60a3 100644 --- a/apps/syndie/jsp/web.xml +++ b/apps/syndie/jsp/web.xml @@ -64,6 +64,11 @@ net.i2p.syndie.web.ThreadNavServlet + + net.i2p.syndie.web.ViewBlogsServlet + net.i2p.syndie.web.ViewBlogsServlet + + net.i2p.syndie.UpdaterServlet net.i2p.syndie.UpdaterServlet @@ -126,6 +131,10 @@ net.i2p.syndie.web.ThreadNavServlet /threadnav/* + + net.i2p.syndie.web.ViewBlogsServlet + /blogs.jsp + diff --git a/history.txt b/history.txt index 4225774f7..22ea816ad 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,7 @@ -$Id: history.txt,v 1.348 2005/12/05 01:14:16 jrandom Exp $ +$Id: history.txt,v 1.349 2005/12/07 15:19:43 jrandom Exp $ + +2005-12-07 jrandom + * Added a first pass at a blog view in Syndie 2005-12-07 jrandom * Expand the thread we're viewing to its leaf