Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Feature/joonne/data storage #37

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
6 changes: 4 additions & 2 deletions harbour-nayttamo.pro
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ TARGET = harbour-nayttamo
CONFIG += sailfishapp libcrypto

SOURCES += src/harbour-nayttamo.cpp \
src/urldecrypt.cpp
src/urldecrypt.cpp \
src/serializer.cpp

OTHER_FILES += \
qml/cover/CoverPage.qml \
Expand Down Expand Up @@ -73,6 +74,7 @@ REQUIRED = $$find(DEFINES, "APP_ID") $$find(DEFINES, "APP_KEY") $$find(DEFINES,
}

HEADERS += \
src/urldecrypt.h
src/urldecrypt.h \
src/serializer.h

unix: PKGCONFIG += libcrypto
45 changes: 44 additions & 1 deletion qml/main.qml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import QtQuick 2.2
import Sailfish.Silica 1.0
import QtMultimedia 5.5

import "pages"

ApplicationWindow
Expand All @@ -11,6 +12,49 @@ ApplicationWindow
property string coverTitle: ""
property string coverSubTitle: ""

property var state: null

onStateChanged: {
if (state === null) {
console.log('initialization, do not set the state')
return
}
serializer && serializer.setState(state)
}

Component.onCompleted: {
state = serializer.getState()
}

function setState(path, value) {
function setStateRecursive(obj, path, value) {
if (!Array.isArray(path)) {
path = path.split('.')
}

if (path.length === 1) {
obj[path[0]] = value
return
}

if (!obj[path[0]]) {
obj[path[0]] = {}
}

return setStateRecursive(obj[path[0]], path.slice(1), value)
}

var newState = JSON.parse(JSON.stringify(state))
console.log('start', JSON.stringify(newState))
setStateRecursive(newState, path, value)
console.log("done", JSON.stringify(newState))
state = newState
}

function insertStartedProgram(program) {
setState('startedPrograms.' + program.id, program.progress)
}

function updateCover(newCoverMode, newCoverTitle, newCoverSubtitle) {
coverMode = newCoverMode ? newCoverMode : ""
coverTitle = newCoverTitle ? newCoverTitle : ""
Expand All @@ -25,4 +69,3 @@ ApplicationWindow
cover: Qt.resolvedUrl("cover/CoverPage.qml")
allowedOrientations: defaultAllowedOrientations
}

9 changes: 9 additions & 0 deletions qml/pages/PlayerPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ Page {
if (visible) updateCover(qsTr("Now playing"), program.title, program.itemTitle)
}

Component.onDestruction: {
appWindow.insertStartedProgram({ id: program.id, progress: mediaPlayer.position })
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check if this is called upon closing the app by a swipe and make sure this is called also when pause button is pressed in case the handle isn't called upon closing the app forcefully

}

function initialize() {
YleApi.getMediaUrl(program.id, program.mediaId)
.then(function(response) {
Expand All @@ -41,6 +45,7 @@ Page {
subtitlesText.getSubtitles(subtitlesUrl)
}
mediaPlayer.source = response.url
if (appWindow.state.startedPrograms[program.id]) mediaPlayer.seek(appWindow.state.startedPrograms[program.id])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could be more readable if this had curly brackets and function call inside those or at least an empty line after this because otherwise it's possible to read that the if affects the next line. Also the line is quite long now.

mediaPlayer.play()
YleApi.reportUsage(program.id, program.mediaId)
})
Expand Down Expand Up @@ -122,6 +127,10 @@ Page {
if (subtitlesUrl && subtitlesText) {
subtitlesText.getSubtitles(subtitlesUrl)
}

if (mediaPlayer.playbackState === MediaPlayer.PausedState) {
appWindow.insertStartedProgram({ id: program.id, progress: mediaPlayer.position })
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/harbour-nayttamo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include <sailfishapp.h>
#include "urldecrypt.h"
#include "serializer.h"

int main(int argc, char *argv[])
{
Expand All @@ -55,6 +56,15 @@ int main(int argc, char *argv[])

view->rootContext()->setContextProperty("urlDecrypt", &urlDecrypt);

auto worker = new QThread;

QScopedPointer<Serializer> serializer(new Serializer);
view->rootContext()->setContextProperty("serializer", serializer.data());
serializer->moveToThread(worker);

QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
worker->start();

view->engine()->addImportPath(SailfishApp::pathTo("qml/components").toString());
view->setSource(SailfishApp::pathTo("qml/main.qml"));

Expand Down
84 changes: 84 additions & 0 deletions src/serializer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include "serializer.h"

#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QTextStream>
#include <QStandardPaths>
#include <QDir>
#include <QDebug>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make the include list alphabetically ordered.


Serializer::Serializer(QObject *parent) : QObject(parent)
{
this->ensureDir();
this->readState();
}

Serializer::~Serializer()
{
this->writeState();
}

QJsonObject Serializer::getInitialState() const
{
return QJsonObject
{
{"startedPrograms", QJsonObject()}
};
}

bool Serializer::readState()
{
QFile file(this->getPath());

if (!file.open(QIODevice::ReadWrite))
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move curly bracket to same line with if which is the style used in other files. Same for other if statements in the new code.

return false;
}

auto json = (QJsonDocument::fromJson(file.readAll())).object();

this->m_state = json.empty() ? this->getInitialState() : json;

return true;
}

bool Serializer::writeState() const
{
QFile file(this->getPath());

if (!file.open(QIODevice::ReadWrite))
{
return false;
}

QJsonDocument saveDoc(m_state);
file.write(saveDoc.toJson());

return true;
}

void Serializer::setState(QJsonObject state)
{
m_state = state;
}

QJsonObject Serializer::getState()
{
return m_state;
}

void Serializer::ensureDir() const
{
QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));

if (!dir.exists())
{
dir.mkpath(".");
}
}

QString Serializer::getPath() const
{
return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QDir::separator() + "state.json";
}
29 changes: 29 additions & 0 deletions src/serializer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef SERIALIZER_H
#define SERIALIZER_H

#include <QObject>
#include <QJsonObject>

class Serializer : public QObject
{
Q_OBJECT
public:
explicit Serializer(QObject *parent = 0);
~Serializer();

Q_INVOKABLE void setState(QJsonObject state);
Q_INVOKABLE QJsonObject getState();

signals:
public slots:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to have the empty signals and public slots defined here?

private:
bool readState();
bool writeState() const;
QString getPath() const;
void ensureDir() const;
QJsonObject getInitialState() const;

QJsonObject m_state;
};

#endif // SERIALIZER_H