added feed items

This commit is contained in:
Hauke Schade 2012-11-23 19:13:46 +01:00
parent 49875713dc
commit d7c98f1e19
2 changed files with 307 additions and 0 deletions

207
qml/ttrss/FeedItems.qml Normal file
View file

@ -0,0 +1,207 @@
//Copyright Hauke Schade, 2012
//
//This file is part of TTRss.
//
//TTRss is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the
//Free Software Foundation, either version 2 of the License, or (at your option) any later version.
//TTRss is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//You should have received a copy of the GNU General Public License along with TTRss (on a Maemo/Meego system there is a copy
//in /usr/share/common-licenses. If not, see http://www.gnu.org/licenses/.
import QtQuick 1.1
import com.nokia.meego 1.0
Page {
id: itemListPage
tools: feedItemsTools
property int feedId: 0
property string pageTitle: ""
property int numStatusUpdates
property bool loading: false
anchors.margins: rootWindow.pageMargin
ListModel {
id: itemListModel
}
ListView {
id: listView
anchors.margins: constant.paddingLarge
anchors{ top: pageHeader.bottom; bottom: parent.bottom; left: parent.left; right: parent.right }
model: itemListModel
delegate: Item {
id: listItem
height: 88
width: parent.width
BorderImage {
id: background
anchors.fill: parent
// Fill page borders
anchors.leftMargin: -itemListPage.anchors.leftMargin
anchors.rightMargin: -itemListPage.anchors.rightMargin
visible: mouseArea.pressed
source: "image://theme/meegotouch-list-background-pressed-center"
}
Row {
anchors.left: parent.left
anchors.right: drilldownarrow.left
clip: true
Column {
clip: true
Label {
id: mainText
text: model.title
font.weight: Font.Bold
font.pixelSize: constant.fontSizeLarge
color: (model.unread > 0) ? constant.colorListItemActive : constant.colorListItemDisabled;
elide: Text.ElideRight
}
Label {
id: subText
text: model.subtitle
font.weight: Font.Light
font.pixelSize: constant.fontSizeSmall
color: (model.unread > 0) ? constant.colorListItemActiveTwo : constant.colorListItemDisabled;
elide: Text.ElideRight
visible: text != ""
}
}
}
Image {
id: drilldownarrow
source: "image://theme/icon-m-common-drilldown-arrow" + (theme.inverted ? "-inverse" : "")
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter
visible: ((model.id != null)&&(model.id !== "__ttrss_get_more_items"))
}
MouseArea {
id: mouseArea
anchors.fill: background
onClicked: {
//TODO open item view with this item
}
}
}
}
ScrollDecorator {
flickableItem: listView
}
function updateFeedItems() {
loading = true;
var ttrss = rootWindow.getTTRSS();
numStatusUpdates = ttrss.getNumStatusUpdates();
ttrss.updateFeedItems(feedId, showFeedItems);
}
function showFeedItems() {
var ttrss = rootWindow.getTTRSS();
var feeditems = ttrss.getFeedItems(feedId);
var showAll = ttrss.getShowAll();
itemListModel.clear();
loading = false;
ttrss.trace(2, ttrss.dump(feeditems))
if (!ttrss.isEmpty(feeditems)) {
for(var feeditem in feeditems) {
itemListModel.append({
title: ttrss.html_entity_decode(feeditems[feeditem].title, 'ENT_QUOTES'),
subtitle: "subtitle",
id: feeditems[feeditem].id,
unread: !!feeditems[feeditem].unread,
});
}
}
else {
itemListModel.append({
title: (showAll ? "No items in feed" : "No unread items in feed"),
subtitle: "",
id: null,
unread: false,
});
}
}
function getMoreItems() {
updateFeedItems();
}
onFeedIdChanged: {
showFeedItems();
updateFeedItems();
}
Component.onCompleted: {
showFeedItems();
updateFeedItems();
}
onStatusChanged: {
var ttrss = rootWindow.getTTRSS();
if(status === PageStatus.Deactivating)
numStatusUpdates = ttrss.getNumStatusUpdates();
else if (status === PageStatus.Activating) {
if(ttrss.getNumStatusUpdates() > numStatusUpdates)
updateFeedItems();
}
}
PageHeader {
id: pageHeader
text: pageTitle
}
ToolBarLayout {
id: feedItemsTools
ToolIcon { iconId: "toolbar-back"; onClicked: { feedItemsMenu.close(); pageStack.pop();} }
ToolIcon {
iconId: "toolbar-refresh";
visible: !loading;
onClicked: { updateFeedItems(); }
}
BusyIndicator {
visible: loading
running: loading
platformStyle: BusyIndicatorStyle { size: 'medium' }
}
ToolIcon { iconId: "toolbar-view-menu" ; onClicked: (feedItemsMenu.status === DialogStatus.Closed) ? feedItemsMenu.open() : feedItemsMenu.close() }
}
Menu {
id: feedItemsMenu
visualParent: pageStack
MenuLayout {
MenuItem {
id: toggleUnread
text: qsTr("Toggle Unread Only")
onClicked: {
var ttrss = rootWindow.getTTRSS();
var oldval = ttrss.getShowAll();
var newval = !oldval;
ttrss.setShowAll(newval);
ttrss.updateFeedItems(feedId, showFeedItems);
}
}
MenuItem {
text: qsTr("About")
onClicked: {
rootWindow.openFile("About.qml");
}
}
}
}
}

