'Viewport' meta tag in offline mode view
This commit is contained in:
parent
115da57336
commit
3a05bd5b29
17 changed files with 233 additions and 84 deletions
100
qml/BusyBar.qml
100
qml/BusyBar.qml
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ Page {
|
|||
model: entryModel
|
||||
|
||||
MainMenu{}
|
||||
//UpMenu {}
|
||||
|
||||
header: PageHeader {
|
||||
title: root.title
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ Page {
|
|||
model: feedModel
|
||||
|
||||
MainMenu{}
|
||||
//UpMenu {}
|
||||
|
||||
header: PageHeader {
|
||||
title: root.title
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ Page {
|
|||
Label {
|
||||
id: dashboard
|
||||
color: Theme.highlightColor
|
||||
text: settings.getNetvibesDefaultDashboard()
|
||||
text: utils.defaultDashboardName()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
53
qml/UpMenu.qml
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -115,12 +115,12 @@ Page {
|
|||
}
|
||||
}
|
||||
|
||||
PushUpMenu {
|
||||
/*PushUpMenu {
|
||||
MenuItem {
|
||||
text: qsTr("Top")
|
||||
onClicked: view.scrollToTop()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
BusyBar {
|
||||
|
|
|
|||
62
qml/main.qml
62
qml/main.qml
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -707,7 +707,6 @@ void NetvibesFetcher::cleanNewFeeds()
|
|||
i = _feedList.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NetvibesFetcher::cleanRemovedFeeds()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue