]> git.sur5r.net Git - minitube/blob - src/ytjs/ytjs.h
New upstream version 3.6.1
[minitube] / src / ytjs / ytjs.h
1 #ifndef YTJS_H
2 #define YTJS_H
3
4 #include <QJSEngine>
5 #include <QQmlEngine>
6 #include <QtCore>
7
8 class Http;
9
10 class JsTimer : public QTimer {
11     Q_OBJECT
12
13 public:
14     static auto &getTimers() {
15         static QHash<QString, JsTimer *> timers;
16         return timers;
17     }
18     // This should be static but cannot bind static functions to QJSEngine
19     Q_INVOKABLE QJSValue clearTimeout(QJSValue id) {
20         // qDebug() << id.toString();
21         auto timer = getTimers().take(id.toString());
22         if (timer) {
23             timer->stop();
24             timer->deleteLater();
25         }
26         return QJSValue();
27     }
28     // This should be static but cannot bind static functions to QJSEngine
29     Q_INVOKABLE QJSValue setTimeout(QJSValue callback, QJSValue delayTime) {
30         // qDebug() << callback.toString() << delayTime.toInt();
31         auto timer = new JsTimer();
32         timer->setInterval(delayTime.toInt());
33         connect(timer, &JsTimer::timeout, this, [callback]() mutable {
34             // qDebug() << "Calling" << callback.toString();
35             auto value = callback.call();
36             if (value.isError()) {
37                 qWarning() << "Error" << value.toString();
38                 qDebug() << value.property("stack").toString().splitRef('\n');
39             }
40         });
41         timer->start();
42         return timer->hashString();
43     }
44
45     Q_INVOKABLE JsTimer(QObject *parent = nullptr) : QTimer(parent) {
46         setTimerType(Qt::VeryCoarseTimer);
47         setSingleShot(true);
48         connect(this, &JsTimer::destroyed, this, [this] { getTimers().remove(hashString()); });
49         connect(this, &JsTimer::timeout, this, &QTimer::deleteLater);
50         getTimers().insert(hashString(), this);
51     }
52
53     QString hashString() { return QString::number((std::uintptr_t)(this)); }
54
55 private:
56 };
57
58 class ResultHandler : public QObject {
59     Q_OBJECT
60
61 public:
62     Q_INVOKABLE QJSValue setData(QJSValue value) {
63         qDebug() << "Success" << value.toString();
64         auto doc = QJsonDocument::fromVariant(value.toVariant());
65         if (doc.isEmpty()) {
66             qDebug() << value.toString();
67             emit error("Cannot parse JSON");
68             return QJSValue();
69         }
70         emit data(doc);
71         return QJSValue();
72     }
73
74     Q_INVOKABLE QJSValue setError(QJSValue value) {
75         QString message = value.toString();
76         qWarning() << "Error" << message;
77         qDebug() << value.property("stack").toString().splitRef('\n');
78         emit error(message);
79         return QJSValue();
80     }
81
82 signals:
83     void data(const QJsonDocument &doc);
84     void error(const QString &message);
85 };
86
87 class YTJS : public QObject {
88     Q_OBJECT
89
90 public:
91     static YTJS &instance();
92     static Http &http();
93     static Http &cachedHttp();
94
95     explicit YTJS(QObject *parent = nullptr);
96     bool checkError(const QJSValue &value);
97
98     bool isInitialized();
99     QQmlEngine &getEngine() { return *engine; }
100
101 signals:
102     void initialized();
103     void initFailed(QString message);
104
105 private:
106     void initialize();
107     QJSValue evaluate(const QString &js);
108
109     // QQmlEngine gives us XMLHttpRequest, console, JSON
110     QQmlEngine *engine;
111     bool initializing = false;
112     bool ready = false;
113 };
114
115 #endif // YTJS_H