'Viewport' meta tag in offline mode view

This commit is contained in:
mkiol 2014-02-21 22:50:49 +01:00
parent 115da57336
commit 3a05bd5b29
17 changed files with 233 additions and 84 deletions

View file

@ -28,24 +28,27 @@ Rectangle {
property string text
property bool cancelable: false
property bool open: false
property real progress: 0.0
signal closeClicked
height: visible ? Theme.itemSizeSmall : 0
//height: visible ? Theme.itemSizeSmall : 0
height: visible ? 70 : 0
width: parent.width
anchors.bottom: parent.bottom
anchors.left: parent.left
/*gradient: Gradient {
GradientStop { position: -0.5; color: "transparent" }
GradientStop { position: 1.5; color: Theme.highlightBackgroundColor}
GradientStop { position: 0.0; color: "transparent" }
GradientStop { position: 0.95; color: Theme.highlightBackgroundColor}
}*/
color: Theme.highlightBackgroundColor
enabled: opacity > 0.0
opacity: root.open ? 1.0 : 0.0
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {} }
function show(text, cancelable) {
@ -58,47 +61,70 @@ Rectangle {
root.open = false;
}
Row {
spacing: Theme.paddingMedium
anchors{
left: parent.left; leftMargin: Theme.paddingMedium
right: parent.right; rightMargin: Theme.paddingMedium
verticalCenter: parent.verticalCenter
}
Rectangle {
id: progressRect
height: parent.height
anchors.right: parent.right
width: parent.width - (root.progress * parent.width)
color: Theme.highlightDimmerColor
opacity: 0.2
Image {
id: icon
anchors.verticalCenter: parent.verticalCenter
//source: "image://theme/icon-m-sync" + "?" + Theme.highlightDimmerColor
source: "image://theme/graphic-busyindicator-medium" + "?" + Theme.highlightDimmerColor
RotationAnimation on rotation {
loops: Animation.Infinite
from: 0
to: 360
duration: 1000
running: root.open
Behavior on width {
enabled: root.opacity == 1.0
SmoothedAnimation {
velocity: 480; duration: 200
}
}
}
Label {
id: titleBar
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
text: root.text
width: parent.width - icon.width * 2 - parent.spacing *2
height: icon.height
anchors.verticalCenter: parent.verticalCenter
color: Theme.highlightDimmerColor
verticalAlignment: Text.AlignVCenter
Image {
id: icon
height: 40; width: 40
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Theme.paddingMedium
source: "image://theme/graphic-busyindicator-medium?"+Theme.highlightDimmerColor
RotationAnimation on rotation {
loops: Animation.Infinite
from: 0
to: 360
duration: 1200
running: root.open
}
}
IconButton {
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://theme/icon-m-close" + "?" + Theme.highlightDimmerColor
onClicked: root.closeClicked()
visible: root.cancelable
onVisibleChanged: {
if (!visible) {
progress = 0;
}
}
Label {
id: titleBar
height: icon.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: icon.right; anchors.right: closeButton.right
anchors.leftMargin: Theme.paddingMedium
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
text: root.text
color: Theme.highlightDimmerColor
verticalAlignment: Text.AlignVCenter
}
IconButton {
id: closeButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.leftMargin: Theme.paddingMedium
anchors.rightMargin: Theme.paddingMedium
icon.source: "image://theme/icon-m-close?"+Theme.highlightDimmerColor
onClicked: root.closeClicked()
visible: root.cancelable
}
}

View file

@ -32,6 +32,7 @@ Page {
model: entryModel
MainMenu{}
//UpMenu {}
header: PageHeader {
title: root.title

View file

@ -32,6 +32,7 @@ Page {
model: feedModel
MainMenu{}
//UpMenu {}
header: PageHeader {
title: root.title

View file

@ -31,6 +31,11 @@ Rectangle {
color: Theme.highlightBackgroundColor
opacity: timer.running ? 1.0 : 0.0
MouseArea {
anchors.fill: parent
onClicked: timer.stop()
}
Behavior on opacity { FadeAnimation {} }
function show(text) {

View file

@ -107,7 +107,7 @@ Page {
Label {
id: dashboard
color: Theme.highlightColor
text: settings.getNetvibesDefaultDashboard()
text: utils.defaultDashboardName()
}
}

View file

@ -30,6 +30,7 @@ Page {
model: tabModel
MainMenu{}
//UpMenu {}
header: PageHeader {
title: "Tabs"
@ -80,6 +81,7 @@ Page {
width: parent.width
Label {
id: label
wrapMode: Text.AlignLeft
anchors.left: parent.left; anchors.right: parent.right;
anchors.leftMargin: Theme.paddingLarge; anchors.rightMargin: Theme.paddingLarge
@ -88,6 +90,15 @@ Page {
}
}
Image {
id: image
width: Theme.iconSizeSmall
height: Theme.iconSizeSmall
anchors.right: parent.right; anchors.rightMargin: Theme.paddingLarge
anchors.verticalCenter: item.verticalCenter
source: iconUrl
}
onClicked: {
utils.setFeedModel(uid);
pageStack.push(Qt.resolvedUrl("FeedPage.qml"),{"title": title});

53
qml/UpMenu.qml Normal file
View file

@ -0,0 +1,53 @@
/*
Copyright (C) 2014 Michal Kosciesza <michal@mkiol.net>
This file is part of Kaktus.
Kaktus 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 3 of the License, or
(at your option) any later version.
Kaktus 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 Kaktus. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
PushUpMenu {
/*MenuLabel {
text: app.offLineMode ? qsTr("Offline") : qsTr("Online")
}
MenuItem {
//text: app.offLineMode ? qsTr("Switch to Online") : qsTr("Switch to Offline")
text: qsTr("Switch mode")
onClicked: {
if (app.offLineMode)
settings.setOfflineMode(false);
else
settings.setOfflineMode(true);
offLineMode = settings.getOfflineMode();
}
}*/
Row {
Switch{
id: pause
iconSource: "image://theme/icon-m-wlan"
onClicked: offLineMode = !offLineMode;
enabled: !offLineMode
}
}
}

View file

@ -115,12 +115,12 @@ Page {
}
}
PushUpMenu {
/*PushUpMenu {
MenuItem {
text: qsTr("Top")
onClicked: view.scrollToTop()
}
}
}*/
}
BusyBar {

View file

@ -22,16 +22,16 @@ import Sailfish.Silica 1.0
ApplicationWindow {
id: app
property bool offLineMode: false
property bool offLineMode
onOffLineModeChanged: {
settings.setOfflineMode(offLineMode);
if (offLineMode)
/*if (offLineMode)
notification.show(qsTr("Offline mode!"));
else
notification.show(qsTr("Online mode!"));
notification.show(qsTr("Online mode!"));*/
}
Component.onCompleted: {
@ -126,7 +126,7 @@ ApplicationWindow {
utils.setTabModel(settings.getNetvibesDefaultDashboard());
pageStack.replaceAbove(null,Qt.resolvedUrl("TabPage.qml"));
if (!dm.isBusy() && settings.getAutoDownloadOnUpdate()) {
if (!dm.isBusy() && settings.getAutoDownloadOnUpdate() ) {
dm.startFeedDownload();
} else {
busy.hide();
@ -168,7 +168,9 @@ ApplicationWindow {
onProgress: {
console.log("Fetcher progress: " + current + "/" + total);
busy.text = "Fetching data... " + Math.floor((current / total) * 100) + "%";
//busy.text = "Fetching data... " + Math.floor((current / total) * 100) + "%";
busy.text = "Receiving data... ";
busy.progress = current / total;
}
onInitiating: {
@ -198,20 +200,29 @@ ApplicationWindow {
}
/*BusyPanel {
id: busy
onCancel: {
console.log("cancel!");
if (dm.isBusy()) {
dm.cancel();
}
}
}*/
Notification {
id: notification
}
Image {
anchors {
right: parent.right
bottom: parent.bottom
margins: Theme.paddingSmall
}
source: offLineMode ? "image://theme/icon-status-wlan-no-signal" : "image://theme/icon-status-wlan-4"
height: 48
width: 48
smooth: true
MouseArea {
anchors.fill: parent
onClicked: {
offLineMode = !offLineMode;
}
}
}
BusyBar {
id: busy
onCloseClicked: {
@ -222,23 +233,4 @@ ApplicationWindow {
}
}
/*Image {
anchors {
right: parent.right
bottom: parent.bottom
margins: Theme.paddingSmall
}
source: offLineMode ? "image://theme/icon-status-wlan-0" : "image://theme/icon-status-wlan-4"
height: 48
width: 48
smooth: true
MouseArea {
anchors.fill: parent
onClicked: {
offLineMode = !offLineMode;
}
}
}*/
}

View file

@ -76,6 +76,8 @@ void CacheServer::handle(QHttpRequest *req, QHttpResponse *resp)
data = tc->fromUnicode(content);
}
//qDebug() << data;
resp->setHeader("Content-Length", QString::number(data.size()));
resp->setHeader("Content-Type", item.contentType);
resp->writeHead(200);
@ -106,22 +108,45 @@ bool CacheServer::readFile(const QString &filename, QByteArray &data)
void CacheServer::filter(QString &content)
{
QRegExp rxImg("(<img\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
//QRegExp rxCss("<link\\s[^>]*rel\\s*=(\"stylesheet\"|'stylesheet')[^>]*href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxCss("(<link\\s[^>]*rel\\s*=(\"stylesheet\"|'stylesheet')[^>]*)href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
//QRegExp rxImg("(<img\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxImgAll("<img[^>]*>", Qt::CaseInsensitive);
QRegExp rxLinkAll("<link[^>]*>", Qt::CaseInsensitive);
QRegExp rxFormAll("<form[^>]*>((?!<\\/form>).)*<\\/form>", Qt::CaseInsensitive);
QRegExp rxInputAll("<input[^>]*>", Qt::CaseInsensitive);
//QRegExp rxMetaAll("<meta[^>]*>", Qt::CaseInsensitive);
QRegExp rxMetaViewport("<meta\\s[^>]*name\\s*=(\"viewport\"|'viewport')[^>]*>", Qt::CaseInsensitive);
//QRegExp rxCss("(<link\\s[^>]*rel\\s*=(\"stylesheet\"|'stylesheet')[^>]*)href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxScript("(<script\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxFrame("(<iframe\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxA("(<a\\s[^>]*)href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxUrl("url[\\s]*\\([^\\)]*\\)", Qt::CaseInsensitive);
QRegExp rxScriptAll("<script[^>]*>((?!<\\/script>).)*<\\/script>", Qt::CaseInsensitive);
QRegExp rxStyleAll("<style[^>]*>((?!<\\/style>).)*<\\/style>", Qt::CaseInsensitive);
QRegExp rxStyle("\\s*style\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxClass("\\s*class\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxWidth("\\s*width\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxHeight("\\s*height\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxHeadEnd("</head>", Qt::CaseInsensitive);
content = content.replace(rxImg,"\\1");
//content = content.replace(rxImg,"\\1");
content = content.replace(rxImgAll,"");
content = content.replace(rxLinkAll,"");
content = content.replace(rxScript,"\\1");
content = content.replace(rxScriptAll,"");
content = content.replace(rxFormAll,"");
content = content.replace(rxInputAll,"");
//content = content.replace(rxMetaAll,"");
content = content.replace(rxMetaViewport,"");
content = content.replace(rxStyle,"");
content = content.replace(rxClass,"");
content = content.replace(rxWidth,"");
content = content.replace(rxHeight,"");
content = content.replace(rxStyleAll,"");
content = content.replace(rxFrame,"\\1");
content = content.replace(rxA,"\\1");
content = content.replace(rxUrl,"http://0.0.0.0");
content = content.replace(rxCss,"\\1");
//content = content.replace(rxCss,"\\1");
content = content.replace(rxHeadEnd,"<meta name='viewport' content='width=540px'><style>body{background:#000;color:#FFF;font-size:25px;}</style></head>");
// Change CSS link
/*

View file

@ -618,6 +618,23 @@ bool DatabaseManager::updateFeedReadlaterFlag(const QString &feedId, int readlat
return ret;
}
DatabaseManager::Dashboard DatabaseManager::readDashboard(const QString &dashboardId)
{
Dashboard d;
if (_db.isOpen()) {
QSqlQuery query(QString("SELECT id, name, title, description FROM dashboards WHERE id='%1';").arg(dashboardId),_db);
while(query.next()) {
d.id = query.value(0).toString();
d.name = query.value(1).toString();
d.title = QString(QByteArray::fromBase64(query.value(2).toByteArray()));
d.description = QString(QByteArray::fromBase64(query.value(3).toByteArray()));
}
} else {
qWarning() << "DB is not open!";
}
return d;
}
QList<DatabaseManager::Dashboard> DatabaseManager::readDashboards()
{

View file

@ -121,6 +121,7 @@ public:
bool updateEntryCache(const QString &entryId, int cacheDate, int flag = 1);
bool writeAction(const Action &action, int date);
Dashboard readDashboard(const QString &dashboardId);
QList<Dashboard> readDashboards();
bool isDashborardExists();
QList<Tab> readTabs(const QString &dashboardId);

View file

@ -393,11 +393,18 @@ void DownloadManager::startFeedDownload()
}
cleanCache();
replyToCachedItemMap.clear();
replyToCheckerMap.clear();
QMap<QString,QString> list = db->readNotCachedEntries();
qDebug() << "startFeedDownload, list.count=" << list.count();
if (list.count() == 0) {
emit ready();
return;
}
replyToCachedItemMap.clear();
replyToCheckerMap.clear();
QMap<QString,QString>::iterator i = list.begin();
while (i != list.end()) {

View file

@ -55,7 +55,9 @@ void EntryModel::createItems(const QString &feedId)
doc.setHtml((*i).title);
QString title = doc.toPlainText()
.replace(QChar::ObjectReplacementCharacter,QChar::Space)
.simplified().left(200);
.simplified();
if (title.length()>200)
title = title.left(197)+QString("...");
appendRow(new EntryItem((*i).id,
title,

View file

@ -707,7 +707,6 @@ void NetvibesFetcher::cleanNewFeeds()
i = _feedList.erase(i);
}
}
}
void NetvibesFetcher::cleanRemovedFeeds()

View file

@ -157,6 +157,13 @@ QList<QString> Utils::dashboards()
return simpleList;
}
QString Utils::defaultDashboardName()
{
Settings *s = Settings::instance();
DatabaseManager::Dashboard d = _db->readDashboard(s->getNetvibesDefaultDashboard());
return d.title;
}
/*void Utils::setAsRead(const QString &entryId)
{
_db->updateEntryReadFlag(entryId,1);

View file

@ -36,6 +36,7 @@
#include "feedmodel.h"
#include "entrymodel.h"
#include "databasemanager.h"
#include "settings.h"
class Utils : public QObject
{
@ -49,6 +50,7 @@ public:
Q_INVOKABLE void setDashboardModel();
Q_INVOKABLE QList<QString> dashboards();
Q_INVOKABLE void copyToClipboard(const QString &text);
Q_INVOKABLE QString defaultDashboardName();
/*Q_INVOKABLE void setAsRead(const QString &entryId);
Q_INVOKABLE void unsetAsRead(const QString &entryId);