diff options
-rw-r--r-- | ajax/loadfeed.php | 18 | ||||
-rw-r--r-- | ajax/markitem.php | 35 | ||||
-rw-r--r-- | ajax/setallitemsread.php (renamed from ajax/importantitem.php) | 25 | ||||
-rw-r--r-- | ajax/setitemstatus.php | 53 | ||||
-rw-r--r-- | css/news.css | 244 | ||||
-rw-r--r-- | img/inactive_star.svg | 8 | ||||
-rw-r--r-- | js/news.js | 273 | ||||
-rw-r--r-- | templates/main.php | 4 | ||||
-rw-r--r-- | templates/part.items.php | 28 |
9 files changed, 475 insertions, 213 deletions
diff --git a/ajax/loadfeed.php b/ajax/loadfeed.php index 992e65019..020f7a706 100644 --- a/ajax/loadfeed.php +++ b/ajax/loadfeed.php @@ -17,19 +17,19 @@ OCP\JSON::callCheck(); $userid = OCP\USER::getUser(); -$feedid = trim($_POST['feedid']); +$feedId = trim($_POST['feedId']); $l = OC_L10N::get('news'); -$tmpl_items = new OCP\Template("news", "part.items"); -$tmpl_items->assign('feedid', $feedid); -$part_items = $tmpl_items->fetchPage(); +$itemsTpl = new OCP\Template("news", "part.items"); +$itemsTpl->assign('feedid', $feedId); +$feedItems = $itemsTpl->fetchPage(); -$tmpl_items_header = new OCP\Template("news", "part.items.header"); -$tmpl_items_header->assign('feedid', $feedid); -$items_header = $tmpl_items_header->fetchPage(); +$feedMapper = new OCA\News\FeedMapper(); +$feed = $feedMapper->findById($feedId); +$feedTitle = $feed->getTitle(); OCP\JSON::success(array('data' => array( 'message' => $l->t('Feed loaded!'), - 'items_header' => $items_header, - 'part_items' => $part_items ))); + 'feedTitle' => $feedTitle, + 'feedItems' => $feedItems ))); diff --git a/ajax/markitem.php b/ajax/markitem.php deleted file mode 100644 index a6efc8521..000000000 --- a/ajax/markitem.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** -* ownCloud - News app -* -* @author Alessandro Cosentino -* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> -* -* This file is licensed under the Affero General Public License version 3 or later. -* See the COPYING-README file -* -*/ - -// Check if we are a user -OCP\JSON::checkLoggedIn(); -OCP\JSON::checkAppEnabled('news'); -OCP\JSON::callCheck(); - -$itemid = $_POST['itemid']; - -$itemmapper = new OCA\News\ItemMapper(); -$item = $itemmapper->find($itemid); -$item->setRead(); -$success = $itemmapper->update($item); - -$l = OC_L10N::get('news'); - -if(!$success) { - OCP\JSON::error(array('data' => array('message' => $l->t('Error marking item as read.')))); - OCP\Util::writeLog('news','ajax/markitem.php: Error marking item as read: '.$_POST['itemid'], OCP\Util::ERROR); - exit(); -} - -//TODO: replace the following with a real success case. see contact/ajax/createaddressbook.php for inspirations -OCP\JSON::success(array('data' => array('itemid' => $itemid ))); - diff --git a/ajax/importantitem.php b/ajax/setallitemsread.php index 72a07f747..4c1876b50 100644 --- a/ajax/importantitem.php +++ b/ajax/setallitemsread.php @@ -15,28 +15,27 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::checkAppEnabled('news'); OCP\JSON::callCheck(); -$itemId = $_POST['itemId']; -$isImportant = $_POST['isImportant']; +$feedId = $_POST['feedId']; $itemMapper = new OCA\News\ItemMapper(); -$item = $itemMapper->find($itemId); - -if($isImportant){ - $item->setImportant(); -} else { - $item->setUnimportant(); +$items = $itemMapper->findAllStatus($feedId, OCA\News\StatusFlag::Unread); + +// FIXME: maybe there is a way to set all items read in the +// FeedMapper instead of iterating through every item and updating as +// necessary +foreach($items as $item){ + $item->setRead(); + $success = $itemMapper->update($item); } -$success = $itemMapper->update($item); - $l = OC_L10N::get('news'); if(!$success) { - OCP\JSON::error(array('data' => array('message' => $l->t('Error marking item as important.')))); - OCP\Util::writeLog('news','ajax/importantitem.php: Error marking item as important: '.$_POST['itemId'], OCP\Util::ERROR); + OCP\JSON::error(array('data' => array('message' => $l->t('Error setting all items as read.')))); + OCP\Util::writeLog('news','ajax/setallitemsread.php: Error setting all items as read of feed '. $feedId, OCP\Util::ERROR); exit(); } //TODO: replace the following with a real success case. see contact/ajax/createaddressbook.php for inspirations -OCP\JSON::success(array('data' => array('itemId' => $itemId))); +OCP\JSON::success(array('data' => array('feedId' => $feedId ))); diff --git a/ajax/setitemstatus.php b/ajax/setitemstatus.php new file mode 100644 index 000000000..03dff7d94 --- /dev/null +++ b/ajax/setitemstatus.php @@ -0,0 +1,53 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +// Check if we are a user +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('news'); +OCP\JSON::callCheck(); + +$itemId = $_POST['itemId']; +$status = $_POST['status']; + +$itemMapper = new OCA\News\ItemMapper(); +$item = $itemMapper->find($itemId); + +switch ($status) { + case 'read': + $item->setRead(); + break; + case 'unread': + $item->setUnread(); + break; + case 'important': + $item->setImportant(); + break; + case 'unimportant': + $item->setUnimportant(); + break; + default: + break; +} + +$success = $itemMapper->update($item); + +$l = OC_L10N::get('news'); + +if(!$success) { + OCP\JSON::error(array('data' => array('message' => $l->t('Error marking item as read.')))); + OCP\Util::writeLog('news','ajax/setitemstatus.php: Error setting itemstatus to '. $status .': '.$_POST['itemid'], OCP\Util::ERROR); + exit(); +} + +//TODO: replace the following with a real success case. see contact/ajax/createaddressbook.php for inspirations +OCP\JSON::success(array('data' => array('itemId' => $itemId ))); + diff --git a/css/news.css b/css/news.css index 953a729a1..8381e0a3f 100644 --- a/css/news.css +++ b/css/news.css @@ -50,64 +50,210 @@ ul.controls li { float: left; } /* item view */ -#rightcontent { top: 3.5em !important; padding: 0 0 0 5px; box-sizing: border-box; -moz-box-sizing: border-box; margin-top: 3.5em;} - -#rightcontent div.feed_controls { box-sizing: border-box; -moz-box-sizing: border-box; background: none repeat scroll 0 0 #FFFFFF; border-bottom: 1px solid #ccc; box-shadow: 0 3px 3px -3px #000000; text-align: right; overflow: hidden; position: fixed; left: 32.5em; right: 0; top: 3.5em; } -#rightcontent div.feed_controls div.feed_title { float: left; padding-left: 10px; } -#rightcontent div.feed_controls div.feed_title h1 { font-size: 1.7em; color: #444; padding-top: .5em; } - -#rightcontent #feed_items { +#rightcontent { + top: 3.5em !important; + padding: 0 0 0 5px; box-sizing: border-box; -moz-box-sizing: border-box; - overflow: auto; - height: 100%; -} - -#feed_items h1.item_title { } -#feed_items .title_unread h1.item_title { font-weight: bold; border-bottom: 1px solid #222; } -#feed_items .title_unread h1.item_title a { color: #222; } -#feed_items .title_unread h1.item_title, -#feed_items .title_read h1.item_title { padding: 15px 10px 10px 10px; font-size: 1.5em; } -#feed_items .title_read h1.item_title { font-weight: normal; border-bottom: 1px solid #ccc; } -#feed_items .title_read h1.item_title a { color: #888; } -#feed_items .title_read a:hover, #feed_items .title_unread a:hover { text-decoration: underline; } - -#feed_items .item_utils { - float: left; - padding: 15px 10px 10px; -} -#feed_items .item_utils ul {} -#feed_items .item_utils ul li { display: inline-block; } -#feed_items .item_utils ul li.star { - background-image: url('%appswebroot%/news/img/inactive_star.svg'); - background-repeat: no-repeat; - background-size: 100%; - height: 1.5em; - width: 1.5em; + margin-top: 3.5em; } -#feed_items .item_utils ul li.star.important, -#feed_items .item_utils ul li.star:hover { - background-image: url('%appswebroot%/news/img/active_star.svg'); -} - - -#feed_items div.body { padding: 15px 25px 10px 25px; } -#feed_items div.body p { line-height: 1.5; margin: 10px 0; } -#feed_items div.body a { color: #0000ff; text-decoration: underline; } -#feed_items div.body ul { padding-left: 15px; list-style-type: disc; } -#feed_items div.body ul li { cursor: default; } -#feed_items li:active { background: none; } -#feed_items div.body pre { padding: 5px; background-color: #dadada; border: 1px solid #ccc; } -#feed_items div.body pre code { font-family: monospace; font-size: 1.5em; } - -#feed_items div.rightcontentmsg { padding-left: 10px; background-color: yellow; } + /** + * View above the feeds which shows the feed title + * and the controls + */ + #rightcontent div.feed_controls { + box-sizing: border-box; + -moz-box-sizing: border-box; + background: none repeat scroll 0 0 #FFFFFF; + border-bottom: 1px solid #ccc; + box-shadow: 0 3px 3px -3px #000000; + text-align: right; overflow: hidden; + position: fixed; + left: 32.5em; + right: 0; + top: 3.5em; + } + + #rightcontent div.feed_controls div.feed_title { + float: left; + padding-left: 10px; + } + + #rightcontent div.feed_controls div.feed_title h1 { + font-size: 1.7em; + color: #444; + padding-top: .5em; + } + + /** + * Area below the feed title and controls + */ + #rightcontent #feed_items { + box-sizing: border-box; + -moz-box-sizing: border-box; + overflow: auto; + height: 100%; + } + + #rightcontent #feed_items li:active { + background: none; + } + + /** + * Rules for a single feed item + */ + .feed_item { + border-top: 1px solid #ccc; + min-height: 100px; + } + + /** + * Utils panel + */ + .utils { + height: 2em; + margin: 0; + padding: 0.6em 0.5em 0.5em 0.5em; + background-image: linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -o-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -moz-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -webkit-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + background-image: -ms-linear-gradient(top, rgb(238,238,238) 0%, rgb(255,255,255) 100%); + } + + /** + * Primary feed utils which are always shown + */ + .feed_item .primary_item_utils { + float: left; + } + + .feed_item .primary_item_utils li { + display: inline-block; + line-height: 1.5em; + font-size: 1em; + color: #aaa; + float: left; + margin-left: ; + cursor: default; + } + + .feed_item .primary_item_utils li:first-child { margin: 0} + .feed_item .primary_item_utils li.star { + background-image: url('%appswebroot%/news/img/inactive_star.svg'); + background-repeat: no-repeat; + background-size: 100%; + width: 1.5em; + height: 1.5em; + cursor: pointer; + } + + .feed_item .primary_item_utils li.star.important, + .feed_item .primary_item_utils li.star:hover { + background-image: url('%appswebroot%/news/img/active_star.svg'); + } + + /** + * Secondary feed items which are only shown on hover + */ + .feed_item .secondary_item_utils { + float: right; + color: #aaa; + } + /* + .feed_item:hover .secondary_item_utils { + display: block; + }*/ + + .feed_item:hover .secondary_item_utils li.keep_unread { + cursor: pointer; + } + + .feed_item .secondary_item_utils li input[type=checkbox]{ + margin-left: .8em; + } + + /** + * Feed title + */ + .feed_item h1.item_title { + font-size: 1.5em; + margin: 0 0 0 1.6em; + font-weight: bold; + } + + .feed_item h1.item_title a { + color: #222; + } + .feed_item h1.item_title a:hover { + color: #222; + text-decoration: underline; + } + + /** + * Feed title when read + */ + .feed_item.read h1.item_title { + font-weight: normal; + } + + .feed_item.read h1.item_title a { + color: #888; + } + + /** + * Author of the feed + */ + .feed_item h2.item_author { + color: #aaa; + margin-left: 2.5em; + } + + + /** + * Body of the feed item + */ + .feed_item div.body { + padding: .5em 2.5em 2em 2.5em; + } + + .feed_item div.body p { + line-height: 1.5; + margin: 10px 0; + } + + .feed_item div.body a { + color: #0000ff; + text-decoration: underline; + } + + .feed_item div.body ul { + padding-left: 15px; + list-style-type: disc; + } + + .feed_item div.body ul li { + cursor: default; + } + + .feed_item div.body pre { + padding: 5px; + background-color: #dadada; + border: 1px solid #ccc; + } + + .feed_item div.body pre code { + font-family: monospace; + font-size: 1.5em; + } + /* dialog/menues */ div.dialog { overflow: visible; } -#dropdownBtn { width: 20em; padding-left: 0; padding-right:20px; background: url('%webroot%/core/img/actions/triangle-s.svg') no-repeat right center; text-align: left; overflow: hidden;} +#dropdownBtn { width: 12.5em; padding-left: 0; padding-right:20px; background: url('%webroot%/core/img/actions/triangle-s.svg') no-repeat right center; text-align: left; overflow: hidden;} ul#dropdownmenu { left: 0em; box-shadow: 0px 0px 10px rgb(0, 0, 0); } ul#feedfoldermenu { position:fixed; margin-left: 0; bottom: 2.8em; border-left:1px solid #ccc; border-top:1px solid #ccc; border-right:1px solid #ccc; -moz-box-shadow: 0 -3px 3px -3px #000; -webkit-box-shadow: 0 -3px 3px -3px #000; box-shadow: 0 -3px 3px -3px #000;} diff --git a/img/inactive_star.svg b/img/inactive_star.svg index 5273fcd86..d2dbb0bd9 100644 --- a/img/inactive_star.svg +++ b/img/inactive_star.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.48.3.1 r9886" - sodipodi:docname="New document 1"> + sodipodi:docname="inactive_star.svg"> <defs id="defs4" /> <sodipodi:namedview @@ -25,8 +25,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="2.8" - inkscape:cx="108.52005" - inkscape:cy="134.37797" + inkscape:cx="44.591479" + inkscape:cy="133.66368" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -47,7 +47,7 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> + <dc:title /> </cc:Work> </rdf:RDF> </metadata> diff --git a/js/news.js b/js/news.js index 7268ea514..13350c579 100644 --- a/js/news.js +++ b/js/news.js @@ -175,71 +175,35 @@ News={ }); return false; }, - markItem:function(itemid, feedid) { - var currentitem = $('#feed_items [data-id="' + itemid + '"][data-feedid="' + feedid + '"]'); - if (currentitem.hasClass('title_unread')) { - $.post(OC.filePath('news', 'ajax', 'markitem.php'),{'itemid':itemid},function(jsondata){ - if(jsondata.status == 'success'){ - currentitem.removeClass('title_unread'); - currentitem.addClass('title_read'); - - // decrement counter - var counterplace = $('li.feed[data-id="'+feedid+'"]').find('.unreaditemcounter'); - var title = $('li.feed[data-id="'+feedid+'"] > a'); - var oldcount = counterplace.html(); - counterplace.empty(); - if (oldcount <= 1) { - counterplace.removeClass('nonzero').addClass('zero'); - title.removeClass('nonzero').addClass('zero'); - } - else { - counterplace.append(--oldcount); - } - //set a timeout for this - } - else{ - OC.dialogs.alert(jsondata.data.message, t('news', 'Error')); - } - }) - }; - }, - markAllItems:function() { - $("#feed_items li.title_unread").each(function(){ - var itemId = $(this).data('id'); - var feedId = $(this).data('feedid'); - News.Feed.markItem(itemId, feedId); - }); - }, - setImportant:function(isImportant, itemId, feedId){ - var $currentItem = $('#feed_items [data-id="' + itemId + '"][data-feedid="' + feedId + '"]'); - var $currentStar = $currentItem.children('.item_utils').children('ul').children('li.star'); - data = { - isImportant: isImportant, - itemId: itemId, - feedId: feedId - }; - $.post(OC.filePath('news', 'ajax', 'importantitem.php'), data, function(jsondata){ - if(jsondata.status == 'success'){ - if(isImportant){ - $currentStar.removeClass('important'); - } else { - $currentStar.addClass('important'); - } - } else{ - OC.dialogs.alert(jsondata.data.message, t('news', 'Error')); + setAllItemsRead:function(feedId) { + $.post(OC.filePath('news', 'ajax', 'setallitemsread.php'), { 'feedId' : feedId }, function(jsonData) { + if(jsonData.status == 'success'){ + // mark ui items as read + $("#feed_items .feed_item:not(.read)").each(function(){ + $(this).addClass('read'); + }); + + var $feedItemCounter = $('li.feed[data-id="'+feedId+'"]').find('.unreaditemcounter'); + $feedItemCounter.removeClass('nonzero').addClass('zero'); + $feedItemCounter.empty(); + } else { + OC.dialogs.alert(t('news', 'Error while loading the feed'), t('news', 'Error')); } }); }, - load:function(feedid) { - $.post(OC.filePath('news', 'ajax', 'loadfeed.php'),{'feedid':feedid},function(jsondata) { - if(jsondata.status == 'success'){ - var rightcontent = $('div.rightcontent'); - rightcontent.empty(); - rightcontent.attr('data-id', feedid); - rightcontent.html(jsondata.data.items_header + jsondata.data.part_items); + load:function(feedId) { + $.post(OC.filePath('news', 'ajax', 'loadfeed.php'), { 'feedId' : feedId }, function(jsonData) { + if(jsonData.status == 'success'){ + var $rightContent = $(".rightcontent"); + $rightContent.attr('data-id', feedId); + var $feedItems = $('#feed_items'); + $feedItems.empty(); + $feedItems.html(jsonData.data.feedItems); + var $feedTitle = $(".feed_controls .feed_title h1"); + $feedTitle.html('ยป ' + jsonData.data.feedTitle); $('li#selected_feed').attr('id', ''); - $('li.feed[data-id="' + feedid + '"]').attr('id', 'selected_feed'); + $('li.feed[data-id="' + feedId + '"]').attr('id', 'selected_feed'); transformCollapsableTrigger(); bindItemEventListeners(); @@ -292,17 +256,132 @@ News={ // TODO: safe this on the server switch(value){ case 'all': - $("#feed_items li").show(); + $("#feed_items .feed_item").show(); break; case 'newest': - $("#feed_items li.title_read").hide(); + $("#feed_items .feed_item.read").hide(); break; default: break; } } - } + }, + // this handler handles changes in the ui when the itemstatus changes + ItemStatusHandler: function(itemId){ + var _itemId = itemId; + var _$currentItem = $('#feed_items li[data-id="' + itemId + '"]'); + var _$currentItemStar = _$currentItem.children('.utils').children('.primary_item_utils').children('.star'); + var _$currentItemKeepUnread = _$currentItem.children('.utils').children('.secondary_item_utils').children('.keep_unread').children('input[type=checkbox]'); + var _feedId = _$currentItem.data('feedid'); + var _read = _$currentItem.hasClass('read'); + var _important = _$currentItemStar.hasClass('important'); + var _keepUnread = _$currentItemKeepUnread.prop('checked'); + + /** + * Switches important items to unimportant and vice versa + */ + var _toggleImportant = function(){ + if(_important){ + status = 'unimportant'; + } else { + status = 'important'; + } + + var data = { + itemId: itemId, + status: status + }; + + $.post(OC.filePath('news', 'ajax', 'setitemstatus.php'), data, function(jsondata){ + if(jsondata.status == 'success'){ + if(_important){ + _$currentItemStar.removeClass('important'); + } else { + _$currentItemStar.addClass('important'); + } + } else{ + OC.dialogs.alert(jsondata.data.message, t('news', 'Error')); + } + }); + }; + + /** + * Toggles an item as "keep unread". This prevents all handlers to mark it as unread + * except the current one + */ + var _toggleKeepUnread = function(){ + if(_keepUnread){ + _$currentItemKeepUnread.prop("checked", false); + } else { + _$currentItemKeepUnread.prop("checked", true); + _setRead(false); + } + }; + + /** + * Sets the current item as read or unread + * @param read true sets the item to read, false to unread + */ + var _setRead = function(read){ + var status; + + // if we already have the status, do nothing + if(read === _read) return; + // check if the keep unread flag was set + if(read && _keepUnread) return; + + if(read){ + status = 'read'; + } else { + status = 'unread'; + } + + var data = { + itemId: itemId, + status: status + }; + + $.post(OC.filePath('news', 'ajax', 'setitemstatus.php'), data, function(jsonData){ + if(jsonData.status == 'success'){ + var counterplace = $('li.feed[data-id="'+_feedId+'"]').find('.unreaditemcounter'); + var title = $('li.feed[data-id="'+_feedId+'"] > a'); + var oldcount = counterplace.html(); + counterplace.empty(); + + if(read){ + _$currentItem.addClass('read'); + if (oldcount <= 1) { + counterplace.removeClass('nonzero').addClass('zero'); + title.removeClass('nonzero').addClass('zero'); + } else { + counterplace.html(--oldcount); + } + } else { + _$currentItem.removeClass('read'); + if (oldcount === '') { + counterplace.removeClass('zero').addClass('nonzero'); + title.removeClass('zero').addClass('nonzero'); + counterplace.html(1); + } else { + counterplace.html(++oldcount); + } + } + + } else { + OC.dialogs.alert(jsonData.data.message, t('news', 'Error')); + } + }) + + }; + + // set public methods + this.setRead = function(read){ _setRead(read); } + this.isRead = function(){ return _read; } + this.toggleImportant = function(){ _toggleImportant(); } + this.toggleKeepUnread = function(){ _toggleKeepUnread(); } + }, + } function transformCollapsableTrigger() { @@ -371,48 +450,34 @@ function setupFeedList() { */ function bindItemEventListeners(){ - // mark items whose title was hid under the top edge as read - // when the bottom is reached, mark all items as read - $('#feed_items').scroll(function(){ - var boxHeight = $(this).height(); - var scrollHeight = $(this).prop('scrollHeight'); - var scrolled = $(this).scrollTop() + boxHeight; - - $(this).children('ul').children('li.title_unread').each(function(){ - var itemOffset = $(this).position().top; - if(itemOffset <= 0 || scrolled >= scrollHeight){ - var itemId = $(this).data('id'); - var feedId = $(this).data('feedid'); - News.Feed.markItem(itemId, feedId); - } - }) - }); - // single hover on item should mark it as read too $('#feed_items h1.item_title a').click(function(){ - var $item = $(this).parent().parent('.news_item'); + var $item = $(this).parent().parent('.feed_item'); var itemId = $item.data('id'); - var feedId = $item.data('feedid'); - News.Feed.markItem(itemId, feedId); + var handler = new News.ItemStatusHandler(itemId); + handler.setRead(true); }) // mark or unmark as important $('#feed_items li.star').click(function(){ - var important = $(this).hasClass('important'); - var $item = $(this).parent().parent().parent('.news_item'); + var $item = $(this).parent().parent().parent('.feed_item'); + var itemId = $item.data('id'); + var handler = new News.ItemStatusHandler(itemId); + handler.toggleImportant(); + }) + + // toggle logic for the keep unread handler + $('#feed_items .keep_unread').click(function(){ + var $item = $(this).parent().parent().parent('.feed_item'); var itemId = $item.data('id'); - var feedId = $item.data('feedid'); - News.Feed.setImportant(important, itemId, feedId); + var handler = new News.ItemStatusHandler(itemId); + handler.toggleKeepUnread(); }) // bind the mark all as read button $('#mark_all_as_read').click(function(){ - News.Feed.markAllItems(); - }); - - // filter for newest or all items - $('#feed_filter').change(function(){ - News.Feed.filter($(this).val()); + var feedId = $('.rightcontent').data('id'); + News.Feed.setAllItemsRead(feedId); }); } @@ -447,6 +512,28 @@ $(document).ready(function(){ bindItemEventListeners(); + // filter for newest or all items + $('#feed_filter').change(function(){ + News.Feed.filter($(this).val()); + }); + + // mark items whose title was hid under the top edge as read + // when the bottom is reached, mark all items as read + $('#feed_items').scroll(function(){ + var boxHeight = $(this).height(); + var scrollHeight = $(this).prop('scrollHeight'); + var scrolled = $(this).scrollTop() + boxHeight; + + $(this).children('ul').children('.feed_item:not(.read)').each(function(){ + var itemOffset = $(this).position().top; + if(itemOffset <= 0 || scrolled >= scrollHeight){ + var itemId = $(this).data('id'); + var handler = new News.ItemStatusHandler(itemId); + handler.setRead(true); + } + }) + }); + }); $(document).click(function(event) { diff --git a/templates/main.php b/templates/main.php index e02a29277..5c066e599 100644 --- a/templates/main.php +++ b/templates/main.php @@ -35,7 +35,9 @@ if ($_['feedid']){ <div id="rightcontent" class="rightcontent" data-id="<?php echo $_['feedid']; ?>"> <?php echo $this->inc("part.items.header"); - echo $this->inc("part.items"); + echo '<div id="feed_items">'; + echo $this->inc("part.items"); + echo '</div>'; ?> <div id="appsettings" class="popup bottomleft hidden"></div> diff --git a/templates/part.items.php b/templates/part.items.php index 7334fa35a..49423236c 100644 --- a/templates/part.items.php +++ b/templates/part.items.php @@ -5,14 +5,13 @@ $feedid = isset($_['feedid']) ? $_['feedid'] : ''; $itemmapper = new OCA\News\ItemMapper(); $items = $itemmapper->findAll($feedid); -echo '<div id="feed_items">'; echo '<ul>'; foreach($items as $item) { if($item->isRead()){ - $newsItemClass = "title_read"; + $newsItemClass = "read"; } else { - $newsItemClass = "title_unread"; + $newsItemClass = ""; } if($item->isImportant()){ @@ -23,14 +22,25 @@ foreach($items as $item) { $startTitle = $l->t('Mark as important'); } - echo '<li class="news_item ' . $newsItemClass .'" data-id="' . $item->getId() . '" data-feedid="' . $feedid . '">'; - echo '<div class="item_utils"><ul>'; - echo '<li class="star ' . $starClass . '" title="' . $startTitle . '"></li>'; - echo '</ul></div>'; - echo '<h1 class="item_title"><a target="_blank" href="' . $item->getUrl() . '">' . $item->getTitle() . '</a></h1>'; + echo '<li class="feed_item ' . $newsItemClass .'" data-id="' . $item->getId() . '" data-feedid="' . $feedid . '">'; + + echo '<div class="utils">'; + echo '<ul class="primary_item_utils">'; + echo '<li class="star ' . $starClass . '" title="' . $startTitle . '"></li>'; + echo '</ul>'; + + echo '<ul class="secondary_item_utils">'; + echo '<li class="keep_unread">' . $l->t('Keep unread') . '<input type="checkbox" /></li>'; + echo '</ul>'; + echo '</div>'; + + echo '<h1 class="item_title"><a target="_blank" href="' . $item->getUrl() . '">' . $item->getTitle() . '</a></h1>'; + + echo '<h2 class="item_author">' . $l->t('from') . ' ' . parse_url($item->getUrl(), PHP_URL_PATH) . '</h2>'; + echo '<div class="body">' . $item->getBody() . '</div>'; + echo '</li>'; } echo '</ul>'; |