View file

@ -29,18 +29,21 @@ var state={
'feeds': {},
'feeditems': {},
'lastcategory': { 'id': null },
'lastfeed': { 'id': null, 'continuation': 0 },
};
var requestsPending={
'token' : false,
'categories' : false,
'feeds' : false,
'feeditems' : false,
};
var responsesPending={
'token' : false,
'categories' : false,
'feeds' : false,
'feeditems' : false,
};
var constants={
@ -294,6 +297,88 @@ function process_updateFeeds(catId, callback, httpreq) {
callback(0);
}
function updateFeedItems(feedId, callback) {
if(responsesPending['feeditems'])
return;
if (state['lastfeed']['id'] !== feedId) {
state['lastfeed']['id'] = feedId;
state['lastfeed']['continuation'] = 0;
}
// needs to be logged in
if(!state['token']) {
requestsPending['feeditems'] = true;
processPendingRequests(callback);
return;
}
responsesPending['feeditems'] = true;
var params = {
'op': 'getHeadlines',
'sid': state['token'],
'feed_id': feedId,
'is_cat': false,
'show_excerpt': false,
'show_content': true, // we want the content, so we do not have to load every article for itself
'view_mode': (state['showall'] ? 'all_articles' : 'unread'),
'skip': state['lastfeed']['continuation']
}
trace(2, 'request: ' + dump(params))
var http = new XMLHttpRequest();
http.open("POST", state['url'], true);
http.setRequestHeader('Content-type','application/json; charset=utf-8');
http.onreadystatechange = function() {
if (http.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
trace(3, "Response Headers -->");
trace(3, http.getAllResponseHeaders());
}
else if (http.readyState === XMLHttpRequest.DONE)
process_updateFeedItems(feedId, callback, http);
}
http.send(JSON.stringify(params));
}
function process_updateFeedItems(feedId, callback, httpreq) {
trace(3, "readystate: "+httpreq.readyState+" status: "+httpreq.status);
trace(3, "response: "+httpreq.responseText);
if(httpreq.status === 200) {
var responseObject=JSON.parse(httpreq.responseText);
if (responseObject.status === 0) {
state['feeditems'][feedId] = {};
//TODO update the continuation counter
for(var i = 0; i < responseObject.content.length; i++) {
var feeditemid = responseObject.content[i].id;
state['feeditems'][feedId][feeditemid] = responseObject.content[i];
}
}
else {
if(responseObject.content.error)
errorText = "Update Feeds failed: "+responseObject.content.error;
else
errorText = "Update Feeds failed (received http code: "+http.status+")";
}
}
else {
trace(1, "Update Feeds Error: received http code: "+httpreq.status+" full text: "+httpreq.responseText);
if(callback)
callback(50, "Update Feeds Error: received http code: "+httpreq.status+" full text: "+httpreq.responseText);
}
responsesPending['feeditems'] = false;
if(state['feeditems'][feedId])
if(!processPendingRequests(callback))
//This action is complete (as there's no other requests to do, fire callback saying all ok
if(callback)
callback(0);
}
function processPendingRequests(callback) {
trace(4, 'In pPR');
var foundWork = false;
@ -328,6 +413,17 @@ function processPendingRequests(callback) {
else
updateFeeds(state['lastcategory']['id'], callback);
}
else if (requestsPending['feeditems']) {
trace(4, 'feeditems request pending');
foundWork = true;
if(responsesPending['feeditems'])
return foundWork;
if(!state['token'])
//Get the auth token
login(callback);
else
updateFeedItems(state['lastfeed']['id'], callback);
}
return foundWork;
}
@ -362,3 +458,7 @@ function getCategories() {
function getFeeds(catId) {
return state['feeds'][catId];
}
function getFeedItems(feedId) {
return state['feeditems'][feedId];
}