Thursday, March 31, 2011 at 1:05 AM.

river2Suite.viewNews

on viewNews (adrcal=nil, flnotmobile=true) {
	<<Changes
		<<3/29/11; 5:40:49 PM by DW
			<<Respect the users' preference for max items on the home page.
		<<3/27/11; 12:21:24 PM by DW
			<<Pass adrdata^.prefs.maxDaysNews to mainresponder.calendar.visitReverseChronologic to limit the number of days we're willing to go back in time.
		<<10/1/10; 6:41:57 PM by DW
			<<If the title and description are identical, don't show the description. This is the case for Twitter feeds.
		<<5/20/10; 8:09:46 AM by DW
			<<If the title of an item ends with ? or ! don't add a period after it.
		<<3/24/10; 9:48:29 AM by DW
			<<If we're generating a static version of the page and Instapaper is enabled, use the URL on the Instapaper site instead of the URL into the River2 (local) site. This works pretty well. The user is prompted to enter his or her username and password before the link is added to IP. It would also be nice if IP took a parameter that told it what URL to redirect back to, that way we could include a #name and it would return you back to the item you were looking at in the river. 
		<<3/21/10; 10:14:52 AM by DW
			<<Instapaper support. Also every item now has a name anchor so it's possible to redirect back to a specific item.
		<<3/18/10; 11:42:39 AM by DW
			<<Allow for static builds of news page.
		<<1/2/10; 6:43:54 AM by DW
			<<Put the body of the additem routine in a try statement so if there's an error it doesn't kill the rendering. It's always "permalink undefined" and is caused by a partially read item. It usually clears because the item is in the process of being read. Probably need a semaphore here, and this will make debugging harder.
		<<12/30/09; 11:57:43 AM by DW
			<<Add the tweetbox at the top of the page, if enabled.
		<<12/26/09; 11:31:41 AM by DW
			<<New optional parameter, flnotmobile -- if false, we render a truly bare-bones river suitable for an iPhone or Droid.
		<<12/26/09; 11:22:17 AM by DW
			<<Comment Share button at the bottom of the page.
		<<12/21/09; 4:25:25 AM by DW
			<<Get the announcement from its new location.
		<<12/2/09; 10:08:51 AM by DW
			<<If pta^.adruser is non-nil, only show the feeds that the user is subscribed to.
		<<12/1/09; 4:33:25 PM by DW
			<<Call twitter.hotupText after stripping markup, as first step toward making River2 friendly for viewing Twitter feeds.
		<<9/16/09; 9:06:08 AM by DW
			<<If we're accessing the river over the web (i.e. not on the same machine) don't use the folder icon to link to enclosures.
		<<9/15/09; 10:12:04 AM by DW
			<<Don't display items from feeds that have been unsubbed.
		<<9/15/09; 8:15:07 AM by DW
			<<New flag, flhomepage, if true we don't display podcasts and photos, per the prefs.
		<<9/9/09; 11:48:32 AM by DW
			<<Include the current announcement in the caption.
		<<9/9/09; 11:44:33 AM by DW
			<<Eliminate the word "Pacific."
		<<9/8/09; 1:34:06 PM by DW
			<<Say "Enclosure downloaded" instead of "Podcast downloaded" so it works equally well for pictures. Define local, flcache, makes testing easier, by recalcing the text of each item each time its displayed. 
		<<9/8/09; 7:18:04 AM by DW
			<<Display a thumbnail for items, if present.
		<<9/5/09; 5:53:46 PM by DW
			<<Factored code for displaying the link to feed contents.
		<<8/28/09; 11:14:03 AM by DW
			<<Include download info for podcasts. (When downloaded, and the size of the file.)
		<<8/20/09; 10:33:49 AM by DW
			<<Add optional param, adrcal, the address of a calendar structure. If nil we display the main river.
		<<8/17/09; 6:10:19 AM by DW
			<<If we've unsubbed from the feed don't display the item.
		<<7/17/09; 6:34:16 PM by DW
			<<Handle the case where an item's title is empty.
		<<6/17/09; 8:28:48 AM by DW
			<<Created. 
	local (pta = html.getpagetableaddress (), adrdata = river2suite.init (), startticks = clock.ticks (), flnotstaticbuild = true, maxitems);
	local (htmltext = "", indentlevel = 0, lastfeedurl = "", ct = 0, errorstring = "", flcache = true, fixedavatarwidth = 48);
	on add (s) {
		htmltext = htmltext + string.filledstring ("\t", indentlevel) + s + "\r"};
	bundle { //set maxitems, 3/29/11 by DW
		maxitems = adrdata^.prefs.maxItemsHomePage;
		if pta^.adruser != nil {
			if pta^.adruser^.prefs.maxRiverItems < maxitems {
				maxitems = pta^.adruser^.prefs.maxRiverItems}}};
	if pta^.method == "POST" {
		local (args, adr, i);
		new (tabletype, @args);
		webserver.parseargs (pta^.requestbody, @args);
		<<scratchpad.args = args; edit (@scratchpad.args)
		if defined (args.deleteButton) {
			try {
				local (ct = 0);
				on visit (adritem) {
					local (name = nameof (adritem^));
					if defined (args.["checkbox" + name]) {
						adrdata^.trash.[name] = adritem^;
						delete (adritem)};
					return (++ct <= maxitems)};
				mainresponder.calendar.visitReverseChronologic (@adrdata^.river, @visit)}
			else {
				errorstring = tryerror}};
		if defined (args.shareButton) {
			errorstring = "Sorry man, it's not implemented yet. Still diggin! :-)"};
		if defined (args.tweetButton) { //12/29/09 by DW
			river2Suite.myRss.newTweet (args.tweetText);
			river2Suite.myRss.buildRss ()}};
	if defined (pta^.river2.flStaticBuild) { //3/18/10 by DW, set flnotstaticbuild
		flnotstaticbuild = not pta^.river2.flStaticBuild};
	local (imgLinkToWebsite = river2Suite.loadImage ("linkToWebsite.gif", pta));
	local (imgXml = river2Suite.loadImage ("linkToFeed.gif", pta));
	local (imgXmlMini = river2Suite.loadImage ("xmlMini.gif", pta));
	local (imgComments = river2Suite.loadImage ("linkToComments.gif", pta));
	local (imgMp3 = river2Suite.loadImage ("linkToMp3.gif", pta));
	local (imgFolder = river2Suite.loadImage ("folder.gif", pta)); //9/1/09 by DW
	local (imgVideo = river2Suite.loadImage ("linkToVideo.gif", pta));
	local (imgEnclosure = river2Suite.loadImage ("linkToEnclosure.gif", pta));
	local (imgButtonBg = river2Suite.loadImage ("buttonBackground.gif", pta));
	local (imgTwitter = river2Suite.loadImage ("twitter.gif", pta));
	local (imgInstapaper = river2Suite.loadImage ("instapaper.gif", pta)); //3/21/10 by DW
	<<local (imgFeedContents = river2Suite.loadImage ("linkToFeedContents.gif", pta))
	<<local (imgTitle = river2Suite.loadImage ("title.gif", pta))
	scratchpad.viewNewsParams = pta^; //debugging
	
	bundle { //add the tweetbox at the top of the page, 12/29/09 by DW
		if defined (adrdata^.myRss.prefs.enabled) {
			if adrdata^.myRss.prefs.enabled {
				local (s, t);
				new (tabletype, @t);
				t.lastTweetByThisUser = "";
				t.initialText = "";
				t.ctChars = sizeof (t.initialText);
				t.prompt = "What song are you singing?";
				bundle { //set xmlIcon
					if adrdata^.myRss.stats.rssUrl != "" {
						t.xmlIcon = "<a href=\"" + adrdata^.myRss.stats.rssUrl + "\">" + imgXmlMini + "</a>"}
					else {
						t.xmlIcon = ""}};
				s = string.multiplereplaceall (string (river2Suite.data.html.tweetBox), @t, false, "<%", "%>");
				add (s)}}};
	
	on visit (adritem) {
		if typeof (adritem^) != tabletype {
			local (name = nameof (adritem^));
			local (adrday = mainresponder.calendar.getdayaddress (@adrdata^.river, adritem^));
			adritem = @adrday^.[name]};
		bundle { //check type and flags, possibly return, 9/9/09 by DW
			if defined (adritem^.type) {
				if flhomepage { //9/15/09 by DW
					if not adrdata^.prefs.flPodcastsOnHomePage {
						if adritem^.type.flPodcast {
							return (true)}};
					if not adrdata^.prefs.flPhotosOnHomePage {
						if adritem^.type.flPhoto {
							return (true)}}}}};
		bundle { //don't display items from feeds that have been unsubbed, 9/15/09 by DW
			if not defined (adrdata^.feeds.[adritem^.feedurl]) { //9/15/09 by DW
				return (true)}};
		bundle { //display the item in a try, 1/2/10 by DW
			try {
				local (title = adritem^.title, feedurl = adritem^.feedurl, link, flTitleEndsWithPunc);
				local (flduplicatedescription = title == adritem^.description); //10/1/10 by DW
				bundle { //set flTitleEndsWithPunc, 5/20/10 by DW
					local (s = string.trimwhitespace (title), x = sizeof (s));
					if x > 0 {
						local (ch = s [x]);
						flTitleEndsWithPunc = (ch == '!') or (ch == '?')}
					else {
						flTitleEndsWithPunc = false}};
				local (itemnum = number (nameof (adritem^)), itemname = "item" + itemnum);
				local (namelink = "<a name=\"" + itemname + "\"></a>");
				if pta^.adruser != nil { //12/2/09 by DW
					if not river2suite.userfollows (pta^.adruser, feedurl) { //3/27/11 by DW
						return (true)}};
					<<if not defined (pta^.adruser^.feeds.[feedurl]) //user isn't following this feed
						<<return (true)
				local (adrfeed = @adrdata^.feeds.[feedurl]);
				if not defined (adrfeed^) { //8/17/09 by DW -- feed has been deleted
					return (true)};
				bundle { //if feedurl changed, add a row that has the feed's name
					if feedurl != lastfeedurl {
						local (adrfeedinfo = @adrfeed^.feedinfo);
						local (pubname = adrfeedinfo^.title, when);
						<<local (urlfeedpage = "feed?url=" + string.urlencode (feedurl))
						if flnotmobile {
							add ("<tr>"); indentlevel++;
							add ("<td class=\"feedname\"> </td>")};
						bundle { //set when
							<<when = adrfeed^.stats.whenLastNewItem //old way
							when = timeCreated (adritem)};
						if flnotmobile {
							add ("<td class=\"feedname\"><a href=\"" + adrfeedinfo^.link + "\">" + imgLinkToWebsite + "</a> <b>" + pubname + "; " +  when + ". " + river2Suite.linkToFeedContents (feedurl) + "</b></td>")}
						else {
							add ("<p><br /><b>" + pubname + "; " +  when + "</b></p>")};
						if flnotmobile {
							add ("<td class=\"feedname\"><a href=\"" + feedurl + "\">" + imgXml + "</a></td>");
							add ("</tr>"); indentlevel--};
						lastfeedurl = feedurl}};
				bundle { //set link
					<<msg (title)
					link = adritem^.permalink;
					if sizeof (link) == 0 {
						link = adritem^.link};
					if sizeof (title) == 0 { //7/17/09 by DW
						link = ""}
					else {
						if sizeof (link) == 0 {
							link = twitter.hotuptext (title)} //12/2/09 by DW, used to just be "title"
						else {
							link = "<a href=\"" + link + "\">" + title + "</a>"}}};
				bundle { //set adritem^.body, if necessary
					if (not defined (adritem^.body)) or (not flcache) {
						if flduplicatedescription { //10/1/10 by DW
							adritem^.body = ""}
						else {
							adritem^.body = searchengine.stripmarkup (adritem^.description)};
						if sizeof (adritem^.body) > adrdata^.prefs.maxBodyLength {
							adritem^.body = string.mid (adritem^.body, 1, adrdata^.prefs.maxBodyLength);
							while adritem^.body [sizeof (adritem^.body)] != " " {
								adritem^.body = string.delete (adritem^.body, sizeof (adritem^.body), 1)};
							adritem^.body = string.delete (adritem^.body, sizeof (adritem^.body), 1);
							adritem^.body = adritem^.body + "..."};
						if defined (adritem^.thumbnail) { //9/7/09 by DW
							local (img = "<img src=\"" + adritem^.thumbnail.url + "\" height=\"" + adritem^.thumbnail.height + "\" width=\"" + adritem^.thumbnail.width + "\" border=\"0\">");
							if sizeof (adritem^.link) > 0 {
								img = "<a href=\"" + adritem^.link + "\">" + img + "</a>"};
							adritem^.body = adritem^.body + "<p>" + img + "</p>"}}};
				if flnotmobile {
					add ("<tr>"); indentlevel++};
				bundle { //add checkbox
					if flnotmobile {
						local (cb = "<input type=\"checkbox\" name=\"checkbox" + nameof (adritem^) + "\" value=xxx >");
						local (img = "");
						<<if defined (adrfeed^.feedinfo.image)
							<<try
								<<local (h = adrfeed^.feedinfo.image.height, w = adrfeed^.feedinfo.image.width)
								<<if h == w
									<<if (h != 0) and (w != 0)
										<<local (ratio =  double (fixedavatarwidth) / double (h))
										<<h = number (ratio * h)
										<<w = fixedavatarwidth
										<<img = "<p><img src=\"" + adrfeed^.feedinfo.image.url + "\" width=\"" + w + "\" height=\"" + h + "\"></p>"
						if flnotstaticbuild {
							add ("<td class=\"newsCheckbox\" valign=\"top\">" + cb + img + "</td>")}
						else {
							add ("<td class=\"newsCheckbox\" valign=\"top\">   </td>")}}};
				bundle { //add body
					if flnotmobile {
						local (downloadinfo = "");
						try { //8/28/09 by DW
							if defined (adritem^.podcast) {
								if defined (adritem^.podcast.whenDownloadBegan) {
									local (when = adritem^.podcast.whenDownloadBegan);
									downloadinfo = "<p><i>Enclosure downloaded on " + date.shortstring (when) + " at " + date.timestring (when, false) + ". " + string.gigabytestring (file.size (adritem^.podcast.f)) + ".</i></p>"}};
							if sizeof (link) > 0 {
								if not flTitleEndsWithPunc { //5/20/10 by DW
									link = link + "."}}};
						add ("<td class=\"newsItem\" valign=\"top\">" + "<p>" + namelink + link + " " + adritem^.body + "</p>" + downloadinfo + "</td>")}
					else {
						if sizeof (link) > 0 {
							if not flTitleEndsWithPunc { //5/20/10 by DW
								link = link + "."}};
						add ("<p>" + namelink + link + " " + adritem^.body + "</p>")}};
				bundle { //add ornaments
					if flnotmobile {
						local (enc = "", comments = "");
						if defined (adritem^.enclosure) {
							local (encurl = adritem^.enclosure.url); //default
							case string.nthfield (adritem^.enclosure.type, "/", 1) {
								"video" {
									enc = imgVideo};
								"audio" {
									enc = imgMp3}}
							else {
								enc = imgEnclosure};
							bundle { //if we've already downloaded podcast, use a folder icon, 9/1/09 by DW
								if pta^.river2.flSameMachine { //9/16/09 by DW
									if defined (adritem^.podcast) {
										if defined (adritem^.podcast.f) {
											if system.environment.isMac {
												encurl = river2Suite.data.urls.folderPage + "f=" + string.urlencode (adritem^.podcast.f)}
											else {
												encurl = river2Suite.data.urls.folderPage + "folder=" + string.urlencode (file.folderfrompath (adritem^.podcast.f))};
											enc = imgFolder}}}};
							enc = "<a href=\"" + encurl + "\">" + enc + "</a>"};
						if sizeof (adritem^.comments) > 0 {
							comments = "<a href=\"" + adritem^.comments + "\">" + imgComments + "</a>"};
						local (s = "");
						if sizeof (enc) > 0 {
							s = enc};
						if sizeof (comments) > 0 {
							if sizeof (s) > 0 {
								s = s + comments}
							else {
								s = comments};
							s = s + "<br />"};
						bundle { //retweet link, 9/21/09 by DW
							if defined (user.twitter.prefs.username) {
								if sizeof (user.twitter.prefs.username) > 0 {
									local (url = river2Suite.data.urls.redirector);
									url = url + "&link=" + string.urlencode (adritem^.link, true) + "&title=" + string.urlencode (adritem^.title, true);
									url = url + "&twittername=" + string.urlencode (user.twitter.prefs.username, true);
									s = s + "<a href=\"" + url + "\">" + imgTwitter + "</a>"}}};
						bundle { //instapaper link, 3/21/10 by DW
							if adrdata^.prefs.instapaper.enabled {
								local (flcaninstapaper = false);
								bundle { //set flcaninstapaper, must have non-empty title and link
									if defined (adritem^.link) {
										if adritem^.link != "" {
											if defined (adritem^.title) {
												if adritem^.title != "" {
													flcaninstapaper = true}}}}};
								if flcaninstapaper {
									if flnotstaticbuild {
										local (url = river2Suite.data.urls.instapaperPage + itemnum + "&redirect=" + itemname);
										if sizeof (s) > 0 {
											s = s + "<br>"};
										s = s + "<a href=\"" + url + "\">" + imgInstapaper + "</a>"}
									else { //static build, 3/24/10 by DW
										local (url = river2Suite.data.urls.instapaperRemotePage + string.urlencode (adritem^.link) + "&title=" + string.urlencode (adritem^.title));
										if sizeof (s) > 0 {
											s = s + "<br>"};
										s = s + "<a href=\"" + url + "\">" + imgInstapaper + "</a>"}}}};
						if sizeof (s) == 0 {
							s = " "};
						add ("<td class=\"newsOrnaments\" valign=\"top\"><center>" + s + "</center></td>")}};
				if flnotmobile {
					add ("</tr>"); indentlevel--}}
			else {
				return (false)}};
		return (++ct <= maxitems)};
	<<add ("<br /><br />" + imgTitle + "<br /><br />")
	add ("<form method=\"POST\">"); indentlevel++;
	if flnotmobile {
		add ("<table id=\"rivertable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" summary=\"" + adrdata^.prefs.tableSummary + "\">"); indentlevel++};
	if flnotmobile {
		add ("<caption>" + string (river2Suite.data.announcements.current) + " " + clock.now () + ".</caption>")};
	<<add ("<tr><th scope=\"col\" abbr=\"\" class=\"nobg\"> </th><th scope=\"col\" abbr=\"\"> </th><th scope=\"col\" abbr=\"\"> </th>")
	
	local (flhomepage = false); //9/15/09 by DW
	if adrcal == nil { //8/20/09 by DW
		adrcal = @adrdata^.river;
		flhomepage = true};
	mainresponder.calendar.visitReverseChronologic (adrcal, @visit, maxDays:adrdata^.prefs.maxDaysNews); //3/27/11 by DW
	
	if flnotmobile {
		add ("</table>"); indentlevel--};
	add ("<br />");
	if sizeof (errorstring) > 0 {
		add ("<p class=\"errormessage\">" + errorstring + "</p>")};
	add ("<br />");
	<<bundle //Share button commented -- 12/26/09 by DW
		<<add ("<input id=\"submit\" type=\"submit\" name=\"shareButton\" class=\"submitButton\" value=\"Share\" />")
		<<add ("   ")
	if flnotstaticbuild {
		add ("<input id=\"submit\" type=\"submit\" name=\"deleteButton\" class=\"submitButton\" value=\"Delete\" />")};
	add ("</form>"); indentlevel--;
	<<wp.newtextobject (htmltext, @scratchpad.htmltext) //for debugging
	<<log2.add (river2Info.name, "viewNews", "", startticks) //for debugging
	return (htmltext)}
<<bundle //test code
	<<html.setpagetableaddress (@scratchpad.viewNewsParams)
	<<viewNews ()
	<<webbrowser.displaytext (viewNews (@config.river2.enclosures.podcasts))



This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.