diff --git a/config/ba.dysko.harbour.tooter.service b/config/ba.dysko.harbour.tooter.service new file mode 100644 index 0000000..c39dfae --- /dev/null +++ b/config/ba.dysko.harbour.tooter.service @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=ba.dysko.harbour.tooter +Exec=/usr/bin/invoker --type=silica-qt5 --desktop-file=harbour-tooter.desktop -s -n /usr/bin/harbour-tooter \ No newline at end of file diff --git a/config/ba.dysko.harbour.tooter.xml b/config/ba.dysko.harbour.tooter.xml new file mode 100644 index 0000000..23c7ab5 --- /dev/null +++ b/config/ba.dysko.harbour.tooter.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/config/icon-lock-harbour-tooter.png b/config/icon-lock-harbour-tooter.png new file mode 100644 index 0000000..0ad7dfd Binary files /dev/null and b/config/icon-lock-harbour-tooter.png differ diff --git a/config/x-harbour.tooter.activity.conf b/config/x-harbour.tooter.activity.conf new file mode 100644 index 0000000..a4c6442 --- /dev/null +++ b/config/x-harbour.tooter.activity.conf @@ -0,0 +1,5 @@ +appIcon=/usr/share/harbour-tooter/config/icon-lock-harbour-tooter.png +x-nemo-icon=/usr/share/harbour-tooter/config/icon-lock-harbour-tooter.png +x-nemo-priority=120 +x-nemo-feedback=sms_exists +x-nemo-led-disabled-without-body-and-summary=false diff --git a/harbour-tooter.pro b/harbour-tooter.pro index 85000db..642573c 100644 --- a/harbour-tooter.pro +++ b/harbour-tooter.pro @@ -13,13 +13,36 @@ TARGET = harbour-tooter QT += network dbus sql +CONFIG += sailfishapp link_pkgconfig +PKGCONFIG += sailfishapp nemonotifications-qt5 Qt5SystemInfo + +DEFINES += "APPVERSION=\\\"$${SPECVERSION}\\\"" +DEFINES += "APPNAME=\\\"$${TARGET}\\\"" + +!exists( src/dbusAdaptor.h ) { + system(qdbusxml2cpp config/ba.dysko.harbour.tooter.xml -i dbus.h -a src/dbusAdaptor) +} + +config.path = /usr/share/$${TARGET}/config/ +config.files = config/icon-lock-harbour-maira.png + +notification_categories.path = /usr/share/lipstick/notificationcategories +notification_categories.files = config/x-harbour.maira.activity.* + +dbus_services.path = /usr/share/dbus-1/services/ +dbus_services.files = config/ba.dysko.harbour.tooter.service + +interfaces.path = /usr/share/dbus-1/interfaces/ +interfaces.files = config/ba.dysko.harbour.tooter.xml -CONFIG += sailfishapp SOURCES += src/harbour-tooter.cpp \ - src/imageuploader.cpp + src/imageuploader.cpp \ + src/dbusAdaptor.cpp \ + src/dbus.cpp OTHER_FILES += qml/harbour-tooter.qml \ + config/* \ qml/cover/CoverPage.qml \ qml/pages/MainPage.qml \ qml/pages/LoginPage.qml \ @@ -73,7 +96,11 @@ DISTFILES += \ qml/pages/Settings.qml \ qml/pages/components/MediaBlock.qml \ qml/pages/components/MyImage.qml \ - qml/pages/components/ImageFullScreen.qml + qml/pages/components/ImageFullScreen.qml \ + config/icon-lock-harbour-tooter.png \ + config/x-harbour.tooter.activity.conf HEADERS += \ - src/imageuploader.h + src/imageuploader.h \ + src/dbusAdaptor.h \ + src/dbus.h diff --git a/harbour-tooter.pro.user b/harbour-tooter.pro.user index 970a98d..f3e58ca 100644 --- a/harbour-tooter.pro.user +++ b/harbour-tooter.pro.user @@ -1,14 +1,14 @@ - + EnvironmentId - {25497605-1bff-4134-a878-76c1475dd8e3} + {41ec03ca-9430-48f3-b421-990d428b2838} ProjectExplorer.Project.ActiveTarget - 0 + 1 ProjectExplorer.Project.EditorSettings @@ -59,18 +59,18 @@ ProjectExplorer.Project.Target.0 - MerSDK-SailfishOS-i486 - MerSDK-SailfishOS-i486 - {f49c1b5a-d715-401a-9a10-0e5fe9e5b72a} + SailfishOS-i486 (in Sailfish OS Build Engine) + SailfishOS-i486 (in Sailfish OS Build Engine) + {2b6dd414-d640-472a-9475-472ab2c5e22e} 0 - 2 + 0 0 - C:/Users/dysko/SF/build-harbour-tooter-MerSDK_SailfishOS_i486-Debug + /Users/dysko/GIT/build-harbour-tooter-SailfishOS_i486_in_Sailfish_OS_Build_Engine-Debug true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -106,7 +106,7 @@ true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -138,11 +138,11 @@ true - C:/Users/dysko/SF/build-harbour-tooter-MerSDK_SailfishOS_i486-Release + /Users/dysko/GIT/build-harbour-tooter-SailfishOS_i486_in_Sailfish_OS_Build_Engine-Release true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -178,7 +178,7 @@ true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -210,11 +210,11 @@ true - C:/Users/dysko/SF/build-harbour-tooter-MerSDK_SailfishOS_i486-Profile + /Users/dysko/GIT/build-harbour-tooter-SailfishOS_i486_in_Sailfish_OS_Build_Engine-Profile true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -250,7 +250,7 @@ true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -396,7 +396,7 @@ 13 14 - C:/Users/dysko/SF/harbour-tooter + /Users/dysko/GIT/harbour-tooter false 10234 3 @@ -424,18 +424,18 @@ ProjectExplorer.Project.Target.1 - MerSDK-SailfishOS-armv7hl - MerSDK-SailfishOS-armv7hl - {588087e2-ecc1-41aa-b652-86f16cba9351} + SailfishOS-armv7hl (in Sailfish OS Build Engine) + SailfishOS-armv7hl (in Sailfish OS Build Engine) + {e475a8ea-d9f2-4d35-b4f0-1f1076cd8d23} 0 2 0 - C:/Users/dysko/SF/build-harbour-tooter-MerSDK_SailfishOS_armv7hl-Debug + /Users/dysko/GIT/build-harbour-tooter-SailfishOS_armv7hl_in_Sailfish_OS_Build_Engine-Debug true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -471,7 +471,7 @@ true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -503,11 +503,11 @@ true - C:/Users/dysko/SF/build-harbour-tooter-MerSDK_SailfishOS_armv7hl-Release + /Users/dysko/GIT/build-harbour-tooter-SailfishOS_armv7hl_in_Sailfish_OS_Build_Engine-Release true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -543,7 +543,7 @@ true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -575,11 +575,11 @@ true - C:/Users/dysko/SF/build-harbour-tooter-MerSDK_SailfishOS_armv7hl-Profile + /Users/dysko/GIT/build-harbour-tooter-SailfishOS_armv7hl_in_Sailfish_OS_Build_Engine-Profile true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -615,7 +615,7 @@ true - Start SDK + Start Build Engine Mer.MerSdkStartStep @@ -761,7 +761,7 @@ 13 14 - C:/Users/dysko/SF/harbour-tooter + /Users/dysko/GIT/harbour-tooter false 10234 3 diff --git a/qml/harbour-tooter.qml b/qml/harbour-tooter.qml index f076e09..8af68cc 100644 --- a/qml/harbour-tooter.qml +++ b/qml/harbour-tooter.qml @@ -67,5 +67,20 @@ ApplicationWindow Component.onDestruction: { Logic.saveData() } + Connections + { + target: Dbus + onViewtoot: + { + console.log(key, "dbus show issue") + + } + onActivateapp: + { + console.log ("dbus activate app") + pageStack.pop(pageStack.find( function(page){ return (page._depth === 0) })) + activate() + } + } } diff --git a/qml/lib/API.js b/qml/lib/API.js index 3b8d784..47cbc02 100644 --- a/qml/lib/API.js +++ b/qml/lib/API.js @@ -116,14 +116,15 @@ var notificationGenerator = function(item){ var notification; switch (item.urgency){ case "normal": - notification = Qt.createQmlObject('import org.nemomobile.notifications 1.0; Notification { category: "x-nemo.example"; urgency: Notification.Normal; }', Qt.application, 'InternalQmlObject'); + notification = Qt.createQmlObject('import org.nemomobile.notifications 1.0; Notification { appName: "Tooter"; itemCount: 1; category: "x-harbour.tooter.activity"; urgency: Notification.Normal; }', Qt.application, 'InternalQmlObject'); break; case "critical": - notification = Qt.createQmlObject('import org.nemomobile.notifications 1.0; Notification { category: "x-nemo.example"; urgency: Notification.Critical; }', Qt.application, 'InternalQmlObject'); + notification = Qt.createQmlObject('import org.nemomobile.notifications 1.0; Notification { appName: "Tooter"; itemCount: 1; category: "x-harbour.tooter.activity"; urgency: Notification.Critical; remoteActions: [ { "name": "default", "displayName": "Do something", "icon": "icon-s-do-it", "service": "org.nemomobile.example", "path": "/example", "iface": "org.nemomobile.example", "method": "doSomething", "arguments": [ "argument", 1 ] },{ "name": "ignore", "displayName": "Ignore the problem", "icon": "icon-s-ignore", "service": "org.nemomobile.example", "path": "/example", "iface": "org.nemomobile.example", "method": "ignore", "arguments": [ "argument", 1 ] } ]; onClicked: console.log("Clicked"); onClosed: console.log("Closed, reason: " + reason); }', Qt.application, 'InternalQmlObject'); break; default: - notification = Qt.createQmlObject('import org.nemomobile.notifications 1.0; Notification { category: "x-nemo.example"; urgency: Notification.Low; }', Qt.application, 'InternalQmlObject'); + notification = Qt.createQmlObject('import org.nemomobile.notifications 1.0; Notification { appName: "Tooter"; itemCount: 1; category: "x-harbour.tooter.activity"; urgency: Notification.Low; }', Qt.application, 'InternalQmlObject'); } + notification.remoteActions = [ { "name": "app", "displayName": "Do something", "icon": "icon-s-do-it", "service": "ba.dysko.harbour.tooter", "path": "/", "iface": "ba.dysko.harbour.tooter", "method": "openapp", "arguments": [ ]}] notification.timestamp = item.timestamp notification.summary = item.summary diff --git a/qml/pages/components/ImageFullScreen.qml b/qml/pages/components/ImageFullScreen.qml index 05d7a79..372cd85 100644 --- a/qml/pages/components/ImageFullScreen.qml +++ b/qml/pages/components/ImageFullScreen.qml @@ -41,14 +41,30 @@ Page { videoError.visible = true; } onStatusChanged: { + console.log(status) switch (status){ - case MediaPlayer.Buffering: - return; - case MediaPlayer.Loading: - playerIcon.visible = false; - return; - default: - return; + case MediaPlayer.Loading: + console.log("loading") + return; + case MediaPlayer.EndOfMedia: + console.log("EndOfMedia") + return; + + } + } + + onPlaybackStateChanged: { + console.log(playbackState) + switch (playbackState){ + case MediaPlayer.PlayingState: + playerIcon.icon.source = "image://theme/icon-m-play" + return; + case MediaPlayer.PausedState: + playerIcon.icon.source = "image://theme/icon-m-pause" + return; + case MediaPlayer.StoppedState: + playerIcon.icon.source = "image://theme/icon-m-stop" + return; } } @@ -70,35 +86,53 @@ Page { //console.log(duration) //console.log(bufferProgress) //console.log(position) - progressRec.width = parent.width * position/duration + if (status !== MediaPlayer.Loading){ + playerProgress.indeterminate = false + playerProgress.maximumValue = duration + playerProgress.minimumValue = 0 + playerProgress.value = position + } + } onStopped: function(){ play() } IconButton { id: playerIcon - anchors.centerIn: parent - icon.source: "image://theme/icon-l-play" + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.leftMargin: Theme.paddingLarge + anchors.bottomMargin: Theme.paddingMedium + icon.source: "image://theme/icon-m-play" onClicked: function() { - visible = false; - video.play() + if (video.playbackState === MediaPlayer.PlayingState) + video.pause() + else + video.play() } } + + ProgressBar { + indeterminate: true + id: playerProgress + anchors.left: playerIcon.right + anchors.right: parent.right + + anchors.verticalCenter: playerIcon.verticalCenter + anchors.leftMargin: 0 + anchors.bottomMargin: Theme.paddingMedium + } + MouseArea { anchors.fill: parent onClicked: function() { - playerIcon.visible = true; - video.stop() + if (video.playbackState === MediaPlayer.PlayingState) + video.pause() + else + video.play() } } } - Rectangle { - id: progressRec - anchors.bottom: parent.bottom - width: 0 - height: Theme.paddingSmall - color: Theme.highlightBackgroundColor - } } Flickable { diff --git a/qml/pages/components/MyList.qml b/qml/pages/components/MyList.qml index b6b9497..51b15d7 100644 --- a/qml/pages/components/MyList.qml +++ b/qml/pages/components/MyList.qml @@ -3,6 +3,7 @@ import Sailfish.Silica 1.0 import "../../lib/API.js" as Logic import "." +import org.nemomobile.notifications 1.0; SilicaListView { id: myList @@ -61,15 +62,31 @@ SilicaListView { text: "NOTIFIKACIJA" onClicked: { Logic.notifier({ - type: "favourite", + type: "follow", urgency: "critical", created_at: new Date(), + account_display_name: '@muo', reblog_account_display_name: "@akakakak", content: "blaaaaaa blaaaaaablaaaaaablaaaaaa" }) } } + MenuItem { + text: "NOTIFIKACIJA2" + onClicked: { + + Logic.notifier({ + type: "reblog", + urgency: "critical", + created_at: new Date(), + account_display_name: '@muowww', + reblog_account_display_name: "@akakwwakak", + content: "blaaaaaa blaaaaawwwablaaaaaablaaaaaa" + + }) + } + } MenuItem { text: qsTr("Settings") onClicked: { @@ -119,6 +136,34 @@ SilicaListView { console.log("CountChanged!")*/ } + Button { + Notification { + id: notification + category: "x-harbour.tooter.activity" + appName: "Tooter" + appIcon: "/usr/share/harbour-tooter/config/icon-lock-harbour-tooter.png" + summary: "Notification summary" + body: "Notification body" + previewSummary: "Notification preview summary" + previewBody: "Notification preview body" + itemCount: 5 + timestamp: "2013-02-20 18:21:00" + remoteActions: [ { + "name": "default", + "displayName": "Do something", + "icon": "icon-s-certificates", + "service": "ba.dysko.harbour.tooter", + "path": "/", + "iface": "ba.dysko.harbour.tooter", + "method": "openapp", + "arguments": [ ] + }] + onClicked: console.log("Clicked") + onClosed: console.log("Closed, reason: " + reason) + } + text: "Application notification" + (notification.replacesId ? " ID:" + notification.replacesId : "") + onClicked: notification.publish() + } footer: Item{ width: parent.width height: Theme.itemSizeLarge @@ -129,7 +174,7 @@ SilicaListView { visible: false onClicked: { loadData("append") - } + } } BusyIndicator { size: BusyIndicatorSize.Small diff --git a/src/dbus.cpp b/src/dbus.cpp new file mode 100644 index 0000000..e221b9b --- /dev/null +++ b/src/dbus.cpp @@ -0,0 +1,52 @@ +#include "dbus.h" + +static const char *PATH = "/"; +static const char *SERVICE = SERVICE_NAME; + +Dbus::Dbus(QObject *parent) : + QObject(parent) +{ + m_dbusRegistered = false; + new TooterAdaptor(this); + registerDBus(); +} + +Dbus::~Dbus() +{ + if (m_dbusRegistered) + { + QDBusConnection connection = QDBusConnection::sessionBus(); + connection.unregisterObject(PATH); + connection.unregisterService(SERVICE); + } +} + +void Dbus::registerDBus() +{ + if (!m_dbusRegistered) + { + QDBusConnection connection = QDBusConnection::sessionBus(); + if (!connection.registerService(SERVICE)) + { + QCoreApplication::quit(); + return; + } + + if (!connection.registerObject(PATH, this)) + { + QCoreApplication::quit(); + return; + } + m_dbusRegistered = true; + } +} + +void Dbus::showtoot(const QStringList &key) +{ + emit viewtoot(key.at(0)); +} + +void Dbus::openapp() +{ + emit activateapp(); +} diff --git a/src/dbus.h b/src/dbus.h new file mode 100644 index 0000000..4bb863b --- /dev/null +++ b/src/dbus.h @@ -0,0 +1,33 @@ +#ifndef DBUS_H +#define DBUS_H + +#include +#include +#include "dbusAdaptor.h" + +#define SERVICE_NAME "ba.dysko.harbour.tooter" + +class QDBusInterface; +class Dbus : public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", SERVICE_NAME) + +public: + explicit Dbus(QObject *parent = 0); + ~Dbus(); + void registerDBus(); + +public Q_SLOTS: + Q_NOREPLY void showtoot(const QStringList &key); + Q_NOREPLY void openapp(); + +signals: + void viewtoot(QString key); + void activateapp(); + +private: + bool m_dbusRegistered; +}; + +#endif // DBUS_H diff --git a/src/dbusAdaptor.cpp b/src/dbusAdaptor.cpp new file mode 100644 index 0000000..d607136 --- /dev/null +++ b/src/dbusAdaptor.cpp @@ -0,0 +1,47 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp config/com.kimmoli.harbour.maira.xml -i dbus.h -a src/dbusAdaptor + * + * qdbusxml2cpp is Copyright (C) 2016 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "src/dbusAdaptor.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class TooterAdaptor + */ + +TooterAdaptor::TooterAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +TooterAdaptor::~TooterAdaptor() +{ + // destructor +} + +void TooterAdaptor::openapp() +{ + // handle method call ba.dysko.harbour.tooter.openapp + QMetaObject::invokeMethod(parent(), "openapp"); +} + +void TooterAdaptor::showtoot(const QStringList &key) +{ + // handle method call ba.dysko.harbour.tooter.showtoot + QMetaObject::invokeMethod(parent(), "showtoot", Q_ARG(QStringList, key)); +} + diff --git a/src/dbusAdaptor.h b/src/dbusAdaptor.h new file mode 100644 index 0000000..c65d635 --- /dev/null +++ b/src/dbusAdaptor.h @@ -0,0 +1,54 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp config/com.kimmoli.harbour.maira.xml -i dbus.h -a src/dbusAdaptor + * + * qdbusxml2cpp is Copyright (C) 2016 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef DBUSADAPTOR_H +#define DBUSADAPTOR_H + +#include +#include +#include "dbus.h" +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface com.kimmoli.harbour.maira + */ +class TooterAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "ba.dysko.harbour.tooter") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + TooterAdaptor(QObject *parent); + virtual ~TooterAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + void openapp(); + Q_NOREPLY void showtoot(const QStringList &key); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/src/harbour-tooter.cpp b/src/harbour-tooter.cpp index 17d3d2c..74b36ff 100644 --- a/src/harbour-tooter.cpp +++ b/src/harbour-tooter.cpp @@ -8,7 +8,7 @@ #include #include #include "imageuploader.h" - +#include "dbus.h" int main(int argc, char *argv[]) { @@ -21,6 +21,9 @@ int main(int argc, char *argv[]) QQmlEngine* engine = view->engine(); QObject::connect(engine, SIGNAL(quit()), app.data(), SLOT(quit())); + Dbus *dbus = new Dbus(); + view->rootContext()->setContextProperty("Dbus", dbus); + view->setSource(SailfishApp::pathTo("qml/harbour-tooter.qml")); view->show(); return app->exec(); diff --git a/translations/harbour-tooter-de.ts b/translations/harbour-tooter-de.ts index fe77649..0d40b2d 100644 --- a/translations/harbour-tooter-de.ts +++ b/translations/harbour-tooter-de.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-el.ts b/translations/harbour-tooter-el.ts index 544825a..3568d62 100644 --- a/translations/harbour-tooter-el.ts +++ b/translations/harbour-tooter-el.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-en.ts b/translations/harbour-tooter-en.ts index 937c8e7..0ea6d27 100644 --- a/translations/harbour-tooter-en.ts +++ b/translations/harbour-tooter-en.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-es.ts b/translations/harbour-tooter-es.ts index c2aa5e2..56dfe3b 100644 --- a/translations/harbour-tooter-es.ts +++ b/translations/harbour-tooter-es.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-fr.ts b/translations/harbour-tooter-fr.ts index 47f359d..c5ddaef 100644 --- a/translations/harbour-tooter-fr.ts +++ b/translations/harbour-tooter-fr.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-nl.ts b/translations/harbour-tooter-nl.ts index 64c067f..2db675e 100644 --- a/translations/harbour-tooter-nl.ts +++ b/translations/harbour-tooter-nl.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-oc.ts b/translations/harbour-tooter-oc.ts index ca0a76c..107edd9 100644 --- a/translations/harbour-tooter-oc.ts +++ b/translations/harbour-tooter-oc.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter-sr.ts b/translations/harbour-tooter-sr.ts index 4485d18..aa513ae 100644 --- a/translations/harbour-tooter-sr.ts +++ b/translations/harbour-tooter-sr.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading diff --git a/translations/harbour-tooter.ts b/translations/harbour-tooter.ts index 7569f9e..61df02f 100644 --- a/translations/harbour-tooter.ts +++ b/translations/harbour-tooter.ts @@ -81,7 +81,7 @@ ImageFullScreen - Error loading image + Error loading