Merge pull request #3 from molan-git/master

Update from molan repository
This commit is contained in:
Carmen F. B 2020-07-12 17:01:15 +02:00 committed by GitHub
commit d978cab096
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 6056 additions and 4446 deletions

2
.gitignore vendored
View file

@ -1,2 +1,2 @@
*.user
README.md

View file

@ -1,22 +1,23 @@
# Tooter [Fork]
# Tooter β <img width="50" title="Page Home" src="https://openrepos.net/sites/default/files/styles/thumbnail/public/packages/10743/icon-harbour-tooter.png">
## About
Tooter is Mastodon client for Sailfish OS. It is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication.
Tooter is Mastodon client for [Sailfish OS](https://sailfishos.org).
This fork is being used to further develop and maintain the Tooter app by dysko (https://github.com/dysk0/harbour-tooter). The development branch 'upstream' is being used for merge pull requests to the original repository. Releases by dysko can be found on the Jolla store and on https://openrepos.net/content/dysko/tooter
This fork is being used to further develop and maintain the Tooter app by dysko ([harbour-tooter](https://github.com/dysk0/harbour-tooter)).
Releases from this forked repository (branch 'master') can be found here: https://openrepos.net/content/molan/tooter-v-fork.
* Releases from this repository (Tooter β from release branch *master*) can be found on [OpenRepos.net](https://openrepos.net/content/molan/tooter-v)
* Releases by dysko can be found on the Jolla store and on [OpenRepos.net](https://openrepos.net/content/dysko/tooter)
## Build
Clone / download this repository and import it in your SailfishOS IDE using the harbour-tooter.pro project file. No additional configuration needed.
Clone / download this repository and import it into your SailfishOS IDE using the harbour-tooter.pro project file. No additional configuration needed.
## Repository branches:
- master: default (Beta release version, harbour-tooterb)
- upstream: commits for Tooter release (harbour-tooter)
* master: release branch which includes specifics for harbour-tooterb (Tooter β)
* upstream: main development branch which is used to send changes to the upstream repository (harbour-tooter)
## Contributions
Contributions to this project are very welcome, since there are still many things which can be done for Tooter.
- please fork the upstream branch if you want to contribute to this project.
Contributions to this project are very welcome, since there are still many things which can be done for Tooter. If you already know what you want to add or fix, please make a Pull Request (PR) with your proposal. Your PR should include an explanation or a change log summary. Merging will not be allowed until the PR has been reviewed.
Please fork the [upstream branch](https://github.com/molan-git/harbour-tooter/tree/upstream) if you want to contribute to this project.
## Screenshots
<img width="200" title="Page Home" src="https://telegra.ph/file/710bba46d9f818e0f88ab.png"> <img width="200" title="Page Profile" src="https://telegra.ph/file/c5b504f637c874861eeee.png"> <img width="200" title="Page Conversation" src="https://telegra.ph/file/c9584f8d68c89827c53e5.png">

View file

@ -4,8 +4,3 @@ X-Nemo-Application-Type=silica-qt5
Icon=harbour-tooterb
Exec=harbour-tooterb
Name=Tooter β
# translation example:
# your app name in German locale (de)
#
# Remember to comment out the following line, if you do not want to use
# a different app name in German locale (de).

View file

@ -9,15 +9,14 @@
# - icon definition filename in desktop file must be changed
# - translation filenames have to be changed
# The name of your application
TARGET = harbour-tooterb
CONFIG += sailfishapp
QT += network dbus sql
QT += multimedia
CONFIG += link_pkgconfig
PKGCONFIG += sailfishapp
PKGCONFIG += \
PKGCONFIG += sailfishapp \
nemonotifications-qt5
DEFINES += "APPVERSION=\\\"$${SPECVERSION}\\\""
@ -39,45 +38,44 @@ dbus_services.files = config/ba.dysko.harbour.tooterb.service
interfaces.path = /usr/share/dbus-1/interfaces/
interfaces.files = config/ba.dysko.harbourb.tooterb.xml
SOURCES += src/harbour-tooterb.cpp
SOURCES += src/imageuploader.cpp
SOURCES += src/filedownloader.cpp
SOURCES += src/notifications.cpp
SOURCES += src/dbusAdaptor.cpp
SOURCES += src/dbus.cpp
SOURCES += src/harbour-tooterb.cpp \
src/imageuploader.cpp \
src/filedownloader.cpp \
src/notifications.cpp \
src/dbusAdaptor.cpp \
src/dbus.cpp
HEADERS += src/imageuploader.h
HEADERS += src/filedownloader.h
HEADERS += src/notifications.h
HEADERS += src/dbusAdaptor.h
HEADERS += src/dbus.h
HEADERS += src/imageuploader.h \
src/filedownloader.h \
src/notifications.h \
src/dbusAdaptor.h \
src/dbus.h
DISTFILES += qml/harbour-tooterb.qml \
qml/images/tooterb-cover.svg \
qml/pages/ConversationPage.qml \
qml/pages/ProfilePage.qml \
qml/pages/SettingsPage.qml \
qml/pages/components/InfoBanner.qml \
qml/pages/components/MediaFullScreen.qml \
qml/pages/components/MyMedia.qml \
qml/pages/components/NavigationPanel.qml \
qml/pages/components/ProfileImage.qml \
qml/pages/components/VisualContainer.qml \
qml/pages/components/MiniStatus.qml \
qml/pages/components/MiniHeader.qml \
qml/pages/components/ItemUser.qml \
qml/pages/components/MyList.qml \
qml/pages/components/Navigation.qml \
qml/pages/components/ProfileHeader.qml \
qml/pages/components/MediaBlock.qml \
qml/pages/components/MyImage.qml \
qml/pages/components/ImageFullScreen.qml \
qml/cover/CoverPage.qml \
qml/pages/MainPage.qml \
qml/pages/LoginPage.qml \
qml/pages/Conversation.qml \
qml/pages/components/Toot.qml \
qml/pages/Browser.qml \
qml/pages/Profile.qml \
qml/pages/Settings.qml \
qml/lib/API.js \
qml/images/notification.svg \
qml/images/verified.svg \
qml/images/boosted.svg \
qml/images/tooterb.svg \
qml/images/emojiselect.svg \
qml/images/icon-s-following \
qml/images/icon-s-bookmark \
qml/images/icon-m-emoji.svg \
qml/images/icon-m-profile.svg \
qml/images/icon-l-profile.svg \
qml/lib/Mastodon.js \
@ -97,21 +95,18 @@ SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
# following CONFIG line
CONFIG += sailfishapp_i18n
# German translation is enabled as an example. If you aren't
# planning to localize your app, remember to comment out the
# following TRANSLATIONS line. And also do not forget to
# modify the localized app name in the the .desktop file.
TRANSLATIONS += translations/harbour-tooterb-de.ts
TRANSLATIONS += translations/harbour-tooterb-el.ts
TRANSLATIONS += translations/harbour-tooterb-es.ts
TRANSLATIONS += translations/harbour-tooterb-fi.ts
TRANSLATIONS += translations/harbour-tooterb-fr.ts
TRANSLATIONS += translations/harbour-tooterb-nl.ts
TRANSLATIONS += translations/harbour-tooterb-nl_BE.ts
TRANSLATIONS += translations/harbour-tooterb-oc.ts
TRANSLATIONS += translations/harbour-tooterb-pl.ts
TRANSLATIONS += translations/harbour-tooterb-ru.ts
TRANSLATIONS += translations/harbour-tooterb-sr.ts
TRANSLATIONS += translations/harbour-tooterb-sv.ts
TRANSLATIONS += translations/harbour-tooterb-zh_CN.ts
TRANSLATIONS += translations/harbour-tooterb-it.ts
TRANSLATIONS += translations/harbour-tooterb.ts \
translations/harbour-tooterb-de.ts \
translations/harbour-tooterb-el.ts \
translations/harbour-tooterb-es.ts \
translations/harbour-tooterb-fr.ts \
translations/harbour-tooterb-it.ts \
translations/harbour-tooterb-nl.ts \
translations/harbour-tooterb-nl_BE.ts \
translations/harbour-tooterb-oc.ts \
translations/harbour-tooterb-pl.ts \
translations/harbour-tooterb-ru.ts \
translations/harbour-tooterb-sr.ts \
translations/harbour-tooterb-sv.ts \
translations/harbour-tooterb-zh_CN.ts

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.9.1, 2020-05-11T10:29:25. -->
<!-- Written by QtCreator 4.9.1, 2020-06-19T11:40:51. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@ -63,6 +63,370 @@
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">SailfishOS-3.2.1.20-i486 (in Sailfish OS Build Engine)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">SailfishOS-3.2.1.20-i486 (in Sailfish OS Build Engine)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">SailfishOS-3.2.1.20-i486</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/XPAM/Github/Github-App/build-harbour-tooterb-SailfishOS_3_2_1_20_i486_in_Sailfish_OS_Build_Engine-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/XPAM/Github/Github-App/build-harbour-tooterb-SailfishOS_3_2_1_20_i486_in_Sailfish_OS_Build_Engine-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/XPAM/Github/Github-App/build-harbour-tooterb-SailfishOS_3_2_1_20_i486_in_Sailfish_OS_Build_Engine-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy As RPM Package</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmBuildStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM Validation</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmValidationStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build RPM Package For Manual Deployment</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerMb2RpmBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.2">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Rsync</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRsyncDeployStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy By Copying Binaries</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRSyncDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="MerRunConfiguration.QmlLiveBenchWorkspace">C:/Users/XPAM/Github/Github-App/harbour-tooter</value>
<value type="bool" key="MerRunConfiguration.QmlLiveEnabled">false</value>
<value type="int" key="MerRunConfiguration.QmlLiveIpcPort">-1</value>
<value type="int" key="MerRunConfiguration.QmlLiveOptions">3</value>
<value type="QString" key="MerRunConfiguration.QmlLiveTargetWorkspace"></value>
<value type="int" key="PE.EnvironmentAspect.Base">1</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">harbour-tooterb (on Sailfish OS Emulator 3.3.0.16)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:C:/Users/XPAM/Github/Github-App/harbour-tooter/harbour-tooterb.pro</value>
<value type="int" key="RemoteLinux.EnvironmentAspect.Version">1</value>
<value type="QString" key="RemoteLinux.RunConfig.AlternateRemoteExecutable"></value>
<value type="bool" key="RemoteLinux.RunConfig.UseAlternateRemoteExecutable">false</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.1</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">SailfishOS-3.3.0.16-armv7hl (in Sailfish OS Build Engine)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">SailfishOS-3.3.0.16-armv7hl (in Sailfish OS Build Engine)</value>
@ -426,7 +790,7 @@
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.1</variable>
<variable>ProjectExplorer.Project.Target.2</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">SailfishOS-3.3.0.16-i486 (in Sailfish OS Build Engine)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">SailfishOS-3.3.0.16-i486 (in Sailfish OS Build Engine)</value>
@ -789,9 +1153,373 @@
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.3</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">SailfishOS-3.2.1.20-armv7hl (in Sailfish OS Build Engine)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">SailfishOS-3.2.1.20-armv7hl (in Sailfish OS Build Engine)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">SailfishOS-3.2.1.20-armv7hl</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/XPAM/Github/Github-App/build-harbour-tooterb-SailfishOS_3_2_1_20_armv7hl_in_Sailfish_OS_Build_Engine-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/XPAM/Github/Github-App/build-harbour-tooterb-SailfishOS_3_2_1_20_armv7hl_in_Sailfish_OS_Build_Engine-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/XPAM/Github/Github-App/build-harbour-tooterb-SailfishOS_3_2_1_20_armv7hl_in_Sailfish_OS_Build_Engine-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Start Build Engine</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Mer.MerSdkStartStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy As RPM Package</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmDeployConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmBuildStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">RPM Validation</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRpmValidationStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build RPM Package For Manual Deployment</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerMb2RpmBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.2">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Prepare Target</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerPrepareTargetStep</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Rsync</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRsyncDeployStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy By Copying Binaries</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRSyncDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="MerRunConfiguration.QmlLiveBenchWorkspace">C:/Users/XPAM/Github/Github-App/harbour-tooter</value>
<value type="bool" key="MerRunConfiguration.QmlLiveEnabled">false</value>
<value type="int" key="MerRunConfiguration.QmlLiveIpcPort">-1</value>
<value type="int" key="MerRunConfiguration.QmlLiveOptions">3</value>
<value type="QString" key="MerRunConfiguration.QmlLiveTargetWorkspace"></value>
<value type="int" key="PE.EnvironmentAspect.Base">1</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">harbour-tooterb (on Sailfish OS Emulator 3.3.0.16)</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:C:/Users/XPAM/Github/Github-App/harbour-tooter/harbour-tooterb.pro</value>
<value type="int" key="RemoteLinux.EnvironmentAspect.Version">1</value>
<value type="QString" key="RemoteLinux.RunConfig.AlternateRemoteExecutable"></value>
<value type="bool" key="RemoteLinux.RunConfig.UseAlternateRemoteExecutable">false</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">2</value>
<value type="int">4</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>

View file

@ -30,9 +30,9 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../lib/API.js" as Logic
CoverBackground {
onStatusChanged: {
switch (status ){
@ -46,20 +46,21 @@ CoverBackground {
break;
}
}
Image {
id: bg
source: "../images/tooter-cover.svg"
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignBottom
fillMode: Image.PreserveAspectFit
anchors {
bottom : parent.bottom
left: parent.left
right: parent.right
top: parent.top
}
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignBottom
fillMode: Image.PreserveAspectFit
source: "../images/tooterb.svg"
}
Timer {
id: timer
interval: 60*1000
@ -70,33 +71,34 @@ CoverBackground {
Image {
id: iconNot
source: "image://theme/icon-s-alarm?" + Theme.highlightColor
anchors {
left: parent.left
top: parent.top
leftMargin: Theme.paddingLarge
topMargin: Theme.paddingLarge
}
source: "image://theme/icon-s-alarm?" + Theme.highlightColor
}
Label {
id: notificationsLbl
text: " "
color: Theme.highlightColor
anchors {
left: iconNot.right
leftMargin: Theme.paddingMedium
verticalCenter: iconNot.verticalCenter
}
text: " "
color: Theme.highlightColor
}
Label {
text: "Tooter β"
color: Theme.secondaryColor
anchors {
right: parent.right
rightMargin: Theme.paddingLarge
verticalCenter: iconNot.verticalCenter
}
text: "Tooter β"
color: Theme.primaryColor
}
signal activateapp(string person, string notice)
@ -112,8 +114,11 @@ CoverBackground {
CoverAction {
iconSource: "image://theme/icon-cover-new"
onTriggered: {
pageStack.push(Qt.resolvedUrl("./../pages/Conversation.qml"), {})
appWindow.activate();
pageStack.push(Qt.resolvedUrl("./../pages/ConversationPage.qml"), {
headerTitle: qsTr("New Toot"),
type: "new"
})
appWindow.activate()
}
}
}
@ -135,5 +140,5 @@ CoverBackground {
notificationsLbl.text = notificationsNum;
Logic.conf.notificationLastID = notificationLastID;
}
}
}

View file

@ -33,23 +33,26 @@ import Sailfish.Silica 1.0
import "pages"
import "./lib/API.js" as Logic
ApplicationWindow
{
ApplicationWindow {
id: appWindow
//initialPage: Component { FirstPage { } }
cover: Qt.resolvedUrl("cover/CoverPage.qml")
allowedOrientations: defaultAllowedOrientations
cover: Qt.resolvedUrl("cover/CoverPage.qml")
Component.onCompleted: {
var obj = {};
Logic.mediator.installTo(obj);
obj.subscribe('confLoaded', function(){
var obj = {}
Logic.mediator.installTo(obj)
obj.subscribe('confLoaded', function() {
console.log('confLoaded');
//console.log(JSON.stringify(Logic.conf))
if (!Logic.conf['notificationLastID'])
Logic.conf['notificationLastID'] = 0;
Logic.conf['notificationLastID'] = 0
if (Logic.conf['instance']) {
Logic.api = new Logic.MastodonAPI({ instance: Logic.conf['instance'], api_user_token: "" });
Logic.api = Logic.mastodonAPI({
"instance": Logic.conf['instance'],
"api_user_token": ""
})
}
if (Logic.conf['login']) {
//Logic.conf['notificationLastID'] = 0
Logic.api.setConfig("api_user_token", Logic.conf['api_user_token'])
@ -57,17 +60,12 @@ ApplicationWindow
Logic.api.get('instance', [], function(data) {
console.log(JSON.stringify(data))
pageStack.push(Qt.resolvedUrl("./pages/MainPage.qml"), {})
});
//
//
})
//pageStack.push(Qt.resolvedUrl("./pages/Conversation.qml"), {})
} else {
pageStack.push(Qt.resolvedUrl("./pages/LoginPage.qml"), {})
}
});
})
Logic.init()
}
@ -75,19 +73,18 @@ ApplicationWindow
//Logic.conf.notificationLastID = 0;
Logic.saveData()
}
Connections
{
target: Dbus
onViewtoot:
{
console.log(key, "dbus onViewtoot")
}
onActivateapp:
{
console.log ("dbus activate app")
pageStack.pop(pageStack.find( function(page){ return (page._depth === 0) }))
activate()
}
}
}
Connections {
target: Dbus
onViewtoot: {
console.log(key, "dbus onViewtoot")
}
onActivateapp: {
console.log ("dbus activate app")
pageStack.pop(pageStack.find( function(page) {
return (page._depth === 0)
}))
activate()
}
}
}

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 36 36" enable-background="new 0 0 36 36" xml:space="preserve">
<g>
<g>
<path fill="#FFFFFF" d="M28.8,12.5c-1.8,0-4.6,0-6.3,0c-0.5,0-1.5,0-0.8-1.1c1-1.9,3-5.9,4.3-8.1c0.7-1.1,0.8-1.8-0.4-1.8
c-2.7,0-9.1,0-12,0c-1.1,0-1.6,0.5-2.1,1.6c-1.4,3.5-4.7,12.1-5.9,15.7c-0.4,1.2,0.3,1.7,1.2,1.7c1.8,0,5,0,6.7,0
c0.6,0,1.2,0.1,0.8,1.4c-0.8,2.3-2,7-2.8,9.7c0,0-0.8,3.7,2.4,0.8C18.1,28.2,25.4,17.7,29,14C29.7,13.4,29.7,12.5,28.8,12.5z
M20.7,21.1c-2.2,2.8-4.4,5.7-6.3,7.8c0.1-0.2,0.1-0.5,0.2-0.7c0.6-2.1,1.2-4.3,1.7-5.7l0,0l0,0c0.3-1.2,0.2-2.1-0.3-2.9
c-0.5-0.7-1.4-1.1-2.4-1.1H7.9c1.3-3.7,3.9-10.4,5.2-13.8l0.3-0.8c0.1-0.2,0.2-0.3,0.2-0.4c0,0,0,0,0,0h10
c-1.2,2.2-2.7,5.2-3.6,6.9c-0.7,1.3-0.5,2.2-0.2,2.8c0.7,1.3,2.2,1.3,2.7,1.3h3.4C24.4,16.3,22.6,18.6,20.7,21.1z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 886 B

After

Width:  |  Height:  |  Size: 886 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<title>icon-s-bookmark</title>
<g>
<rect width="32" height="32" fill="#fff" fill-opacity="0"/>
<path d="M26.85,29.74a1,1,0,0,1-.66-.25L16,20.82,5.81,29.48a1,1,0,0,1-1,.2c-.7-.22-.7-.76-.7-1.58,0-.63,0-1.88,0-4.38V4.48A2.41,2.41,0,0,1,6.44,2H25.56a2.41,2.41,0,0,1,2.29,2.5V23.73c0,2.5,0,3.75,0,4.38,0,.82,0,1.36-.7,1.58A1,1,0,0,1,26.85,29.74ZM16,18.55a1.07,1.07,0,0,1,.69.24l9.16,7.79c0-.7,0-1.62,0-2.84V4.48c0-.3-.18-.5-.29-.5H6.44c-.12,0-.29.2-.29.5V23.73c0,1.22,0,2.14,0,2.84l9.16-7.79A1.07,1.07,0,0,1,16,18.55Z" fill="#fff"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 623 B

View file

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<title>Artboard 1</title>
<g>
<rect x="-2" y="-2" width="36.2" height="36.2" fill="#fff" fill-opacity="0"/>
<g>
<path d="M22.9,11.3a6.8,6.8,0,1,1-6.8-6.8A6.74,6.74,0,0,1,22.9,11.3Z" fill="#fff"/>
<g opacity="0.6">
<path d="M28,26.6v.6H4.3v-.6a6.23,6.23,0,0,1,6.2-6.2H21.8A6.24,6.24,0,0,1,28,26.3Z" fill="#fff"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 451 B

View file

@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="15 0 60 60" enable-background="new 15 0 60 60" xml:space="preserve">
<path id="Home" display="none" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linejoin="round" stroke-miterlimit="10" d="
M42,7.7l-18.6,15c-0.3,0.3-0.5,0.7-0.5,1V52c0,0.8,0.7,1.4,1.4,1.4h12.4c0.8,0,1.4-0.7,1.4-1.4V34.1c0-0.7,0.7-1.4,1.4-1.4h11.1
c0.8,0,1.4,0.7,1.4,1.4V52c0,0.8,0.7,1.4,1.4,1.4h12.4c0.8,0,1.4-0.7,1.4-1.4V23.7c0-0.4-0.2-0.8-0.5-1l-18.5-15
C46.3,6.2,43.7,6.2,42,7.7z"/>
<g id="Local" display="none">
<circle display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linejoin="round" stroke-miterlimit="10" cx="45" cy="26.1" r="6.9"/>
<path display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linejoin="round" stroke-miterlimit="10" d="M45,6.8
c10.7,0,19.3,8.6,19.3,19.3c0,2.8-0.6,5.4-1.7,7.9c-0.8,2-2.1,3.8-3.6,5.3l-14,14l-14.1-14c-1.5-1.6-2.7-3.4-3.6-5.3
c-1-2.4-1.7-5.1-1.7-7.9C25.7,15.4,34.3,6.8,45,6.8z"/>
</g>
<g id="Federation" display="none">
<circle display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" cx="45" cy="30" r="23.4"/>
<ellipse display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" cx="45" cy="30" rx="12.4" ry="23.4"/>
<path display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M61.5,13.4
c-2.6,4.1-9.5,6.9-16.5,6.9s-13.9-2.8-16.5-6.9"/>
<path display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M28.5,46.6
c2.6-4.1,9.5-6.9,16.5-6.9s13.9,2.8,16.5,6.9"/>
<line display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="21.6" y1="30" x2="68.4" y2="30"/>
<line display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" x1="45" y1="6.6" x2="45" y2="53.4"/>
</g>
<g id="Search" display="none">
<circle display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linejoin="round" stroke-miterlimit="10" cx="42.3" cy="27.3" r="19.3"/>
<line display="inline" fill="none" stroke="#FFFFFF" stroke-width="2" stroke-linejoin="round" stroke-miterlimit="10" x1="67" y1="52" x2="56.1" y2="41.1"/>
</g>
<path id="Notification_1_" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linejoin="round" stroke-miterlimit="10" d="
M56.3,49.9c1.9,2.2,4.6,3.5,7.7,3.5c2.1,0,3.9-0.6,5.5-1.7c-3.2-1.8-5.4-5-6.1-8.7c2.5-3.8,3.9-8.2,3.9-13
C67.4,17.1,56.9,6.6,44,6.6S20.5,17,20.5,29.9S31,53.3,43.8,53.3C48.5,53.3,52.8,52,56.3,49.9z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View file

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
<path fill="#FFFFFF" d="M47.7,22.5c-0.2-0.8-0.5-1.6-1-2.3c-0.5-0.7-1-1.3-1.6-1.9s-1.3-1-2.1-1.4c0.1-0.2,0.2-0.5,0.3-0.7
c0-0.3,0.1-0.5,0.2-0.8s0.1-0.5,0.1-0.8s0-0.6,0.1-0.8c0-1.3-0.3-2.5-0.7-3.6c-0.4-1.1-1-2.1-1.9-2.9s-1.7-1.5-2.8-2
c-1-0.5-2.2-0.7-3.4-0.7c-0.3,0-0.5,0-0.8,0c-0.3,0-0.5,0.1-0.8,0.1c-0.2,0-0.5,0.1-0.8,0.2S32.1,5,31.9,5.1
c-0.4-0.8-0.9-1.4-1.4-2.1s-1.1-1.2-1.8-1.6s-1.4-0.8-2.2-1C25.7,0.1,24.9,0,24,0c-0.8,0-1.7,0.1-2.5,0.4S20,1,19.3,1.4
c-0.7,0.4-1.3,1-1.8,1.6c-0.6,0.6-1,1.3-1.3,2.1c-0.3-0.1-0.5-0.2-0.8-0.2c-0.2-0.1-0.5-0.1-0.8-0.2c-0.3,0-0.5-0.1-0.8-0.1
c-0.2,0-0.5,0-0.8,0c-1.1,0-2.3,0.2-3.4,0.7c-1.1,0.5-2,1.1-2.8,2S5.5,9,5,10.1s-0.7,2.3-0.7,3.6c0,0.3,0,0.5,0,0.8s0.1,0.6,0.1,0.8
c0,0.3,0.1,0.5,0.2,0.8c0.1,0.3,0.2,0.5,0.2,0.7c-0.7,0.4-1.3,0.9-2,1.4s-1.2,1.2-1.6,1.9c-0.4,0.7-0.7,1.5-1,2.3
C0.1,23.4,0,24.3,0,25.2c0,0.8,0.1,1.7,0.3,2.5s0.5,1.5,0.9,2.2s0.8,1.3,1.4,1.9s1.2,1,1.8,1.4c0,0.1,0,0.2,0,0.3s-0.1,0.2,0,0.3
c0,0.1,0,0.2,0,0.3c0,0.1,0,0.2,0,0.3c0,1.2,0.2,2.4,0.7,3.5C5.5,39,6.2,40,6.9,40.8s1.7,1.5,2.8,2s2.2,0.7,3.4,0.7
c0.3,0,0.6,0,0.8,0c0.2,0,0.5-0.1,0.8-0.1c0.3,0,0.5-0.1,0.8-0.2c0.2-0.1,0.5-0.2,0.8-0.3c0.3,0.8,0.7,1.5,1.3,2.1
c0.6,0.6,1.2,1.2,1.8,1.6c0.7,0.5,1.4,0.8,2.2,1.1s1.6,0.4,2.5,0.4c0.9,0,1.7-0.1,2.5-0.4c0.8-0.2,1.5-0.6,2.2-1.1s1.3-1,1.8-1.6
c0.5-0.6,1-1.3,1.4-2.1c0.2,0.1,0.5,0.2,0.7,0.3c0.3,0.1,0.5,0.2,0.8,0.2c0.2,0,0.5,0.1,0.8,0.1c0.3,0,0.5,0,0.8,0
c1.2,0,2.4-0.2,3.4-0.7s2-1.1,2.8-2s1.4-1.8,1.9-2.9c0.4-1.1,0.7-2.3,0.7-3.5c0-0.1-0.1-0.2,0-0.3s0-0.2,0-0.3c0-0.1,0-0.2,0-0.3
s0-0.2-0.1-0.3c0.7-0.4,1.3-0.9,1.9-1.4c0.5-0.6,1-1.2,1.4-1.9c0.4-0.7,0.7-1.4,0.9-2.2c0.2-0.8,0.3-1.6,0.3-2.5
C48,24.3,47.9,23.4,47.7,22.5z M35.8,18.5c-0.2,0.3-0.3,0.6-0.5,0.8h-0.1L22,32.6c0,0-0.1,0,0,0s0,0,0,0c-0.1,0.1-0.2,0.2-0.4,0.3
c-0.2,0.1-0.3,0.2-0.4,0.2c-0.1,0-0.3,0.1-0.5,0.1c-0.2,0-0.3,0.1-0.4,0.1c-0.2,0-0.4,0-0.5-0.1c-0.1,0-0.3-0.1-0.5-0.1
c-0.2,0-0.3-0.1-0.4-0.2c-0.1-0.1-0.3-0.2-0.4-0.3l-5.7-5.8c-0.3-0.2-0.5-0.5-0.6-0.8c-0.1-0.3-0.2-0.6-0.2-0.9c0-0.3,0-0.6,0.2-0.9
c0.2-0.3,0.3-0.6,0.5-0.9c0.3-0.2,0.6-0.4,0.9-0.5s0.6-0.2,0.9-0.2c0.4,0,0.7,0.1,0.9,0.2c0.3,0.1,0.6,0.3,0.9,0.5l3.9,4l11.7-11.6
c0.2-0.2,0.4-0.4,0.8-0.5s0.7-0.2,0.9-0.2s0.6,0.1,0.9,0.2s0.6,0.3,0.8,0.5c0.3,0.3,0.5,0.6,0.6,0.9c0.1,0.3,0.2,0.6,0.2,0.9
C36.1,17.9,36,18.2,35.8,18.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -9,6 +9,7 @@ var mediator = (function(){
mediator.channels[channel].push({ context : this, callback : fn });
return this;
};
var publish = function(channel){
if(!mediator.channels[channel]) return false;
var args = Array.prototype.slice.call(arguments, 1);
@ -18,6 +19,7 @@ var mediator = (function(){
};
return this;
};
return {
channels : {},
publish : publish,
@ -28,6 +30,7 @@ var mediator = (function(){
}
};
}());
var init = function(){
console.log("db.version: "+db.version);
if(db.version === '') {
@ -35,7 +38,7 @@ var init = function(){
tx.executeSql('CREATE TABLE IF NOT EXISTS settings ('
+ ' key TEXT UNIQUE, '
+ ' value TEXT '
+');');
+ ');');
//tx.executeSql('INSERT INTO settings (key, value) VALUES (?, ?)', ["conf", "{}"]);
});
db.changeVersion('', '0.1', function(tx) {
@ -88,21 +91,22 @@ var tootParser = function(data){
ret.display_name = data.account.display_name
ret.avatar_static = data.account.avatar_static
ret.favourited = data.favourited ? true : false
ret.favourites_count = data.favourites_count ? data.favourites_count : 0
ret.status_favourites_count = data.favourites_count ? data.favourites_count : 0
ret.reblog = data.reblog ? true : false
ret.reblogged = data.reblogged ? true : false
ret.reblogs_count = data.reblogs_count ? data.reblogs_count : false
ret.status_reblogs_count = data.reblogs_count ? data.reblogs_count : false
ret.bookmarked = data.bookmarked ? true : false
ret.muted = data.muted ? true : false
ret.sensitive = data.sensitive ? true : false
ret.visibility = data.visibility ? data.visibility : false
console.log(ret)
}
var test = 1;
Qt.include("Mastodon.js")
@ -161,6 +165,7 @@ var notifier = function(item){
key: item.id
}
break;
case "follow":
msg = {
urgency: "critical",
@ -182,6 +187,7 @@ var notifier = function(item){
key: item.id
}
break;
case "mention":
msg = {
urgency: "critical",
@ -193,6 +199,7 @@ var notifier = function(item){
key: item.id
}
break;
default:
//console.log(JSON.stringify(messageObject.data))
return;

View file

@ -3,17 +3,19 @@
// do whatever you want with it
// but please don't hurt it (and keep this header)
var MastodonAPI = function(config) {
var mastodonAPI = function(config) {
var apiBase = config.instance + "/api/v1/";
return {
setConfig: function (key, value) {
// modify initial config afterwards
config[key] = value;
},
getConfig: function(key) {
//get config key
return config[key];
},
get: function (endpoint) {
// for GET API calls
// can be called with two or three parameters
@ -56,8 +58,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) {
if (http.status == 200) {
if (http.readyState === 4) {
if (http.status === 200) {
console.log("Successful GET API request to " +apiBase+endpoint);
callback(JSON.parse(http.response),http.status)
} else {
@ -67,6 +69,7 @@ var MastodonAPI = function(config) {
}
http.send();
},
post: function (endpoint) {
// for POST API calls
var postData, callback;
@ -91,8 +94,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) {
if (http.status == 200) {
if (http.readyState === 4) {
if (http.status === 200) {
console.log("Successful POST API request to " +apiBase+endpoint);
callback(JSON.parse(http.response),http.status)
} else {
@ -113,6 +116,7 @@ var MastodonAPI = function(config) {
}
});*/
},
delete: function (endpoint, callback) {
// for DELETE API calls.
$.ajax({
@ -125,6 +129,7 @@ var MastodonAPI = function(config) {
}
});
},
stream: function (streamType, onData) {
// Event Stream Support
// websocket streaming is undocumented. i had to reverse engineer the fucking web client.
@ -132,7 +137,7 @@ var MastodonAPI = function(config) {
// user for your local home TL and notifications
// public for your federated TL
// public:local for your home TL
// hashtag&tag=fuckdonaldtrump for the stream of #fuckdonaldtrump
// hashtag&tag=mastodonrocks for the stream of #mastodonrocks
// callback gets called whenever new data ist recieved
// callback { event: (eventtype), payload: {mastodon object as described in the api docs} }
// eventtype could be notification (=notification) or update (= new toot in TL)
@ -147,12 +152,10 @@ var MastodonAPI = function(config) {
onData(event);
};
es.onmessage = listener;
},
registerApplication: function (client_name, redirect_uri, scopes, website, callback) {
//register a new application
// OAuth Auth flow:
// First register the application
// 2) get a access code from a user (using the link, generation function below!)
@ -180,8 +183,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) {
if (http.status == 200) {
if (http.readyState === 4) {
if (http.status === 200) {
console.log("Registered Application: " + http.response);
callback(http.response)
} else {
@ -191,10 +194,12 @@ var MastodonAPI = function(config) {
}
http.send(params);
},
generateAuthLink: function (client_id, redirect_uri, responseType, scopes) {
return config.instance + "/oauth/authorize?client_id=" + client_id + "&redirect_uri=" + redirect_uri +
"&response_type=" + responseType + "&scope=" + scopes.join("+");
},
getAccessTokenFromAuthCode: function (client_id, client_secret, redirect_uri, code, callback) {
/*$.ajax({
url: config.instance + "/oauth/token",
@ -221,8 +226,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) {
if (http.status == 200) {
if (http.readyState === 4) {
if (http.status === 200) {
console.log("Got Token: " + http.response);
callback(http.response)
} else {
@ -236,7 +241,7 @@ var MastodonAPI = function(config) {
};
// node.js
if (typeof module !== 'undefined') { module.exports = MastodonAPI; };
if (typeof module !== 'undefined') { module.exports = mastodonAPI; };
String.prototype.replaceAll = function(search, replacement) {
var target = this;

View file

@ -1,5 +1,8 @@
Qt.include("Mastodon.js")
var loadImages = true;
WorkerScript.onMessage = function(msg) {
console.log("Action > " + msg.action)
console.log("Model > " + msg.model)
@ -7,27 +10,31 @@ WorkerScript.onMessage = function(msg) {
console.log("Conf > " + JSON.stringify(msg.conf))
console.log("Params > " + JSON.stringify(msg.params))
// order notifications in ASC order
/** order notifications in ASC order */
function orderNotifications(items){
for (var i = items.length-1; i > 0; i--){
for (var i = items.length-1; i > 0; i--) {
if (items[i].id > 0 ) //msg.conf.notificationLastID)
WorkerScript.sendMessage({ 'fireNotification': true, "data": items[i]})
}
}
if (!msg.conf || !msg.conf.login){
/** Logged-in status */
if (!msg.conf || !msg.conf.login) {
console.log("Not loggedin")
return;
}
/** Load images */
if (typeof msg.conf['loadImages'] !== "undefined")
loadImages = msg.conf['loadImages']
var API = MastodonAPI({ instance: msg.conf.instance, api_user_token: msg.conf.api_user_token});
/** POST statuses */
var API = mastodonAPI({ instance: msg.conf.instance, api_user_token: msg.conf.api_user_token});
if (msg.method === "POST"){
API.post(msg.action, msg.params, function(data) {
if (msg.bgAction){
console.log(JSON.stringify(data))
} else if (msg.action === "statuses"){
} else if (msg.action === "statuses") {
// status posted
if(msg.model){
var item = parseToot(data);
@ -59,7 +66,7 @@ WorkerScript.onMessage = function(msg) {
} else if(msg.action === "notifications") {
// notification
//console.log("Is notification... parsing...")
console.log("Get notification list")
console.log(JSON.stringify(data[i]))
item = parseNotification(data[i]);
items.push(item)
@ -69,7 +76,9 @@ WorkerScript.onMessage = function(msg) {
console.log("ancestors")
for (var j = 0; j < data[i].length; j ++) {
item = parseToot(data[i][j]);
item['id'] = item['status_id']
item['id'] = item['status_id'];
if (typeof item['attachments'] === "undefined")
item['attachments'] = [];
items.push(item)
console.log(JSON.stringify(data[i][j]))
}
@ -78,7 +87,7 @@ WorkerScript.onMessage = function(msg) {
//console.log(JSON.stringify(i))
} else if(msg.action.indexOf("statuses") >-1 && msg.action.indexOf("context") >-1 && i === "descendants") {
// status ancestors toots - conversation
// status descendants toots - conversation
console.log("descendants")
for (var j = 0; j < data[i].length; j ++) {
item = parseToot(data[i][j]);
@ -91,16 +100,18 @@ WorkerScript.onMessage = function(msg) {
addDataToModel (msg.model, "append", items);
items = [];
} else if (data[i].hasOwnProperty("content")){
//console.log("Is toot... parsing...")
} else if (data[i].hasOwnProperty("content")){
//console.log("Get Toot")
item = parseToot(data[i]);
item['id'] = item['status_id']
items.push(item)
} else {
WorkerScript.sendMessage({ 'action': msg.action, 'success': true, key: i, "data": data[i]})
WorkerScript.sendMessage({ 'action': msg.action, 'success': true, key: i, "data": data[i] })
}
}
}
if(msg.model && items.length)
addDataToModel(msg.model, msg.mode, items)
/*if(msg.action === "notifications")
@ -108,40 +119,53 @@ WorkerScript.onMessage = function(msg) {
});
}
//WorkerScript.sendMessage({ 'notifyNewItems': length - i })
function addDataToModel (model, mode, items){
function addDataToModel (model, mode, items) {
var length = items.length;
console.log("Fetched > " +length)
if (mode === "append") {
model.append(items)
} else if (mode === "prepend") {
for(var i = length-1; i >= 0 ; i--){
for(var i = length-1; i >= 0 ; i--) {
model.insert(0,items[i])
}
}
model.sync()
}
function parseAccounts(collection, prefix, data){
var res = collection;
/** Function: Get Account Data */
function parseAccounts(collection, prefix, data) {
var res = collection;
// Base attributes
res[prefix + 'account_id'] = data["id"]
res[prefix + 'account_username'] = data["username"]
res[prefix + 'account_acct'] = data["acct"]
res[prefix + 'account_url'] = data["url"]
// Display attributes
res[prefix + 'account_display_name'] = data["display_name"]
res[prefix + 'account_discoverable'] = data["discoverable"]
res[prefix + 'account_locked'] = data["locked"]
res[prefix + 'account_created_at'] = data["created_at"]
res[prefix + 'account_note'] = data["note"]
res[prefix + 'account_avatar'] = data["avatar"]
res[prefix + 'account_header'] = data["header"]
res[prefix + 'account_locked'] = data["locked"]
//res[prefix + 'account_emojis'] = data["emojis"]
res[prefix + 'account_discoverable'] = data["discoverable"]
// Statistical attributes
res[prefix + 'account_created_at'] = data["created_at"]
res[prefix + 'account_statuses_count'] = data["statuses_count"]
res[prefix + 'account_followers_count'] = data["followers_count"]
res[prefix + 'account_following_count'] = data["following_count"]
// Optional attributes
//res[prefix + 'account_fields'] = data["fields"]
res[prefix + 'account_bot'] = data["bot"]
res[prefix + 'account_group'] = data["group"]
// console.log(JSON.stringify(res))
//console.log(JSON.stringify(res))
return (res);
}
/** Function: Get Notification Data */
function parseNotification(data){
//console.log(JSON.stringify(data))
var item = {
@ -150,50 +174,49 @@ function parseNotification(data){
attachments: []
};
switch (item['type']){
case "mention":
if (!data.status) {
break;
break;
}
item = parseToot(data.status)
item['typeIcon'] = "image://theme/icon-s-retweet"
item['typeIcon'] = "image://theme/icon-s-alarm"
item['type'] = "mention";
item['type'] = "mention"
break;
case "reblog":
if (!data.status) {
break;
}
item = parseToot(data.status)
item = parseAccounts(item, "reblog_", data["account"])
item = parseAccounts(item, "", data["status"]["account"])
item['status_reblog'] = true;
item['type'] = "reblog";
item['status_reblog'] = true
item['type'] = "reblog"
item['typeIcon'] = "image://theme/icon-s-retweet"
break;
case "favourite":
if (!data.status) {
break;
}
item = parseToot(data.status)
item = parseAccounts(item, "reblog_", data["account"])
item = parseAccounts(item, "", data["status"]["account"])
item['status_reblog'] = true;
item['status_reblog'] = true
item['type'] = "favourite"
item['typeIcon'] = "image://theme/icon-s-favorite"
item['type'] = "favourite";
//item['retweetScreenName'] = item['reblog_account_username'];
break;
case "follow":
item['type'] = "follow";
item = parseAccounts(item, "", data["account"])
item = parseAccounts(item, "reblog_", data["account"])
item['content'] = data['account']['note']
item['typeIcon'] = "image://theme/icon-s-installed"
item['attachments'] = []
//item['content'] = data['account']['note']
item['typeIcon'] = "../../images/icon-s-follow.svg"
//item['attachments'] = []
break;
default:
item['typeIcon'] = "image://theme/icon-s-sailfish"
}
@ -204,6 +227,7 @@ function parseNotification(data){
return item;
}
/** Function: */
function collect() {
var ret = {};
var len = arguments.length;
@ -216,70 +240,81 @@ function collect() {
}
return ret;
}
function getDate(dateStr){
/** Function: Get Status date */
function getDate(dateStr) {
var ts = new Date(dateStr);
return new Date(ts.getFullYear(), ts.getMonth(), ts.getDate(), 0, 0, 0)
}
function parseToot (data){
/** Function: Get Status data */
function parseToot (data) {
var i = 0;
var item = {};
item['type'] = "toot"
item['highlight'] = false
item['status_id'] = data["id"]
item['status_uri'] = data["uri"]
item['status_url'] = data["url"]
item['status_in_reply_to_id'] = data["in_reply_to_id"]
item['status_in_reply_to_account_id'] = data["in_reply_to_account_id"]
item['status_reblog'] = data["reblog"] ? true : false
item['status_content'] = data["content"]
item['status_created_at'] = item['created_at'] = new Date(data["created_at"]);
item['section'] = getDate(data["created_at"]);
item['reblogs_count'] = data["reblogs_count"]
item['favourites_count'] = data["favourites_count"]
item['reblogged'] = data["reblogged"]
item['favourited'] = data["favourited"]
item['bookmarked'] = data["bookmarked"]
item['status_created_at'] = item['created_at'] = new Date(data["created_at"])
item['status_sensitive'] = data["sensitive"]
item['status_spoiler_text'] = data["spoiler_text"]
item['status_visibility'] = data["visibility"]
item['status_language'] = data["language"]
item['status_uri'] = data["uri"]
item['status_url'] = data["url"]
item['status_replies_count'] = data["replies_count"]
item['status_reblogs_count'] = data["reblogs_count"]
item['status_favourites_count'] = data["favourites_count"]
item['status_favourited'] = data["favourited"]
item['status_reblogged'] = data["reblogged"]
item['status_bookmarked'] = data["bookmarked"]
item['status_content'] = data["content"]
item['attachments'] = data['media_attachments']
item['status_in_reply_to_id'] = data["in_reply_to_id"]
item['status_in_reply_to_account_id'] = data["in_reply_to_account_id"]
item['status_reblog'] = data["reblog"] ? true : false
item['section'] = getDate(data["created_at"])
if(item['status_reblog']){
/** If Toot is a Reblog */
if(item['status_reblog']) {
item['type'] = "reblog";
item['typeIcon'] = "image://theme/icon-s-retweet"
item['status_id'] = data["reblog"]["id"];
item['status_spoiler_text'] = data["reblog"]["spoiler_text"]
item['status_id'] = data["reblog"]["id"]
item['status_sensitive'] = data["reblog"]["sensitive"]
item['emojis'] = data["reblog"]["emojis"];
item['status_spoiler_text'] = data["reblog"]["spoiler_text"]
item['status_replies_count'] = data["reblog"]["replies_count"]
item['status_reblogs_count'] = data["reblog"]["reblogs_count"]
item['status_favourites_count'] = data["reblog"]["favourites_count"]
item = parseAccounts(item, "", data['reblog']["account"])
item = parseAccounts(item, "reblog_", data["account"])
} else {
item = parseAccounts(item, "", data["account"])
}
/** Replace HTML content in Toots */
item['content'] = data['content']
.replaceAll('</span><span class="invisible">', '')
.replaceAll('<span class="invisible">', '')
.replaceAll('</span><span class="ellipsis">', '')
.replaceAll('class=""', '');
.replaceAll('</span><span class="invisible">', '')
.replaceAll('<span class="invisible">', '')
.replaceAll('</span><span class="ellipsis">', '')
.replaceAll('class=""', '');
/** Media attachements in Toots */
item['attachments'] = [];
for(i = 0; i < data['media_attachments'].length ; i++){
for(i = 0; i < data['media_attachments'].length; i++) {
var attachments = data['media_attachments'][i];
item['content'] = item['content'].replaceAll(attachments['text_url'], '')
var tmp = {
id: attachments['id'],
id: attachments['id'],
type: attachments['type'],
url: attachments['remote_url'] && typeof attachments['remote_url'] == "string" ? attachments['remote_url'] : attachments['url'] ,
preview_url: loadImages ? attachments['preview_url'] : ''
preview_url: loadImages ? attachments['preview_url'] : ''
}
item['attachments'].push(tmp)
}
if(item['status_reblog']){
for(i = 0; i < data['reblog']['media_attachments'].length ; i++){
/** Media attachements in Reblogs */
if(item['status_reblog']) {
for(i = 0; i < data['reblog']['media_attachments'].length ; i++) {
var attachments = data['reblog']['media_attachments'][i];
item['content'] = item['content'].replaceAll(attachments['text_url'], '')
var tmp = {
@ -291,20 +326,22 @@ function parseToot (data){
item['attachments'].push(tmp)
}
}
return addEmojis(item, data);
}
function addEmojis(item, data){
/** Function: Display custom Emojis in Toots */
function addEmojis(item, data) {
var emoji, i;
for (i = 0; i < data["emojis"].length; i++){
for (i = 0; i < data["emojis"].length; i++) {
emoji = data["emojis"][i];
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"middle\" width=\"24\" height=\"24\">")
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"top\" width=\"50\" height=\"50\">")
//console.log(JSON.stringify(data["emojis"][i]))
}
if (data["reblog"])
for (i = 0; i < data["reblog"]["emojis"].length; i++){
for (i = 0; i < data["reblog"]["emojis"].length; i++) {
emoji = data["reblog"]["emojis"][i];
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"middle\" width=\"24\" height=\"24\">")
item['content'] = item['content'].replaceAll(":"+emoji.shortcode+":", "<img src=\"" + emoji.static_url+"\" align=\"top\" width=\"50\" height=\"50\">")
}
return item;

View file

@ -1,646 +0,0 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import harbour.tooterb.Uploader 1.0
import "../lib/API.js" as Logic
import "./components/"
Page {
id: conversationPage
property string headerTitle: ""
property string type
property alias title: header.title
property alias description: header.description
property alias avatar: header.image
property string suggestedUser: ""
property ListModel suggestedModel
property string toot_id: ""
property string toot_url: ""
property int tootMaxChar: 500;
property ListModel mdl
allowedOrientations: Orientation.All
onSuggestedUserChanged: {
console.log(suggestedUser)
suggestedModel = Qt.createQmlObject(
'import QtQuick 2.0; ListModel { }',
Qt.application, 'InternalQmlObject'
)
predictionList.visible = false
if (suggestedUser.length > 0) {
var msg = {
"action": 'accounts/search',
"method": 'GET',
"model": suggestedModel,
"mode": "append",
"params": [{
"name": "q",
"data": suggestedUser
}],
"conf": Logic.conf
}
worker.sendMessage(msg)
predictionList.visible = true
}
}
InfoBanner {
id: sentBanner
}
ListModel {
id: mediaModel
onCountChanged: {
btnAddImage.enabled = mediaModel.count < 4
}
}
WorkerScript {
id: worker
source: "../lib/Worker.js"
onMessage: {
console.log(JSON.stringify(messageObject))
}
}
ProfileHeader {
id: header
visible: false
}
SilicaListView {
id: conversationList
header: PageHeader {
title: headerTitle // pageTitle pushed from MainPage.qml or VisualContainer.qml
}
clip: true
anchors {
top: parent.top
bottom: panel.top
left: parent.left
right: parent.right
}
model: mdl
section {
property: 'section'
delegate: SectionHeader {
height: Theme.itemSizeExtraSmall
text: Format.formatDate(section, Formatter.DateMedium)
}
}
delegate: VisualContainer {
}
onCountChanged: {
if (mdl)
for (var i = 0; i < mdl.count; i++) {
if (mdl.get(i).status_id === toot_id) {
console.log(mdl.get(i).status_id)
positionViewAtIndex(i, ListView.Center)
}
}
}
PullDownMenu {
visible: type == "reply" && toot_url != ""
/* MenuItem {
text: qsTr("Open in Browser")
onClicked: Qt.openUrlExternally(toot_url);
} */
// ! url isn't always fetched. Needs a solution.
MenuItem {
text: qsTr("Copy Link to Clipboard")
onClicked: Clipboard.text = toot_url;
}
}
}
Rectangle {
id: predictionList
visible: false
anchors.bottom: panel.top
anchors.left: parent.left
anchors.right: panel.right
height: suggestedModel.count > 6 ? Theme.itemSizeMedium * 6 : Theme.itemSizeMedium * suggestedModel.count
color: Theme.highlightDimmerColor
SilicaListView {
anchors.fill: parent
model: suggestedModel
clip: true
delegate: ItemUser {
onClicked: {
var start = toot.cursorPosition
while (toot.text[start] !== "@" && start > 0) {
start--
}
textOperations.text = toot.text
textOperations.cursorPosition = toot.cursorPosition
textOperations.moveCursorSelection(start - 1, TextInput.SelectWords)
toot.text = textOperations.text.substring(0, textOperations.selectionStart)
+ ' @'
+ model.account_acct
+ ' '
+ textOperations.text.substring(textOperations.selectionEnd).trim()
toot.cursorPosition = toot.text.indexOf('@' + model.account_acct)
}
}
onCountChanged: {
positionViewAtIndex(suggestedModel.count - 1, ListView.End)
}
}
}
DockedPanel {
id: panel
open: true
onExpandedChanged: {
if (!expanded) {
show()
}
}
width: parent.width
height: progressBar.height + toot.height + (mediaModel.count ? uploadedImages.height : 0)
+ btnContentWarning.height + Theme.paddingMedium
+ (warningContent.visible ? warningContent.height : 0)
dock: Dock.Bottom
Rectangle {
width: parent.width
height: progressBar.height
color: Theme.highlightBackgroundColor
opacity: 0.2
anchors {
left: parent.left
right: parent.right
top: parent.top
}
}
Rectangle {
id: progressBar
width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0
height: Theme.itemSizeSmall * 0.05
color: Theme.highlightBackgroundColor
opacity: 0.7
anchors {
left: parent.left
top: parent.top
}
}
TextField {
id: warningContent
visible: false
height: visible ? implicitHeight : 0
anchors {
top: parent.top
topMargin: Theme.paddingMedium
left: parent.left
right: parent.right
}
autoScrollEnabled: true
labelVisible: false
font.pixelSize: Theme.fontSizeSmall
placeholderText: qsTr("Write your warning here")
placeholderColor: palette.highlightColor
color: palette.highlightColor
horizontalAlignment: Text.AlignLeft
EnterKey.onClicked: {
//tweet()
}
}
TextInput {
id: textOperations
visible: false
}
TextArea {
id: toot
anchors {
top: warningContent.bottom
topMargin: Theme.paddingMedium
left: parent.left
right: parent.right
rightMargin: Theme.paddingLarge * 2
}
autoScrollEnabled: true
labelVisible: false
//focus: true
text: description !== "" && (description.charAt(0) == '@'
|| description.charAt(
0) == '#') ? description + ' ' : ''
height: Math.max(270, Math.min(900, implicitHeight))
horizontalAlignment: Text.AlignLeft
placeholderText: qsTr("What's on your mind?")
font.pixelSize: Theme.fontSizeSmall
EnterKey.onClicked: {
//tweet()
}
onTextChanged: {
textOperations.text = toot.text
textOperations.cursorPosition = toot.cursorPosition
textOperations.selectWord()
textOperations.select(
textOperations.selectionStart ? textOperations.selectionStart - 1 : 0,
textOperations.selectionEnd)
//console.log(textOperations.text.substr(textOperations.selectionStart, textOperations.selectionEnd))
console.log(toot.text.length)
suggestedUser = ""
if (textOperations.selectedText.charAt(0) === "@") {
suggestedUser = textOperations.selectedText.trim().substring(1)
}
}
}
IconButton {
id: btnSmileys
property string selection
onSelectionChanged: {
console.log(selection)
}
anchors {
top: warningContent.bottom
bottom: bottom.top
right: parent.right
rightMargin: Theme.paddingSmall
}
opacity: 0.8
icon.source: "../../qml/images/emojiselect.svg" + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor))
onClicked: pageStack.push(firstWizardPage)
}
SilicaGridView {
id: uploadedImages
width: parent.width
anchors.top: bottom.toot
anchors.bottom: parent.bottom
height: mediaModel.count ? Theme.itemSizeSmall : 0
model: mediaModel
cellWidth: uploadedImages.width / 4
cellHeight: Theme.itemSizeSmall
delegate: BackgroundItem {
id: myDelegate
width: uploadedImages.cellWidth
height: uploadedImages.cellHeight
RemorseItem {
id: remorse
}
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: model.preview_url
}
onClicked: {
var idx = index
console.log(idx)
//mediaModel.remove(idx)
remorse.execute(myDelegate, qsTr("Delete"), function () {
mediaModel.remove(idx)
})
}
}
add: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1.0
duration: 800
}
}
remove: Transition {
NumberAnimation {
property: "opacity"
from: 1.0
to: 0
duration: 800
}
}
displaced: Transition {
NumberAnimation {
properties: "x,y"
duration: 800
easing.type: Easing.InOutBack
}
}
}
IconButton {
id: btnContentWarning
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
left: parent.left
leftMargin: Theme.paddingMedium
}
icon.source: "image://theme/icon-s-warning?"
+ (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor))
onClicked: warningContent.visible = !warningContent.visible
}
IconButton {
id: btnAddImage
enabled: mediaModel.count < 4
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
left: btnContentWarning.right
leftMargin: Theme.paddingSmall
}
icon.source: "image://theme/icon-s-attach?"
+ (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor))
onClicked: {
btnAddImage.enabled = false
var once = true
var imagePicker = pageStack.push("Sailfish.Pickers.ImagePickerPage", {"allowedOrientations": Orientation.All})
imagePicker.selectedContentChanged.connect(function () {
var imagePath = imagePicker.selectedContent
console.log(imagePath)
imageUploader.setUploadUrl(Logic.conf.instance + "/api/v1/media")
imageUploader.setFile(imagePath)
imageUploader.setAuthorizationHeader(Logic.conf.api_user_token)
imageUploader.upload()
})
}
}
ImageUploader {
id: imageUploader
onProgressChanged: {
console.log("progress " + progress)
uploadProgress.width = parent.width * progress
}
onSuccess: {
uploadProgress.width = 0
console.log(replyData)
mediaModel.append(JSON.parse(replyData))
}
onFailure: {
uploadProgress.width = 0
btnAddImage.enabled = true
console.log(status)
console.log(statusText)
}
}
ComboBox {
id: privacy
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
left: btnAddImage.right
right: btnSend.left
}
menu: ContextMenu {
MenuItem {
text: qsTr("Public")
}
MenuItem {
text: qsTr("Unlisted")
}
MenuItem {
text: qsTr("Followers-only")
}
MenuItem {
text: qsTr("Direct")
}
}
}
IconButton {
id: btnSend
icon.source: "image://theme/icon-m-send?"
+ (pressed ? Theme.highlightColor : Theme.primaryColor)
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
right: parent.right
rightMargin: Theme.paddingSmall
}
enabled: toot.text !== "" && toot.text.length < tootMaxChar && uploadProgress.width == 0
onClicked: {
var visibility = ["public", "unlisted", "private", "direct"]
var media_ids = []
for (var k = 0; k < mediaModel.count; k++) {
console.log(mediaModel.get(k).id)
media_ids.push(mediaModel.get(k).id)
}
var msg = {
"action": 'statuses',
"method": 'POST',
"model": mdl,
"mode": "append",
"params": {
"status": toot.text,
"visibility": visibility[privacy.currentIndex],
"media_ids": media_ids
},
"conf": Logic.conf
}
if (toot_id)
msg.params['in_reply_to_id'] = (toot_id) + ""
if (warningContent.visible && warningContent.text.length > 0) {
msg.params['sensitive'] = 1
msg.params['spoiler_text'] = warningContent.text
}
worker.sendMessage(msg)
warningContent.text = ""
toot.text = ""
mediaModel.clear();
sentBanner.showText(qsTr("Toot sent!"))
}
}
Rectangle {
id: uploadProgress
color: Theme.highlightBackgroundColor
anchors.bottom: parent.bottom
anchors.left: parent.left
height: 3
}
}
Component.onCompleted: {
toot.cursorPosition = toot.text.length
if (mdl.count > 0) {
var setIndex = 0
switch (mdl.get(0).status_visibility) {
case "unlisted":
setIndex = 1
break
case "private":
setIndex = 2
break
case "direct":
privacy.enabled = false
setIndex = 3
break
default:
privacy.enabled = true
setIndex = 0
}
privacy.currentIndex = setIndex
}
console.log(JSON.stringify())
worker.sendMessage({
"action": 'statuses/' + mdl.get(0).status_id + '/context',
"method": 'GET',
"model": mdl,
"params": { },
"conf": Logic.conf
})
}
Component {
id: firstWizardPage
Dialog {
id: emoticonsDialog
canAccept: false //selector.currentIndex >= 0
//acceptDestination: conversationPage
onAcceptPendingChanged: {
if (acceptPending) {
// Tell the destination page what the selected category is
// acceptDestinationInstance.category = selector.value
}
}
SilicaGridView {
id: gridView
anchors.fill: parent
cellWidth: gridView.width / 6
cellHeight: cellWidth
header: PageHeader {
title: qsTr("Emojis")
description: qsTr("Tap to insert")
}
model: ListModel {
ListElement { section: "smileys"; glyph: "😁" }
ListElement { section: "smileys"; glyph: "😂" }
ListElement { section: "smileys"; glyph: "😃" }
ListElement { section: "smileys"; glyph: "😄" }
ListElement { section: "smileys"; glyph: "😅" }
ListElement { section: "smileys"; glyph: "😆" }
ListElement { section: "smileys"; glyph: "😉" }
ListElement { section: "smileys"; glyph: "😊" }
ListElement { section: "smileys"; glyph: "😋" }
ListElement { section: "smileys"; glyph: "😌" }
ListElement { section: "smileys"; glyph: "😍" }
ListElement { section: "smileys"; glyph: "😏" }
ListElement { section: "smileys"; glyph: "😒" }
ListElement { section: "smileys"; glyph: "😓" }
ListElement { section: "smileys"; glyph: "😔" }
ListElement { section: "smileys"; glyph: "😖" }
ListElement { section: "smileys"; glyph: "😘" }
ListElement { section: "smileys"; glyph: "😚" }
ListElement { section: "smileys"; glyph: "😜" }
ListElement { section: "smileys"; glyph: "😝" }
ListElement { section: "smileys"; glyph: "😞" }
ListElement { section: "smileys"; glyph: "😠" }
ListElement { section: "smileys"; glyph: "😡" }
ListElement { section: "smileys"; glyph: "😢" }
ListElement { section: "smileys"; glyph: "😣" }
ListElement { section: "smileys"; glyph: "😤" }
ListElement { section: "smileys"; glyph: "😥" }
ListElement { section: "smileys"; glyph: "😨" }
ListElement { section: "smileys"; glyph: "😩" }
ListElement { section: "smileys"; glyph: "😪" }
ListElement { section: "smileys"; glyph: "😫" }
ListElement { section: "smileys"; glyph: "😭" }
ListElement { section: "smileys"; glyph: "😰" }
ListElement { section: "smileys"; glyph: "😱" }
ListElement { section: "smileys"; glyph: "😲" }
ListElement { section: "smileys"; glyph: "😳" }
ListElement { section: "smileys"; glyph: "😵" }
ListElement { section: "smileys"; glyph: "😷" }
ListElement { section: "smileys"; glyph: "😸" }
ListElement { section: "smileys"; glyph: "😹" }
ListElement { section: "smileys"; glyph: "😺" }
ListElement { section: "smileys"; glyph: "😻" }
ListElement { section: "smileys"; glyph: "😼" }
ListElement { section: "smileys"; glyph: "😽" }
ListElement { section: "smileys"; glyph: "😾" }
ListElement { section: "smileys"; glyph: "😿" }
ListElement { section: "smileys"; glyph: "🙀" }
ListElement { section: "smileys"; glyph: "🙅" }
ListElement { section: "smileys"; glyph: "🙆" }
ListElement { section: "smileys"; glyph: "🙇" }
ListElement { section: "smileys"; glyph: "🙈" }
ListElement { section: "smileys"; glyph: "🙉" }
ListElement { section: "smileys"; glyph: "🙊" }
ListElement { section: "smileys"; glyph: "🙋" }
ListElement { section: "smileys"; glyph: "🙌" }
ListElement { section: "smileys"; glyph: "🙍" }
ListElement { section: "smileys"; glyph: "🙎" }
ListElement { section: "smileys"; glyph: "🙏" }
ListElement { section: "Transport and map"; glyph: "🚀" }
ListElement { section: "Transport and map"; glyph: "🚃" }
ListElement { section: "Transport and map"; glyph: "🚀" }
ListElement { section: "Transport and map"; glyph: "🚄" }
ListElement { section: "Transport and map"; glyph: "🚅" }
ListElement { section: "Transport and map"; glyph: "🚇" }
ListElement { section: "Transport and map"; glyph: "🚉" }
ListElement { section: "Transport and map"; glyph: "🚌" }
ListElement { section: "Transport and map"; glyph: "🚏" }
ListElement { section: "Transport and map"; glyph: "🚑" }
ListElement { section: "Transport and map"; glyph: "🚒" }
ListElement { section: "Transport and map"; glyph: "🚓" }
ListElement { section: "Transport and map"; glyph: "🚕" }
ListElement { section: "Transport and map"; glyph: "🚗" }
ListElement { section: "Transport and map"; glyph: "🚙" }
ListElement { section: "Transport and map"; glyph: "🚚" }
ListElement { section: "Transport and map"; glyph: "🚢" }
ListElement { section: "Transport and map"; glyph: "🚨" }
ListElement { section: "Transport and map"; glyph: "🚩" }
ListElement { section: "Transport and map"; glyph: "🚪" }
ListElement { section: "Transport and map"; glyph: "🚫" }
ListElement { section: "Transport and map"; glyph: "🚬" }
ListElement { section: "Transport and map"; glyph: "🚭" }
ListElement { section: "Transport and map"; glyph: "🚲" }
ListElement { section: "Transport and map"; glyph: "🚶" }
ListElement { section: "Transport and map"; glyph: "🚹" }
ListElement { section: "Transport and map"; glyph: "🚺" }
ListElement { section: "Transport and map"; glyph: "🚻" }
ListElement { section: "Transport and map"; glyph: "🚼" }
ListElement { section: "Transport and map"; glyph: "🚽" }
ListElement { section: "Transport and map"; glyph: "🚾" }
ListElement { section: "Transport and map"; glyph: "🛀" }
ListElement { section: "Horoscope Signs"; glyph: "♈" }
ListElement { section: "Horoscope Signs"; glyph: "♉" }
ListElement { section: "Horoscope Signs"; glyph: "♊" }
ListElement { section: "Horoscope Signs"; glyph: "♋" }
ListElement { section: "Horoscope Signs"; glyph: "♌" }
ListElement { section: "Horoscope Signs"; glyph: "♍" }
ListElement { section: "Horoscope Signs"; glyph: "♎" }
ListElement { section: "Horoscope Signs"; glyph: "♏" }
ListElement { section: "Horoscope Signs"; glyph: "♐" }
ListElement { section: "Horoscope Signs"; glyph: "♑" }
ListElement { section: "Horoscope Signs"; glyph: "♒" }
ListElement { section: "Horoscope Signs"; glyph: "♓" }
}
delegate: BackgroundItem {
width: gridView.cellWidth
height: gridView.cellHeight
Label {
anchors.centerIn: parent
color: (highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor)
font.pixelSize: Theme.fontSizeLarge
text: glyph
}
onClicked: {
var cursorPosition = toot.cursorPosition
toot.text = toot.text.substring(
0, cursorPosition) + model.glyph + toot.text.substring(
cursorPosition)
toot.cursorPosition = cursorPosition + model.glyph.length
emoticonsDialog.canAccept = true
emoticonsDialog.accept()
}
}
}
}
}
}

View file

@ -0,0 +1,585 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import harbour.tooterb.Uploader 1.0
import "../lib/API.js" as Logic
import "./components/"
Page {
id: conversationPage
property ListModel suggestedModel
property ListModel mdl
property int tootMaxChar: 500
property bool bot: false //otherwise ReferenceError ProfileHeader.qml
property bool followed_by: false //otherwise ReferenceError ProfileHeader.qml
property bool locked: false //otherwise ReferenceError ProfileHeader.qml
property bool group: false //otherwise ReferenceError ProfileHeader.qml
property string type
property string username: ""
property string headerTitle: ""
property string suggestedUser: ""
property string status_id: ""
property string status_url: ""
property string status_uri: ""
property string status_link:
if (status_url === "") {
var test = status_uri.split("/")
console.log(status_uri)
console.log(JSON.stringify(test))
console.log(JSON.stringify(test.length))
if (test.length === 8 && (test[7] === "activity")) {
var urialt = status_uri.replace("activity", "")
status_link = urialt
}
else status_link = status_uri
} else status_link = status_url
allowedOrientations: Orientation.All
onSuggestedUserChanged: {
console.log(suggestedUser)
suggestedModel = Qt.createQmlObject( 'import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject' )
predictionList.visible = false
if (suggestedUser.length > 0) {
var msg = {
"action": 'accounts/search',
"method": 'GET',
"model": suggestedModel,
"mode": "append",
"params": [{
"name": "q",
"data": suggestedUser
}],
"conf": Logic.conf
}
worker.sendMessage(msg)
predictionList.visible = true
}
}
ListModel {
id: mediaModel
onCountChanged: {
btnAddImage.enabled = mediaModel.count < 4
}
}
WorkerScript {
id: worker
source: "../lib/Worker.js"
onMessage: { console.log(JSON.stringify(messageObject)) }
}
SilicaListView {
id: myList
header: PageHeader {
title: headerTitle // pageTitle pushed from MainPage.qml or VisualContainer.qml
}
clip: true
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: if (panel.open == true) {
panel.top
} else {
hiddenPanel.top
}
model: mdl
section {
property: 'section'
delegate: SectionHeader {
height: Theme.itemSizeExtraSmall
text: Format.formatDate(section, Formatter.DateMedium)
}
}
delegate: VisualContainer {}
onCountChanged: {
if (mdl)
for (var i = 0; i < mdl.count; i++) {
if (mdl.get(i).status_id === status_id) {
console.log(mdl.get(i).status_id)
positionViewAtIndex(i, ListView.Center)
}
}
}
PullDownMenu {
id: pulleyConversation
visible: type === "reply"
MenuItem {
text: qsTr("Open in Browser")
onClicked: {
Qt.openUrlExternally(status_link)
}
}
MenuItem {
//: Use the translation of "Copy Link" for a shorter PullDownMenu label
text: qsTr("Copy Link to Clipboard")
onClicked: Clipboard.text = status_link
}
MenuItem {
//: "Reply" will show the Toot text entry Panel. "Hide Reply" closes it. Alternative: Use "Close Reply"
text: !panel.open ? qsTr("Reply") : qsTr("Hide Reply")
visible: type == "reply"
onClicked: !panel.open ? panel.open = true : panel.open = false
}
}
}
Rectangle {
id: predictionList
visible: false
color: Theme.highlightDimmerColor
height: parent.height - panel.height - (Theme.paddingLarge * 4.5)
anchors {
left: panel.left
right: panel.right
bottom: panel.open == true ? panel.top : hiddenPanel.top
}
SilicaListView {
id: predictionResults
rotation: 180 // shows best matching result on the bottom
anchors.fill: parent
model: suggestedModel
clip: true
quickScroll: false
delegate: ItemUser {
rotation: 180
onClicked: {
var start = toot.cursorPosition
while (toot.text[start] !== "@" && start > 0) {
start--
}
textOperations.text = toot.text
textOperations.cursorPosition = toot.cursorPosition
textOperations.moveCursorSelection(start - 1, TextInput.SelectWords)
toot.text = textOperations.text.substring(0, textOperations.selectionStart)
+ ' @'
+ model.account_acct
+ ' '
+ textOperations.text.substring(textOperations.selectionEnd).trim()
toot.cursorPosition = toot.text.indexOf('@' + model.account_acct)
}
}
onCountChanged: {
if (count > 0) {
positionViewAtBeginning(suggestedModel.count - 1, ListView.Beginning)
}
}
VerticalScrollDecorator {}
}
}
DockedPanel {
id: panel
width: parent.width
height: progressBar.height + toot.height + (mediaModel.count ? uploadedImages.height : 0) + btnContentWarning.height + Theme.paddingMedium + (warningContent.visible ? warningContent.height : 0)
dock: Dock.Bottom
open: true
Rectangle {
id: progressBarBg
width: parent.width
height: progressBar.height
color: Theme.highlightBackgroundColor
opacity: 0.2
anchors {
left: parent.left
right: parent.right
top: parent.top
}
}
Rectangle {
id: progressBar
width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0
height: Theme.itemSizeSmall * 0.05
color: Theme.highlightBackgroundColor
opacity: 0.7
anchors {
left: parent.left
top: parent.top
}
}
TextField {
id: warningContent
visible: false
height: visible ? implicitHeight : 0
autoScrollEnabled: true
labelVisible: false
font.pixelSize: Theme.fontSizeSmall
//: placeholderText in Toot content warning panel
placeholderText: qsTr("Write your warning here")
placeholderColor: palette.highlightColor
color: palette.highlightColor
horizontalAlignment: Text.AlignLeft
EnterKey.onClicked: {}
anchors {
top: parent.top
topMargin: Theme.paddingMedium
left: parent.left
right: parent.right
}
}
TextInput {
id: textOperations
visible: false
}
TextArea {
id: toot
autoScrollEnabled: true
labelVisible: false
//: placeholderText in Toot text panel
placeholderText: qsTr("What's on your mind?")
font.pixelSize: Theme.fontSizeSmall
text: username !== "" && (username.charAt(0) === '@'
|| username.charAt(
0) === '#') ? username + ' ' : ''
height: if (type !== "reply") {
isPortrait ? Math.max(conversationPage.height / 3, Math.min(conversationPage.height * 0.65, implicitHeight)) : Math.max(conversationPage.height / 2, Math.min(conversationPage.height * 0.65, implicitHeight))
}
else {
isPortrait ? Math.max(conversationPage.height / 4, Math.min(conversationPage.height * 0.65, implicitHeight)) : Math.max(conversationPage.height / 2.5, Math.min(conversationPage.height * 0.65, implicitHeight))
}
horizontalAlignment: Text.AlignLeft
anchors {
top: warningContent.bottom
topMargin: Theme.paddingMedium
left: parent.left
right: parent.right
rightMargin: Theme.paddingLarge * 2
}
EnterKey.onClicked: {}
onTextChanged: {
textOperations.text = toot.text
textOperations.cursorPosition = toot.cursorPosition
textOperations.selectWord()
textOperations.select(
textOperations.selectionStart ? textOperations.selectionStart - 1 : 0,
textOperations.selectionEnd)
console.log(toot.text.length)
suggestedUser = ""
if (textOperations.selectedText.charAt(0) === "@") {
suggestedUser = textOperations.selectedText.trim().substring(1)
}
}
}
IconButton {
id: btnSmileys
property string selection
opacity: 0.7
icon {
source: "../../qml/images/icon-m-emoji.svg?"
color: Theme.secondaryColor
width: Theme.iconSizeSmallPlus
fillMode: Image.PreserveAspectFit
}
anchors {
top: warningContent.bottom
bottom: bottom.top
right: parent.right
rightMargin: Theme.paddingSmall
}
onSelectionChanged: { console.log(selection) }
onClicked: pageStack.push(emojiDialog)
}
SilicaGridView {
id: uploadedImages
width: parent.width
anchors.top: bottom.toot
anchors.bottom: parent.bottom
height: mediaModel.count ? Theme.itemSizeExtraLarge : 0
model: mediaModel
cellWidth: uploadedImages.width / 4
cellHeight: isPortrait ? cellWidth : Theme.itemSizeExtraLarge
delegate: BackgroundItem {
id: myDelegate
width: uploadedImages.cellWidth
height: uploadedImages.cellHeight
RemorseItem {
id: remorse
cancelText: ""
}
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: model.preview_url
}
onClicked: {
var idx = index
console.log(idx)
//mediaModel.remove(idx)
remorse.execute(myDelegate, "", function () {
mediaModel.remove(idx)
})
}
}
add: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1.0
duration: 800
}
}
remove: Transition {
NumberAnimation {
property: "opacity"
from: 1.0
to: 0
duration: 800
}
}
displaced: Transition {
NumberAnimation {
properties: "x,y"
duration: 800
easing.type: Easing.InOutBack
}
}
}
IconButton {
id: btnContentWarning
icon.source: "image://theme/icon-s-warning?" + ( pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor) )
onClicked: warningContent.visible = !warningContent.visible
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
left: parent.left
leftMargin: Theme.paddingMedium
}
}
IconButton {
id: btnAddImage
enabled: mediaModel.count < 4
icon.source: "image://theme/icon-s-attach?" + ( pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor) )
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
left: btnContentWarning.right
leftMargin: Theme.paddingSmall
}
onClicked: {
btnAddImage.enabled = false
var once = true
var imagePicker = pageStack.push("Sailfish.Pickers.ImagePickerPage", { "allowedOrientations": Orientation.All })
imagePicker.selectedContentChanged.connect(function () {
var imagePath = imagePicker.selectedContent
console.log(imagePath)
imageUploader.setUploadUrl(Logic.conf.instance + "/api/v1/media")
imageUploader.setFile(imagePath)
imageUploader.setAuthorizationHeader(Logic.conf.api_user_token)
imageUploader.upload()
})
}
}
ImageUploader {
id: imageUploader
onProgressChanged: {
console.log("progress " + progress)
uploadProgress.width = parent.width * progress
}
onSuccess: {
uploadProgress.width = 0
console.log(replyData)
mediaModel.append(JSON.parse(replyData))
}
onFailure: {
uploadProgress.width = 0
btnAddImage.enabled = true
console.log(status)
console.log(statusText)
}
}
ComboBox {
id: privacy
menu: ContextMenu {
MenuItem {
text: qsTr("Public")
}
MenuItem {
text: qsTr("Unlisted")
}
MenuItem {
text: qsTr("Followers-only")
}
MenuItem {
text: qsTr("Direct")
}
}
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
left: btnAddImage.right
right: btnSend.left
}
}
IconButton {
id: btnSend
icon.source: "image://theme/icon-m-send?" + (pressed ? Theme.highlightColor : Theme.primaryColor)
enabled: toot.text !== "" && toot.text.length < tootMaxChar && uploadProgress.width == 0
anchors {
top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5
right: parent.right
rightMargin: Theme.paddingSmall
}
onClicked: {
var visibility = ["public", "unlisted", "private", "direct"]
var media_ids = []
for (var k = 0; k < mediaModel.count; k++) {
console.log(mediaModel.get(k).id)
media_ids.push(mediaModel.get(k).id)
}
var msg = {
"action": 'statuses',
"method": 'POST',
"model": mdl,
"mode": "append",
"params": {
"status": toot.text,
"visibility": visibility[privacy.currentIndex],
"media_ids": media_ids
},
"conf": Logic.conf
}
if (status_id)
msg.params['in_reply_to_id'] = (status_id) + ""
if (warningContent.visible && warningContent.text.length > 0) {
msg.params['sensitive'] = 1
msg.params['spoiler_text'] = warningContent.text
}
worker.sendMessage(msg)
warningContent.text = ""
toot.text = ""
mediaModel.clear()
sentBanner.showText(qsTr("Toot sent!"))
}
}
Rectangle {
id: uploadProgress
color: Theme.highlightBackgroundColor
height: Theme.itemSizeSmall * 0.05
anchors {
bottom: parent.bottom
left: parent.left
}
}
}
Component.onCompleted: {
toot.cursorPosition = toot.text.length
if (mdl.count > 0) {
var setIndex = 0
switch (mdl.get(0).status_visibility) {
case "unlisted":
setIndex = 1
break
case "private":
setIndex = 2
break
case "direct":
privacy.enabled = false
setIndex = 3
break
default:
privacy.enabled = true
setIndex = 0
}
privacy.currentIndex = setIndex
}
console.log(JSON.stringify())
worker.sendMessage({
"action": 'statuses/' + mdl.get(0).status_id + '/context',
"method": 'GET',
"model": mdl,
"params": { },
"conf": Logic.conf
})
}
BackgroundItem {
id: hiddenPanel
visible: !panel.open
height: Theme.paddingLarge * 0.7
width: parent.width
opacity: enabled ? 0.6 : 0.0
Behavior on opacity { FadeAnimator { duration: 400 } }
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
}
MouseArea {
anchors.fill: parent
onClicked: panel.open = !panel.open
}
Rectangle {
id: hiddenPanelBackground
width: parent.width
height: parent.height
color: Theme.highlightBackgroundColor
opacity: 0.4
anchors.fill: parent
}
Rectangle {
id: progressBarBackground
width: parent.width
height: progressBarHiddenPanel.height
color: Theme.highlightBackgroundColor
opacity: 0.2
anchors {
top: parent.top
left: parent.left
right: parent.right
}
}
Rectangle {
id: progressBarHiddenPanel
width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0
height: Theme.itemSizeSmall * 0.05
color: Theme.highlightBackgroundColor
opacity: 0.7
anchors {
top: parent.top
left: parent.left
}
}
}
EmojiSelect {
id: emojiDialog
}
InfoBanner {
id: sentBanner
}
}

View file

@ -1,33 +1,3 @@
/*
Copyright (C) 2013 Jolla Ltd.
Contact: Thomas Perl <thomas.perl@jollamobile.com>
All rights reserved.
You may use this file under the terms of BSD license as follows:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Jolla Ltd nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import QtQuick 2.0
import QtWebKit 3.0
import Sailfish.Silica 1.0
@ -61,86 +31,82 @@ Page {
focus: true
label: qsTr("Enter a valid Mastodon instance URL")
text: "https://"
placeholderText: "https://mastodon.social"
width: parent.width
validator: RegExpValidator { regExp: /^(ftp|http|https):\/\/[^ "]+$/ }
EnterKey.enabled: instance.acceptableInput;
EnterKey.highlighted: instance.acceptableInput;
EnterKey.iconSource: "image://theme/icon-m-accept"
EnterKey.onClicked: {
Logic.api = new Logic.MastodonAPI({ instance: instance.text, api_user_token: "" });
Logic.api = Logic.mastodonAPI({ instance: instance.text, api_user_token: "" });
Logic.api.registerApplication("Tooter",
'http://localhost/harbour-tooter', // redirect uri, we will need this later on
["read", "write", "follow"], //scopes
"http://grave-design.com/harbour-tooter", //website on the login screen
function(data) {
'http://localhost/harbour-tooter', // redirect uri, we will need this later on
["read", "write", "follow"], //scopes
"http://grave-design.com/harbour-tooter", //website on the login screen
function(data) {
console.log(data)
var conf = JSON.parse(data)
conf.instance = instance.text;
conf.login = false;
console.log(data)
var conf = JSON.parse(data)
conf.instance = instance.text;
conf.login = false;
/*conf['login'] = false;
conf['mastodon_client_id'] = data['mastodon_client_id'];
conf['mastodon_client_secret'] = data['mastodon_client_secret'];
conf['mastodon_client_redirect_uri'] = data['mastodon_client_redirect_uri'];
delete Logic.conf;*/
Logic.conf = conf;
console.log(JSON.stringify(conf))
console.log(JSON.stringify(Logic.conf))
// we got our application
/*conf['login'] = false;
conf['mastodon_client_id'] = data['mastodon_client_id'];
conf['mastodon_client_secret'] = data['mastodon_client_secret'];
conf['mastodon_client_redirect_uri'] = data['mastodon_client_redirect_uri'];
delete Logic.conf;*/
Logic.conf = conf;
console.log(JSON.stringify(conf))
console.log(JSON.stringify(Logic.conf))
// we got our application
// our user to it!
var url = Logic.api.generateAuthLink(Logic.conf["client_id"],
Logic.conf["redirect_uri"],
"code", // oauth method
["read", "write", "follow"] //scopes
);
console.log(url)
webView.url = url
webView.visible = true
}
);
// our user to it!
var url = Logic.api.generateAuthLink(Logic.conf["client_id"],
Logic.conf["redirect_uri"],
"code", // oauth method
["read", "write", "follow"] //scopes
);
console.log(url)
webView.url = url
webView.visible = true
}
);
}
}
Label {
id: serviceDescr
text: qsTr("Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust — whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
wrapMode: Text.WordWrap
width: parent.width
anchors {
left: parent.left
right: parent.right
topMargin: Theme.paddingMedium
left: parent.left
leftMargin: Theme.horizontalPageMargin
right: parent.right
rightMargin: Theme.horizontalPageMargin
}
width: parent.width
wrapMode: Text.WordWrap
color: Theme.highlightColor
font.pixelSize: Theme.fontSizeExtraSmall
text: qsTr("Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust — whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.")
}
}
}
SilicaWebView {
id: webView
visible: false
opacity: 0
anchors {
top: parent.top
left: parent.left
right: parent.right
bottom: parent.bottom
}
opacity: 0
onLoadingChanged: {
console.log(url)
if (
(url+"").substr(0, 37) === 'http://localhost/harbour-tooter?code=' ||
(url+"").substr(0, 38) === 'https://localhost/harbour-tooter?code='
) {
) {
visible = false;
var vars = {};
@ -151,22 +117,22 @@ Page {
console.log(authCode)
Logic.api.getAccessTokenFromAuthCode(
Logic.conf["client_id"],
Logic.conf["client_secret"],
Logic.conf["redirect_uri"],
authCode,
function(data) {
// AAAND DATA CONTAINS OUR TOKEN!
console.log(data)
data = JSON.parse(data)
console.log(JSON.stringify(data))
console.log(JSON.stringify(data.access_token))
Logic.conf["api_user_token"] = data.access_token
Logic.conf["login"] = true;
Logic.api.setConfig("api_user_token", Logic.conf["api_user_token"])
pageStack.replace(Qt.resolvedUrl("MainPage.qml"), {})
}
)
Logic.conf["client_id"],
Logic.conf["client_secret"],
Logic.conf["redirect_uri"],
authCode,
function(data) {
// AAAND DATA CONTAINS OUR TOKEN!
console.log(data)
data = JSON.parse(data)
console.log(JSON.stringify(data))
console.log(JSON.stringify(data.access_token))
Logic.conf["api_user_token"] = data.access_token
Logic.conf["login"] = true;
Logic.api.setConfig("api_user_token", Logic.conf["api_user_token"])
pageStack.replace(Qt.resolvedUrl("MainPage.qml"), {})
}
)
}
@ -185,6 +151,7 @@ Page {
}
FadeAnimation on opacity {}
PullDownMenu {
MenuItem {
text: qsTr("Reload")
@ -193,4 +160,3 @@ Page {
}
}
}

View file

@ -1,33 +1,3 @@
/*
Copyright (C) 2013 Jolla Ltd.
Contact: Thomas Perl <thomas.perl@jollamobile.com>
All rights reserved.
You may use this file under the terms of BSD license as follows:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Jolla Ltd nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../lib/API.js" as Logic
@ -36,19 +6,21 @@ import "./components/"
Page {
id: mainPage
property bool isFirstPage: true
property bool isTablet: true; //Screen.sizeCategory >= Screen.Large
// The effective value will be restricted by ApplicationWindow.allowedOrientations
property bool isFirstPage: true
property bool isTablet: true //Screen.sizeCategory >= Screen.Large
allowedOrientations: Orientation.All
// Docked Navigation panel
DockedPanel {
id: infoPanel
open: true
width: mainPage.isPortrait ? parent.width : Theme.itemSizeLarge
height: mainPage.isPortrait ? Theme.itemSizeLarge : parent.height
dock: mainPage.isPortrait ? Dock.Bottom : Dock.Right
Navigation {
width: isPortrait ? parent.width : Theme.itemSizeLarge
height: isPortrait ? Theme.itemSizeLarge : parent.height
dock: isPortrait ? Dock.Bottom : Dock.Right
NavigationPanel {
id: navigation
isPortrait: !mainPage.isPortrait
onSlideshowShow: {
@ -60,66 +32,79 @@ Page {
VisualItemModel {
id: visualModel
MyList{
id: tlHome;
MyList {
id: tlHome
title: qsTr("Home")
type: "timelines/home"
mdl: Logic.modelTLhome
width: parent.itemWidth
width: isPortrait ? parent.itemWidth : parent.itemWidth - Theme.itemSizeLarge
height: parent.itemHeight
onOpenDrawer: infoPanel.open = setDrawer
onOpenDrawer: isPortrait ? infoPanel.open = setDrawer : infoPanel.open = true
}
MyList{
id: tlNotifications;
MyList {
id: tlNotifications
title: qsTr("Notifications")
type: "notifications"
notifier: true
mdl: Logic.modelTLnotifications
width: parent.itemWidth
width: isPortrait ? parent.itemWidth : parent.itemWidth - Theme.itemSizeLarge
height: parent.itemHeight
onOpenDrawer: infoPanel.open = setDrawer
onOpenDrawer: isPortrait ? infoPanel.open = setDrawer : infoPanel.open = true
}
MyList{
id: tlLocal;
MyList {
id: tlLocal
title: qsTr("Local")
type: "timelines/public?local=true"
//params: ["local", true]
mdl: Logic.modelTLlocal
width: parent.itemWidth
width: isPortrait ? parent.itemWidth : parent.itemWidth - Theme.itemSizeLarge
height: parent.itemHeight
onOpenDrawer: infoPanel.open = setDrawer
onOpenDrawer: isPortrait ? infoPanel.open = setDrawer : infoPanel.open = true
}
MyList{
id: tlPublic;
MyList {
id: tlPublic
title: qsTr("Federated")
type: "timelines/public"
mdl: Logic.modelTLpublic
width: parent.itemWidth
width: isPortrait ? parent.itemWidth : parent.itemWidth - Theme.itemSizeLarge
height: parent.itemHeight
onOpenDrawer: infoPanel.open = setDrawer
onOpenDrawer: isPortrait ? infoPanel.open = setDrawer : infoPanel.open = true
}
Item {
id: tlSearch;
width: parent.itemWidth
height: parent.itemHeight
id: tlSearch
property ListModel mdl: ListModel {}
property string search;
property string search
width: isPortrait ? parent.itemWidth : parent.itemWidth - Theme.itemSizeLarge
height: parent.itemHeight
onSearchChanged: {
console.log(search)
loader.sourceComponent = loading
loader.sourceComponent = search.charAt(0) === "@" ? userListComponent : tagListComponent
if (search.charAt(0) === "@") {
loader.sourceComponent = userListComponent
} else if (search.charAt(0) === "#") {
loader.sourceComponent = tagListComponent
} else loader.sourceComponent = wordListComponent
}
Loader {
id: loader
anchors.fill: parent
}
Column {
id: headerContainer
width: tlSearch.width
PageHeader {
title: qsTr("Search")
}
SearchField {
id: searchField
width: parent.width
@ -133,6 +118,7 @@ Page {
}
}
}
Component {
id: loading
BusyIndicator {
@ -141,6 +127,7 @@ Page {
running: true
}
}
Component {
id: tagListComponent
MyList {
@ -148,7 +135,7 @@ Page {
mdl: ListModel {}
width: parent.width
height: parent.height
onOpenDrawer: infoPanel.open = setDrawer
onOpenDrawer: isPortrait ? infoPanel.open = setDrawer : infoPanel.open = true
anchors.fill: parent
currentIndex: -1 // otherwise currentItem will steal focus
header: Item {
@ -165,6 +152,7 @@ Page {
}
}
}
Component {
id: userListComponent
MyList {
@ -185,15 +173,24 @@ Page {
delegate: ItemUser {
onClicked: {
pageStack.push(Qt.resolvedUrl("Profile.qml"), {
pageStack.push(Qt.resolvedUrl("ProfilePage.qml"), {
"display_name": model.account_display_name,
"username": model.account_acct,
"user_id": model.account_id,
"profileImage": model.account_avatar,
"profileBackground": model.account_header
"profileBackground": model.account_header,
"note": model.account_note,
"url": model.account_url,
"followers_count": model.account_followers_count,
"following_count": model.account_following_count,
"statuses_count": model.account_statuses_count,
"locked": model.account_locked,
"bot": model.account_bot,
"group": model.account_group
})
}
}
Component.onCompleted: {
view2.type = "accounts/search"
view2.params = []
@ -203,11 +200,33 @@ Page {
}
}
Component {
id: wordListComponent
MyList {
id: view3
mdl: ListModel {}
width: parent.width
height: parent.height
onOpenDrawer: infoPanel.open = setDrawer
anchors.fill: parent
currentIndex: -1 // otherwise currentItem will steal focus
header: Item {
id: header
width: headerContainer.width
height: headerContainer.height
Component.onCompleted: headerContainer.parent = header
}
delegate: VisualContainer
Component.onCompleted: {
view3.type = "timelines/tag/"+tlSearch.search
view3.loadData("append")
}
}
}
}
}
SlideshowView {
id: slideshow
width: parent.width
@ -215,44 +234,41 @@ Page {
itemWidth: isTablet ? Math.round(parent.width) : parent.width
itemHeight: height
clip: true
model: visualModel
onCurrentIndexChanged: {
navigation.slideshowIndexChanged(currentIndex)
}
anchors {
fill: parent
leftMargin: 0
top: parent.top
topMargin: 0
rightMargin: mainPage.isPortrait ? 0 : infoPanel.visibleSize
bottomMargin: mainPage.isPortrait ? infoPanel.visibleSize : 0
rightMargin: isPortrait ? 0 : infoPanel.visibleSize
bottomMargin: isPortrait ? infoPanel.visibleSize : 0
}
model: visualModel
Component.onCompleted: {
}
}
IconButton {
anchors {
right: (mainPage.isPortrait ? parent.right : infoPanel.left)
bottom: (mainPage.isPortrait ? infoPanel.top : parent.bottom)
margins: {
left: Theme.paddingLarge
bottom: Theme.paddingLarge
}
}
id: newTweet
id: newToot
width: Theme.iconSizeLarge
height: width
visible: !isPortrait ? true : !infoPanel.open
icon.source: "image://theme/icon-l-add"
anchors {
right: (mainPage.isPortrait ? parent.right : infoPanel.left)
rightMargin: isPortrait ? Theme.paddingLarge : Theme.paddingLarge * 0.8
bottom: (mainPage.isPortrait ? infoPanel.top : parent.bottom)
bottomMargin: Theme.paddingLarge
}
onClicked: {
pageStack.push(Qt.resolvedUrl("Conversation.qml"), {headerTitle: qsTr("New Toot"), type: "new"})
pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
headerTitle: qsTr("New Toot"),
type: "new"
})
}
}
function onLinkActivated(href){
function onLinkActivated(href) {
var test = href.split("/")
console.log(href)
console.log(JSON.stringify(test))
@ -268,11 +284,11 @@ Page {
navigation.navigateTo('search')
} else {
Qt.openUrlExternally(href);
Qt.openUrlExternally(href)
}
}
Component.onCompleted: {
console.log("aaa")
}
}

View file

@ -1,305 +0,0 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../lib/API.js" as Logic
import "./components/"
import QtGraphicalEffects 1.0
Page {
property ListModel tweets;
property string display_name : "";
property string username : "";
property string profileImage : "";
property int user_id;
property int statuses_count;
property int following_count;
property int followers_count;
property int favourites_count;
property int reblogs_count;
property int count_moments;
property string profileBackground: "";
property string note: "";
property string url: "";
property bool locked : false;
property date created_at;
property bool following : false;
property bool requested : false;
property bool followed_by : false;
property bool blocking : false;
property bool muting : false;
property bool domain_blocking : false;
WorkerScript {
id: worker
source: "../lib/Worker.js"
onMessage: {
console.log(JSON.stringify(messageObject))
if(messageObject.action.indexOf("accounts/search") > -1 ){
user_id = messageObject.data.id
followers_count = messageObject.data.followers_count
following_count = messageObject.data.following_count
username = messageObject.data.acct
display_name = messageObject.data.display_name
profileImage = messageObject.data.avatar_static
profileBackground = messageObject.data.header_static
var msg = {
'action' : "accounts/relationships/",
'params' : [ {name: "id", data: user_id}],
'conf' : Logic.conf
};
worker.sendMessage(msg);
list.loadData("prepend")
}
if(messageObject.action === "accounts/relationships/"){
console.log(JSON.stringify(messageObject))
following= messageObject.data.following
requested= messageObject.data.requested
followed_by= messageObject.data.followed_by
blocking= messageObject.data.blocking
muting= messageObject.data.muting
domain_blocking= messageObject.data.domain_blocking
}
switch (messageObject.key) {
case 'followers_count':
followers_count = messageObject.data
break;
case 'following_count':
following_count = messageObject.data
break;
case 'acct':
// line below was commented out, reason unknown
// username = messageObject.data
break;
case 'locked':
locked = messageObject.data
break;
case 'created_at':
created_at = messageObject.data
break;
case 'statuses_count':
statuses_count = messageObject.data
break;
case 'note':
note = messageObject.data
break;
case 'url':
url = messageObject.data
break;
case 'following':
following = messageObject.data
followers_count = followers_count + (following ? 1 : - 1)
break;
case 'muting':
muting = messageObject.data
break;
case 'muting':
muting = messageObject.data
break;
case 'blocking':
blocking = messageObject.data
followers_count = followers_count + (blocking ? -1 : 0)
break;
case 'followed_by':
followed_by = messageObject.data
break;
}
}
}
// The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All
Component.onCompleted: {
var msg;
if (user_id) {
msg = {
'action' : "accounts/relationships/",
'params' : [ {name: "id", data: user_id}],
'conf' : Logic.conf
};
worker.sendMessage(msg);
msg = {
'action' : "accounts/"+user_id,
'conf' : Logic.conf
};
worker.sendMessage(msg);
} else {
var instance = Logic.conf['instance'].split("//")
msg = {
'action' : "accounts/search?limit=1&q="+username.replace("@"+instance[1], ""),
'conf' : Logic.conf
};
worker.sendMessage(msg);
}
}
MyList {
id: list
header: ProfileHeader {
id: header
title: display_name
description: username
image: profileImage
bg: profileBackground
}
anchors {
top: parent.top
bottom: expander.top
left: parent.left
right: parent.right
}
clip: true
mdl: ListModel {}
type: "accounts/"+user_id+"/statuses"
vars: {}
conf: Logic.conf
}
ExpandingSectionGroup {
id: expander
//currentIndex: 0
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
ExpandingSection {
title: qsTr("Summary")
content.sourceComponent: Column {
spacing: Theme.paddingMedium
anchors.bottomMargin: Theme.paddingLarge
DetailItem {
visible: followers_count ? true : false
label: qsTr("Followers")
value: followers_count
}
DetailItem {
visible: following_count ? true : false
label: qsTr("Following")
value: (following_count)
}
DetailItem {
visible: statuses_count ? true : false
label: qsTr("Statuses")
value: (statuses_count)
}
DetailItem {
visible: favourites_count ? true : false
label: qsTr("Favourites")
value: (favourites_count)
}
Column {
spacing: Theme.paddingMedium
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: btnFollow
text: (following ? qsTr("Unfollow") : (requested ? qsTr("Follow request sent!") : qsTr("Follow")))
onClicked: {
var msg = {
'method' : 'POST',
'params' : [],
'action' : "accounts/" + user_id + (following ? '/unfollow':'/follow'),
'conf' : Logic.conf
};
worker.sendMessage(msg);
}
}
Button {
id: btnMute
text: (muting ? qsTr("Unmute") : qsTr("Mute"))
onClicked: {
var msg = {
'method' : 'POST',
'params' : [],
'action' : "accounts/" + user_id + (muting ? '/unmute':'/mute'),
'conf' : Logic.conf
};
worker.sendMessage(msg);
}
}
Button {
id: btnBlock
text: (blocking ? qsTr("Unblock") : qsTr("Block") )
onClicked: {
var msg = {
'method' : 'POST',
'params' : [],
'action' : "accounts/" + user_id + (blocking ? '/unblock':'/block'),
'conf' : Logic.conf
};
worker.sendMessage(msg);
}
}
}
Label {
text: " "
}
}
}
ExpandingSection {
title: qsTr("Bio")
content.sourceComponent: Column {
spacing: Theme.paddingMedium
anchors.bottomMargin: Theme.paddingLarge
Text {
x: Theme.horizontalPageMargin
width: parent.width - ( 2 * Theme.horizontalPageMargin )
id: txtnote
text: note
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.secondaryColor
linkColor: Theme.secondaryHighlightColor
wrapMode: Text.Wrap
anchors {
horizontalCenter: parent.horizontalCenter
}
onLinkActivated: {
var test = link.split("/")
console.log(link)
console.log(JSON.stringify(test))
console.log(JSON.stringify(test.length))
if (test.length === 5 && (test[3] === "tags" || test[3] === "tag") ) {
pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true;
if (check)
page.onLinkActivated(link)
return check;
}));
send(link)
// function still missing for user accounts
// } else if (test.length === 4 && test[3][0] === "@" ) {
} else {
Qt.openUrlExternally(link);
}
}
}
Column {
spacing: Theme.paddingMedium
anchors.horizontalCenter: parent.horizontalCenter
Button {
text: qsTr("Open Profile in Browser")
onClicked: {
Qt.openUrlExternally(url);
}
}
}
Label {
text: " "
}
}
}
}
}

360
qml/pages/ProfilePage.qml Normal file
View file

@ -0,0 +1,360 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0
import "../lib/API.js" as Logic
import "./components/"
Page {
id: profilePage
property ListModel tweets
property string display_name: ""
property string username: ""
property string profileImage: ""
property string profileBackground: ""
property string note: ""
property string url: ""
property string user_id: ""
property int statuses_count
property int following_count
property int followers_count
property bool locked: false
property bool bot: false
property bool group: false
property bool following: false
property bool followed_by: false
property bool requested: false
property bool blocking: false
property bool muting: false
property bool domain_blocking: false
property date created_at
WorkerScript {
id: worker
source: "../lib/Worker.js"
onMessage: {
console.log(JSON.stringify(messageObject))
if(messageObject.action.indexOf("accounts/search") > -1 ){
user_id = messageObject.data.id
followers_count = messageObject.data.followers_count
following_count = messageObject.data.following_count
username = messageObject.data.acct
display_name = messageObject.data.display_name
profileImage = messageObject.data.avatar_static
profileBackground = messageObject.data.header_static
var msg = {
'action' : "accounts/relationships/",
'params' : [ {name: "id", data: user_id}],
'conf' : Logic.conf
};
worker.sendMessage(msg);
list.loadData("prepend")
}
if(messageObject.action === "accounts/relationships/"){
console.log(JSON.stringify(messageObject))
following = messageObject.data.following
requested = messageObject.data.requested
followed_by = messageObject.data.followed_by
blocking = messageObject.data.blocking
muting = messageObject.data.muting
domain_blocking = messageObject.data.domain_blocking
}
switch (messageObject.key) {
case 'followers_count':
followers_count = messageObject.data
break;
case 'following_count':
following_count = messageObject.data
break;
/* case 'acct':
username = messageObject.data
break; */
case 'created_at':
created_at = messageObject.data
break;
case 'statuses_count':
statuses_count = messageObject.data
break;
case 'note':
note = messageObject.data
break;
case 'url':
url = messageObject.data
break;
case 'following':
following = messageObject.data
followers_count = followers_count + (following ? 1 : - 1)
break;
case 'muting':
muting = messageObject.data
break;
case 'blocking':
blocking = messageObject.data
// followers_count = followers_count + (blocking ? -1 : 0)
break;
}
}
}
// The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All
Component.onCompleted: {
var msg
if (user_id) {
msg = {
'action' : "accounts/relationships/",
'params' : [ {name: "id", data: user_id} ],
'conf' : Logic.conf
}
worker.sendMessage(msg)
} else {
var instance = Logic.conf['instance'].split("//")
msg = {
'action' : "accounts/search?limit=1&q="+username.replace("@"+instance[1], ""),
'conf' : Logic.conf
}
worker.sendMessage(msg)
}
}
MyList {
id: list
header: ProfileHeader {
id: profileHeader
title: display_name
description: username
image: profileImage
bg: profileBackground
}
clip: true
mdl: ListModel {}
type: "accounts/"+user_id+"/statuses"
vars: {}
conf: Logic.conf
anchors {
top: parent.top
bottom: profileExpander.top
left: parent.left
right: parent.right
}
}
// ProfilePage ExpandingSection
ExpandingSectionGroup {
id: profileExpander
anchors.bottom: parent.bottom
ExpandingSection {
id: expandingSection1
title:
//: If there's no good translation for "About", use "Details" (in details about profile).
qsTr("About")
content.sourceComponent: Column {
spacing: Theme.paddingLarge
Item {
id: txtContainer
width: parent.width
height: profilePage.isPortrait ? Math.min( txtNote.height, parent.height * 0.5 ) : Math.min( txtNote.height, parent.height * 0.2 )
visible: {
if ((note.text === "") || ( note.text === "<p></p>" )) {
false
} else {
true
}
}
SilicaFlickable {
id: txtFlickable
contentWidth: parent.width
contentHeight: txtNote.height
anchors.fill: parent
clip: true
VerticalScrollDecorator {}
Label {
id: txtNote
text: note
textFormat: Text.StyledText
color: Theme.secondaryHighlightColor
font.pixelSize: Theme.fontSizeExtraSmall
linkColor: Theme.secondaryColor
wrapMode: Text.Wrap
width: parent.width - ( 2 * Theme.horizontalPageMargin )
anchors.horizontalCenter: parent.horizontalCenter
onLinkActivated: {
var test = link.split("/")
console.log(link)
console.log(JSON.stringify(test))
console.log(JSON.stringify(test.length))
if (test.length === 5 && (test[3] === "tags" || test[3] === "tag") ) {
pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true;
if (check)
page.onLinkActivated(link)
return check;
}));
send(link)
} else if (test.length === 4 && test[3][0] === "@" ) {
pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true;
if (check)
page.onLinkActivated(link)
return check;
}));
} else {
Qt.openUrlExternally(link);
}
}
}
}
}
Item { // dummy item for spacing
height: Theme.paddingSmall
}
Row {
id: statsRow
spacing: Theme.paddingLarge
anchors.horizontalCenter: parent.horizontalCenter
anchors.leftMargin: Theme.paddingLarge
anchors.rightMargin: Theme.paddingLarge
Label {
id: txtFollowers
visible: true //followers_count ? true : false
text: followers_count+" "+
//: Will show as: "35 Followers"
qsTr("Followers")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
wrapMode: Text.Wrap
}
Label {
id: txtFollowing
visible: true //following_count ? true : false
text: following_count+" "+
//: Will show as: "23 Following"
qsTr("Following")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
wrapMode: Text.Wrap
}
Label {
id: txtStatuses
visible: true //statuses_count ? true : false
text: statuses_count+" "+
//: Will show as: "115 Statuses"
qsTr("Statuses")
font.pixelSize: Theme.fontSizeExtraSmall
color: pressed ? Theme.highlightColor : Theme.primaryColor
wrapMode: Text.Wrap
MouseArea {
anchors.fill: parent
onClicked: expandingSection1.expanded = false
}
}
}
Item { // dummy item for spacing
height: Theme.paddingSmall
}
ButtonLayout {
id: btnLayout
Button {
id: btnMention
preferredWidth: Theme.buttonWidthSmall
text: qsTr("Mention")
onClicked: {
pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
headerTitle: qsTr("Mention"),
description: "@"+username,
type: "new"
})
}
}
Button {
id: btnFollow
preferredWidth: Theme.buttonWidthSmall
text: (following ?
//: Is a button. Keep it as short as possible.
qsTr("Unfollow") : (requested ?
//: Is a button. Keep it as short as possible.
qsTr("Requested") :
//: Is a button. Keep it as short as possible.
qsTr("Follow")))
color: (following ? highlightColor : (requested ? palette.errorColor : palette.primaryColor))
onClicked: {
var msg = {
'method' : 'POST',
'params' : [],
'action' : "accounts/" + user_id + (following ? '/unfollow':'/follow'),
'conf' : Logic.conf
};
worker.sendMessage(msg);
}
}
Button {
id: btnMute
preferredWidth: Theme.buttonWidthSmall
text: (muting ?
//: Is a button. Keep it as short as possible.
qsTr("Unmute") :
//: Is a button. Keep it as short as possible.
qsTr("Mute"))
color: (muting ? palette.errorColor : palette.primaryColor)
onClicked: {
var msg = {
'method' : 'POST',
'params' : [],
'action' : "accounts/" + user_id + (muting ? '/unmute':'/mute'),
'conf' : Logic.conf
};
worker.sendMessage(msg);
}
}
Button {
id: btnBlock
preferredWidth: Theme.buttonWidthSmall
text: (blocking ?
//: Is a button. Keep it as short as possible.
qsTr("Unblock") :
//: Is a button. Keep it as short as possible.
qsTr("Block") )
color: (blocking ? palette.errorColor : palette.primaryColor)
onClicked: {
var msg = {
'method' : 'POST',
'params' : [],
'action' : "accounts/" + user_id + (blocking ? '/unblock':'/block'),
'conf' : Logic.conf
}
worker.sendMessage(msg)
}
}
}
Rectangle { // dummy item for spacing
height: Theme.paddingSmall
width: parent.width
opacity: 0
}
}
}
}
}

View file

@ -1,200 +0,0 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../lib/API.js" as Logic
Page {
SilicaFlickable {
anchors.fill: parent
contentHeight: column.height + Theme.paddingLarge
contentWidth: parent.width
RemorsePopup { id: remorsePopup }
VerticalScrollDecorator {}
Column {
id: column
spacing: Theme.paddingSmall
width: parent.width
PageHeader {
title: qsTr("Settings")
}
Column {
// No spacing in this column
width: parent.width
IconTextSwitch {
id: removeAccount
text: Logic.conf['login'] ? qsTr("Remove Account") : qsTr("Add Account")
description: Logic.conf['login'] ? qsTr("Deauthorize this app and remove your account") : qsTr("Authorize this app to access your Mastodon account")
icon.source: Logic.conf['login'] ? "image://theme/icon-m-contact" : "image://theme/icon-m-add"
onCheckedChanged: {
remorsePopup.execute(removeAccount.text, function() {
busy = true;
checked = false;
timer1.start();
if (Logic.conf['login']) {
Logic.conf['login'] = false
Logic.conf['instance'] = null;
Logic.conf['api_user_token'] = null;
}
pageStack.push(Qt.resolvedUrl("LoginPage.qml"))
})
}
/* busy = true;
checked = false;
timer1.start()
}*/
Timer {
id: timer1
interval: 4700
onTriggered: parent.busy = false
}
}
IconTextSwitch {
//enabled: false
checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages']
text: qsTr("Load images in toots")
description: qsTr("Disable this option if you want to preserve your data connection")
icon.source: "image://theme/icon-m-image"
onClicked: {
Logic.conf['loadImages'] = checked
}
}
IconTextSwitch {
text: qsTr("Translate")
description: qsTr("Use Transifex to help with app translation to your language")
icon.source: "image://theme/icon-m-font-size"
onCheckedChanged: {
busy = true;
checked = false;
Qt.openUrlExternally("https://www.transifex.com/dysko/tooter/");
timer2.start()
}
Timer {
id: timer2
interval: 4700
onTriggered: parent.busy = false
}
}
}
SectionHeader {
text: qsTr("Credits")
}
Column {
width: parent.width
anchors {
left: parent.left
right: parent.right
rightMargin: Theme.horizontalPageMargin
}
Repeater {
model: ListModel {
ListElement {
name: "Duško Angirević"
desc: qsTr("UI/UX design and development")
mastodon: "dysko@mastodon.social"
mail: ""
}
ListElement {
name: "Miodrag Nikolić"
desc: qsTr("Visual identity")
mastodon: ""
mail: "micotakis@gmail.com"
}
ListElement {
name: "Molan"
desc: qsTr("Development and translations")
mastodon: ""
mail: "mol_an@sunrise.ch"
}
ListElement {
name: "Quentin PAGÈS / Quenti ♏"
desc: qsTr("Occitan & French translation")
mastodon: "Quenti@framapiaf.org"
mail: ""
}
ListElement {
name: "Luchy Kon / dashinfantry"
desc: qsTr("Chinese translation")
mastodon: ""
mail: "dashinfantry@gmail.com"
}
ListElement {
name: "André Koot"
desc: qsTr("Dutch translation")
mastodon: "meneer@mastodon.social"
mail: "https://twitter.com/meneer"
}
ListElement {
name: "CarmenFdez"
desc: qsTr("Spanish translation")
mastodon: ""
mail: ""
}
ListElement {
name: "Mohamed-Touhami MAHDI"
desc: qsTr("Added README file")
mastodon: "dragnucs@touha.me"
mail: "touhami@touha.me"
}
}
Item {
width: parent.width
height: Theme.itemSizeMedium
IconButton {
id: btn
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
}
icon.source: "image://theme/" + (model.mastodon !== "" ? "icon-m-contact" : "icon-m-mail") + "?" + (pressed
? Theme.highlightColor
: Theme.primaryColor)
onClicked: {
if (model.mastodon !== ""){
var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
pageStack.push(Qt.resolvedUrl("Conversation.qml"), {
toot_id: 0,
title: model.name,
description: '@'+model.mastodon,
avatar: "",
mdl: m,
type: "reply"
})
} else {
Qt.openUrlExternally("mailto:"+model.mail);
}
}
}
Column {
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: Theme.horizontalPageMargin
right: btn.left
rightMargin: Theme.paddingMedium
}
Label {
id: lblName
text: model.name
color: Theme.secondaryColor
font.pixelSize: Theme.fontSizeSmall
}
Label {
text: model.desc
color: Theme.secondaryHighlightColor
font.pixelSize: Theme.fontSizeExtraSmall
}
}
}
}
}
}
}
}

246
qml/pages/SettingsPage.qml Normal file
View file

@ -0,0 +1,246 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../lib/API.js" as Logic
Page {
id: settingsPage
allowedOrientations: Orientation.All
SilicaFlickable {
contentHeight: column.height + Theme.paddingLarge
contentWidth: parent.width
anchors.fill: parent
RemorsePopup { id: remorsePopup }
VerticalScrollDecorator {}
Column {
id: column
spacing: Theme.paddingMedium
width: parent.width
PageHeader {
title: qsTr("Settings")
}
SectionHeader { text: qsTr("Options")}
IconTextSwitch {
text: qsTr("Load Images in Toots")
description: qsTr("Disable this option if you want to preserve your data connection")
icon.source: "image://theme/icon-m-image"
checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages']
onClicked: {
Logic.conf['loadImages'] = checked
}
}
SectionHeader { text: qsTr("Account") }
Item {
id: removeAccount
width: parent.width
height: txtRemoveAccount.height + btnRemoveAccount.height + Theme.paddingLarge
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin
right: parent.right
rightMargin: Theme.paddingLarge
}
Icon {
id: icnRemoveAccount
color: Theme.highlightColor
width: Theme.iconSizeMedium
fillMode: Image.PreserveAspectFit
source: Logic.conf['login'] ? "image://theme/icon-m-contact" : "image://theme/icon-m-add"
anchors.right: parent.right
}
Column {
id: clnRemoveAccount
spacing: Theme.paddingMedium
anchors {
left: parent.left
right: icnRemoveAccount.left
}
Button {
id: btnRemoveAccount
text: Logic.conf['login'] ? qsTr("Remove Account") : qsTr("Add Account")
preferredWidth: Theme.buttonWidthMedium
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
remorsePopup.execute(btnRemoveAccount.text, function() {
if (Logic.conf['login']) {
Logic.conf['login'] = false
Logic.conf['instance'] = null;
Logic.conf['api_user_token'] = null;
}
pageStack.push(Qt.resolvedUrl("LoginPage.qml"))
})
}
Timer {
id: timer1
interval: 4700
onTriggered: parent.busy = false
}
}
Label {
id: txtRemoveAccount
text: Logic.conf['login'] ? qsTr("Deauthorize this app from using your account and remove account data from phone") : qsTr("Authorize this app to access your Mastodon account")
font.pixelSize: Theme.fontSizeExtraSmall
wrapMode: Text.Wrap
color: Theme.highlightColor
width: parent.width - Theme.paddingMedium
anchors.left: parent.left
}
}
}
SectionHeader {
text: qsTr("Translate")
}
LinkedLabel {
id: translateLbl
//: Full sentence for translation: "Use Transifex to help with app translation to your language." - The word Transifex is a link and doesn't need translation.
text: qsTr("Use")+" "+"<a href='https://www.transifex.com/molan-git/tooter-b'>Transifex</a>"+" "+qsTr("to help with app translation to your language.")
textFormat: Text.StyledText
color: Theme.highlightColor
linkColor: Theme.primaryColor
font.family: Theme.fontFamilyHeading
font.pixelSize: Theme.fontSizeExtraSmall
wrapMode: Text.Wrap
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin
right: parent.right
rightMargin: Theme.paddingLarge
}
}
SectionHeader {
//: Translation alternative: "Development"
text: qsTr("Credits")
}
Column {
width: parent.width
anchors {
left: parent.left
right: parent.right
rightMargin: Theme.paddingLarge
}
Repeater {
model: ListModel {
ListElement {
name: "Duško Angirević"
desc: qsTr("UI/UX design and development")
mastodon: "dysko@mastodon.social"
mail: ""
}
ListElement {
name: "Molan"
desc: qsTr("Development and translations")
mastodon: "molan@fosstodon.org"
mail: ""
}
ListElement {
name: "Miodrag Nikolić"
desc: qsTr("Visual identity")
mastodon: ""
mail: "micotakis@gmail.com"
}
ListElement {
name: "Quentin PAGÈS / Quenti ♏"
desc: qsTr("Occitan & French translation")
mastodon: "Quenti@framapiaf.org"
mail: ""
}
ListElement {
name: "Luchy Kon / dashinfantry"
desc: qsTr("Chinese translation")
mastodon: ""
mail: "dashinfantry@gmail.com"
}
ListElement {
name: "André Koot"
desc: qsTr("Dutch translation")
mastodon: "meneer@mastodon.social"
mail: "https://twitter.com/meneer"
}
ListElement {
name: "CarmenFdez"
desc: qsTr("Spanish translation")
mastodon: ""
mail: ""
}
}
Item {
width: parent.width
height: Theme.itemSizeMedium
IconButton {
id: btn
icon.source: "image://theme/" + (model.mastodon !== "" ? "icon-m-outline-chat" : "icon-m-mail") + "?" + (pressed
? Theme.highlightColor : Theme.primaryColor)
anchors {
verticalCenter: parent.verticalCenter
right: parent.right
}
onClicked: {
if (model.mastodon !== ""){
var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
headerTitle: "Mention",
description: '@'+model.mastodon,
type: "new"
})
} else {
Qt.openUrlExternally("mailto:"+model.mail);
}
}
}
Column {
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: Theme.horizontalPageMargin
right: btn.left
rightMargin: Theme.paddingMedium
}
Label {
id: lblName
text: model.name
color: Theme.highlightColor
font.pixelSize: Theme.fontSizeSmall
}
Label {
text: model.desc
color: Theme.secondaryHighlightColor
font.pixelSize: Theme.fontSizeExtraSmall
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,270 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Dialog {
id: emojiDialog
allowedOrientations: Orientation.All
canAccept: false //selector.currentIndex >= 0
onAcceptPendingChanged: {
if (acceptPending) {
// Tell the destination page what the selected category is
// acceptDestinationInstance.category = selector.value
}
}
anchors.top: parent.top
Column {
id: emojiColumn
spacing: Theme.paddingLarge
width: parent.width
height: parent.height
SilicaGridView {
id: gridView
header: PageHeader {
title: qsTr("Emojis")
description: qsTr("Tap to insert")
}
cellWidth: isPortrait ? gridView.width / 6 : gridView.width / 10
cellHeight: cellWidth
width: parent.width
height: parent.height
model: ListModel {
ListElement { section: "Smileys"; glyph: "😄" }
ListElement { section: "Smileys"; glyph: "😃" }
ListElement { section: "Smileys"; glyph: "😀" }
ListElement { section: "Smileys"; glyph: "😊" }
ListElement { section: "Smileys"; glyph: "☺" }
ListElement { section: "Smileys"; glyph: "😉" }
ListElement { section: "Smileys"; glyph: "😍" }
ListElement { section: "Smileys"; glyph: "😘" }
ListElement { section: "Smileys"; glyph: "😚" }
ListElement { section: "Smileys"; glyph: "😗" }
ListElement { section: "Smileys"; glyph: "😙" }
ListElement { section: "Smileys"; glyph: "😜" }
ListElement { section: "Smileys"; glyph: "😝" }
ListElement { section: "Smileys"; glyph: "😛" }
ListElement { section: "Smileys"; glyph: "😳" }
ListElement { section: "Smileys"; glyph: "😁" }
ListElement { section: "Smileys"; glyph: "😔" }
ListElement { section: "Smileys"; glyph: "😌" }
ListElement { section: "Smileys"; glyph: "😒" }
ListElement { section: "Smileys"; glyph: "😞" }
ListElement { section: "Smileys"; glyph: "😣" }
ListElement { section: "Smileys"; glyph: "😢" }
ListElement { section: "Smileys"; glyph: "😂" }
ListElement { section: "Smileys"; glyph: "😭" }
ListElement { section: "Smileys"; glyph: "😪" }
ListElement { section: "Smileys"; glyph: "😥" }
ListElement { section: "Smileys"; glyph: "😰" }
ListElement { section: "Smileys"; glyph: "😅" }
ListElement { section: "Smileys"; glyph: "😩" }
ListElement { section: "Smileys"; glyph: "😫" }
ListElement { section: "Smileys"; glyph: "😨" }
ListElement { section: "Smileys"; glyph: "😱" }
ListElement { section: "Smileys"; glyph: "😠" }
ListElement { section: "Smileys"; glyph: "😡" }
ListElement { section: "Smileys"; glyph: "😤" }
ListElement { section: "Smileys"; glyph: "😖" }
ListElement { section: "Smileys"; glyph: "😆" }
ListElement { section: "Smileys"; glyph: "😋" }
ListElement { section: "Smileys"; glyph: "😷" }
ListElement { section: "Smileys"; glyph: "😎" }
ListElement { section: "Smileys"; glyph: "😴" }
ListElement { section: "Smileys"; glyph: "😵" }
ListElement { section: "Smileys"; glyph: "😲" }
ListElement { section: "Smileys"; glyph: "😟" }
ListElement { section: "Smileys"; glyph: "😦" }
ListElement { section: "Smileys"; glyph: "😧" }
ListElement { section: "Smileys"; glyph: "😈" }
ListElement { section: "Smileys"; glyph: "👿" }
ListElement { section: "Smileys"; glyph: "😮" }
ListElement { section: "Smileys"; glyph: "😬" }
ListElement { section: "Smileys"; glyph: "😐" }
ListElement { section: "Smileys"; glyph: "😕" }
ListElement { section: "Smileys"; glyph: "😯" }
ListElement { section: "Smileys"; glyph: "😶" }
ListElement { section: "Smileys"; glyph: "😇" }
ListElement { section: "Smileys"; glyph: "😏" }
ListElement { section: "Smileys"; glyph: "😑" }
ListElement { section: "Cat Faces"; glyph: "😺" }
ListElement { section: "Cat Faces"; glyph: "😸" }
ListElement { section: "Cat Faces"; glyph: "😻" }
ListElement { section: "Cat Faces"; glyph: "😽" }
ListElement { section: "Cat Faces"; glyph: "😼" }
ListElement { section: "Cat Faces"; glyph: "🙀" }
ListElement { section: "Cat Faces"; glyph: "😿" }
ListElement { section: "Cat Faces"; glyph: "😹" }
ListElement { section: "Cat Faces"; glyph: "😾" }
ListElement { section: "Other Faces"; glyph: "👹" }
ListElement { section: "Other Faces"; glyph: "👺" }
ListElement { section: "Other Faces"; glyph: "🙈" }
ListElement { section: "Other Faces"; glyph: "🙉" }
ListElement { section: "Other Faces"; glyph: "🙊" }
ListElement { section: "Other Faces"; glyph: "💀" }
ListElement { section: "Other Faces"; glyph: "👽" }
ListElement { section: "Misc Emoji"; glyph: "🔥" }
ListElement { section: "Misc Emoji"; glyph: "✨" }
ListElement { section: "Misc Emoji"; glyph: "🌟" }
ListElement { section: "Misc Emoji"; glyph: "💫" }
ListElement { section: "Misc Emoji"; glyph: "💥" }
ListElement { section: "Misc Emoji"; glyph: "💢" }
ListElement { section: "Misc Emoji"; glyph: "💦" }
ListElement { section: "Misc Emoji"; glyph: "💧" }
ListElement { section: "Misc Emoji"; glyph: "💤" }
ListElement { section: "Misc Emoji"; glyph: "💨" }
ListElement { section: "Misc Emoji"; glyph: "👂" }
ListElement { section: "Misc Emoji"; glyph: "👀" }
ListElement { section: "Misc Emoji"; glyph: "👃" }
ListElement { section: "Misc Emoji"; glyph: "👅" }
ListElement { section: "Misc Emoji"; glyph: "👄" }
ListElement { section: "Misc Emoji"; glyph: "👍" }
ListElement { section: "Misc Emoji"; glyph: "👎" }
ListElement { section: "Misc Emoji"; glyph: "👌" }
ListElement { section: "Misc Emoji"; glyph: "👊" }
ListElement { section: "Misc Emoji"; glyph: "✊" }
ListElement { section: "Misc Emoji"; glyph: "✌" }
ListElement { section: "Misc Emoji"; glyph: "👋" }
ListElement { section: "Misc Emoji"; glyph: "✋" }
ListElement { section: "Misc Emoji"; glyph: "👐" }
ListElement { section: "Misc Emoji"; glyph: "👆" }
ListElement { section: "Misc Emoji"; glyph: "👇" }
ListElement { section: "Misc Emoji"; glyph: "👉" }
ListElement { section: "Misc Emoji"; glyph: "👈" }
ListElement { section: "Misc Emoji"; glyph: "🙌" }
ListElement { section: "Misc Emoji"; glyph: "🙏" }
ListElement { section: "Misc Emoji"; glyph: "☝" }
ListElement { section: "Misc Emoji"; glyph: "👏" }
ListElement { section: "Misc Emoji"; glyph: "💪" }
ListElement { section: "Animals Emoji"; glyph: "🐶" }
ListElement { section: "Animals Emoji"; glyph: "🐺" }
ListElement { section: "Animals Emoji"; glyph: "🐱" }
ListElement { section: "Animals Emoji"; glyph: "🐭" }
ListElement { section: "Animals Emoji"; glyph: "🐹" }
ListElement { section: "Animals Emoji"; glyph: "🐰" }
ListElement { section: "Animals Emoji"; glyph: "🐸" }
ListElement { section: "Animals Emoji"; glyph: "🐯" }
ListElement { section: "Animals Emoji"; glyph: "🐨" }
ListElement { section: "Animals Emoji"; glyph: "🐘" }
ListElement { section: "Animals Emoji"; glyph: "🐼" }
ListElement { section: "Animals Emoji"; glyph: "🐧" }
ListElement { section: "Animals Emoji"; glyph: "🐦" }
ListElement { section: "Animals Emoji"; glyph: "🐤" }
ListElement { section: "Animals Emoji"; glyph: "🐥" }
ListElement { section: "Animals Emoji"; glyph: "🐣" }
ListElement { section: "Animals Emoji"; glyph: "🐔" }
ListElement { section: "Animals Emoji"; glyph: "🐍" }
ListElement { section: "Animals Emoji"; glyph: "🐢" }
ListElement { section: "Animals Emoji"; glyph: "🐛" }
ListElement { section: "Animals Emoji"; glyph: "🐝" }
ListElement { section: "Animals Emoji"; glyph: "🐜" }
ListElement { section: "Animals Emoji"; glyph: "🐞" }
ListElement { section: "Animals Emoji"; glyph: "🐌" }
ListElement { section: "Animals Emoji"; glyph: "🐙" }
ListElement { section: "Animals Emoji"; glyph: "🐚" }
ListElement { section: "Animals Emoji"; glyph: "🐠" }
ListElement { section: "Animals Emoji"; glyph: "🐟" }
ListElement { section: "Animals Emoji"; glyph: "🐬" }
ListElement { section: "Animals Emoji"; glyph: "🐳" }
ListElement { section: "Animals Emoji"; glyph: "🐋" }
ListElement { section: "Animals Emoji"; glyph: "🐄" }
ListElement { section: "Animals Emoji"; glyph: "🐏" }
ListElement { section: "Animals Emoji"; glyph: "🐀" }
ListElement { section: "Animals Emoji"; glyph: "🐃" }
ListElement { section: "Animals Emoji"; glyph: "🐅" }
ListElement { section: "Animals Emoji"; glyph: "🐇" }
ListElement { section: "Animals Emoji"; glyph: "🐉" }
ListElement { section: "Animals Emoji"; glyph: "🐎" }
ListElement { section: "Animals Emoji"; glyph: "🐐" }
ListElement { section: "Animals Emoji"; glyph: "🐓" }
ListElement { section: "Animals Emoji"; glyph: "🐕" }
ListElement { section: "Animals Emoji"; glyph: "🐖" }
ListElement { section: "Animals Emoji"; glyph: "🐁" }
ListElement { section: "Animals Emoji"; glyph: "🐂" }
ListElement { section: "Animals Emoji"; glyph: "🐲" }
ListElement { section: "Animals Emoji"; glyph: "🐡" }
ListElement { section: "Animals Emoji"; glyph: "🐊" }
ListElement { section: "Animals Emoji"; glyph: "🐫" }
ListElement { section: "Animals Emoji"; glyph: "🐪" }
ListElement { section: "Animals Emoji"; glyph: "🐆" }
ListElement { section: "Animals Emoji"; glyph: "🐈" }
ListElement { section: "Animals Emoji"; glyph: "🐩" }
ListElement { section: "Animals Emoji"; glyph: "🐾" }
ListElement { section: "Transport and Map"; glyph: "🚀" }
ListElement { section: "Transport and Map"; glyph: "🚃" }
ListElement { section: "Transport and Map"; glyph: "🚀" }
ListElement { section: "Transport and Map"; glyph: "🚄" }
ListElement { section: "Transport and Map"; glyph: "🚅" }
ListElement { section: "Transport and Map"; glyph: "🚇" }
ListElement { section: "Transport and Map"; glyph: "🚉" }
ListElement { section: "Transport and Map"; glyph: "🚌" }
ListElement { section: "Transport and Map"; glyph: "🚏" }
ListElement { section: "Transport and Map"; glyph: "🚑" }
ListElement { section: "Transport and Map"; glyph: "🚒" }
ListElement { section: "Transport and Map"; glyph: "🚓" }
ListElement { section: "Transport and Map"; glyph: "🚕" }
ListElement { section: "Transport and Map"; glyph: "🚗" }
ListElement { section: "Transport and Map"; glyph: "🚙" }
ListElement { section: "Transport and Map"; glyph: "🚚" }
ListElement { section: "Transport and Map"; glyph: "🚢" }
ListElement { section: "Transport and Map"; glyph: "🚨" }
ListElement { section: "Transport and Map"; glyph: "🚩" }
ListElement { section: "Transport and Map"; glyph: "🚪" }
ListElement { section: "Transport and Map"; glyph: "🚫" }
ListElement { section: "Transport and Map"; glyph: "🚬" }
ListElement { section: "Transport and Map"; glyph: "🚭" }
ListElement { section: "Transport and Map"; glyph: "🚲" }
ListElement { section: "Transport and Map"; glyph: "🚶" }
ListElement { section: "Transport and Map"; glyph: "🚹" }
ListElement { section: "Transport and Map"; glyph: "🚺" }
ListElement { section: "Transport and Map"; glyph: "🚻" }
ListElement { section: "Transport and Map"; glyph: "🚼" }
ListElement { section: "Transport and Map"; glyph: "🚽" }
ListElement { section: "Transport and Map"; glyph: "🚾" }
ListElement { section: "Transport and Map"; glyph: "🛀" }
ListElement { section: "Horoscope Signs"; glyph: "♈" }
ListElement { section: "Horoscope Signs"; glyph: "♉" }
ListElement { section: "Horoscope Signs"; glyph: "♊" }
ListElement { section: "Horoscope Signs"; glyph: "♋" }
ListElement { section: "Horoscope Signs"; glyph: "♌" }
ListElement { section: "Horoscope Signs"; glyph: "♍" }
ListElement { section: "Horoscope Signs"; glyph: "♎" }
ListElement { section: "Horoscope Signs"; glyph: "♏" }
ListElement { section: "Horoscope Signs"; glyph: "♐" }
ListElement { section: "Horoscope Signs"; glyph: "♑" }
ListElement { section: "Horoscope Signs"; glyph: "♒" }
ListElement { section: "Horoscope Signs"; glyph: "♓" }
}
delegate: BackgroundItem {
width: gridView.cellWidth
height: gridView.cellHeight
Label {
text: glyph
font.pixelSize: Theme.fontSizeLarge
color: highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
anchors.centerIn: parent
}
onClicked: {
var cursorPosition = toot.cursorPosition
toot.text = toot.text.substring(
0, cursorPosition) + model.glyph + toot.text.substring(
cursorPosition)
toot.cursorPosition = cursorPosition + model.glyph.length
emojiDialog.canAccept = true
emojiDialog.accept()
}
}
VerticalScrollDecorator { flickable: gridView }
}
}
}

View file

@ -4,36 +4,34 @@ import Sailfish.Silica 1.0
DockedPanel {
id: root
z: 100
width: parent.width
height: content.height
dock: Dock.Top
width: isPortrait ? parent.width : Theme.buttonWidthLarge * 1.5
height: content.height
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
id: content
width: root.width
height: infoLabel.height + 5*Theme.paddingMedium
//anchors.topMargin: 20
color: Theme.highlightBackgroundColor
opacity: 1.0
width: root.width
height: infoLabel.height + 2 * Theme.paddingMedium
Label {
id: infoLabel
text : ""
color: Theme.primaryColor
font.family: Theme.fontFamilyHeading
font.pixelSize: Theme.fontSizeMedium
//font.weight: Font.Bold
width: parent.width
color: Theme.primaryColor
wrapMode: Text.WrapAnywhere
width: parent.width
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin*2
right: parent.right
rightMargin: Theme.horizontalPageMargin
verticalCenter: parent.verticalCenter
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
@ -51,7 +49,7 @@ DockedPanel {
Timer {
id: autoClose
interval: 6000
interval: 4500
running: false
onTriggered: {
root.hide()

View file

@ -4,18 +4,20 @@ import Sailfish.Silica 1.0
BackgroundItem {
id: delegate
signal openUser (string notice)
height: Theme.itemSizeMedium
width: parent.width
Rectangle {
signal openUser (string notice)
width: parent.width
height: Theme.itemSizeMedium
Item {
id: avatar
width: Theme.itemSizeExtraSmall
height: width
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Theme.horizontalPageMargin
color: Theme.highlightDimmerColor
Image {
id: img
opacity: status === Image.Ready ? 1.0 : 0.0
@ -23,46 +25,79 @@ BackgroundItem {
anchors.fill: parent
source: model.account_avatar
}
BusyIndicator {
size: BusyIndicatorSize.Small
opacity: img.status === Image.Ready ? 0.0 : 1.0
Behavior on opacity { FadeAnimator {} }
running: avatar.status !== Image.Ready;
running: avatar.status !== Image.Ready
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: pageStack.push(Qt.resolvedUrl("./../Profile.qml"), {
onClicked: pageStack.push(Qt.resolvedUrl("./../ProfilePage.qml"), {
"display_name": model.account_display_name,
"username": model.account_acct,
"user_id": model.account_id,
"profileImage": model.account_avatar
"profileImage": model.account_avatar,
"profileBackground": model.account_header,
"note": model.account_note,
"url": model.account_url,
"followers_count": model.account_followers_count,
"following_count": model.account_following_count,
"statuses_count": model.account_statuses_count,
"locked": model.account_locked,
"bot": model.account_bot,
"group": model.account_group
})
}
}
Column {
Item {
id: userDescription
height: account_acct.height + display_name.height
anchors.left: avatar.right
anchors.leftMargin: Theme.paddingLarge
anchors.right: parent.right
anchors.rightMargin: Theme.horizontalPageMargin
anchors.verticalCenter: parent.verticalCenter
height: account_acct.height + display_name.height
Label {
id: display_name
text: model.account_display_name+" "
color: !pressed ? Theme.primaryColor : Theme.highlightColor
text: account_display_name ? account_display_name : account_username.split('@')[0]
color: !pressed ? Theme.primaryColor : Theme.highlightColor
font.pixelSize: Theme.fontSizeSmall
truncationMode: TruncationMode.Fade
width: parent.width - Theme.paddingMedium
anchors.top: parent.top
}
Label {
id: account_acct
text: "@"+model.account_acct
color: !pressed ? Theme.secondaryColor : Theme.secondaryHighlightColor
anchors.leftMargin: Theme.paddingMedium
font.pixelSize: Theme.fontSizeExtraSmall
truncationMode: TruncationMode.Fade
width: parent.width - Theme.paddingMedium
anchors.top: display_name.bottom
}
}
onClicked: openUser({
onClicked: openUser( {
"display_name": model.account_display_name,
"username": model.account_acct,
"user_id": model.account_id,
"profileImage": model.account_avatar
})
"profileImage": model.account_avatar,
"profileBackground": model.account_header,
"note": model.account_note,
"url": model.account_url,
"followers_count": model.account_followers_count,
"following_count": model.account_following_count,
"statuses_count": model.account_statuses_count,
"locked": model.account_locked,
"bot": model.account_bot,
"group": model.account_group
} )
}

View file

@ -4,15 +4,17 @@ import QtMultimedia 5.0
Item {
id: holder
property ListModel model
property double wRatio : 16/9
property double hRatio : 9/16
id: holder
width: width
height: height
Component.onCompleted: {
if (model && model.count && model.get(0).type === "video") {
while (model.count>1){
while (model.count>1) {
model.remove(model.count-1)
}
//console.log(JSON.stringify(model.get(0)))
@ -21,15 +23,17 @@ Item {
if (model && model.count)
count = model.count
switch(count){
case 1:
placeholder1.width = holder.width
placeholder1.height = placeholder1.width*hRatio
placeholder1.visible = true;
holder.height = placeholder1.height
break;
case 2:
placeholder1.visible = true;
placeholder2.visible = true;
placeholder1.visible = true
placeholder2.visible = true
placeholder1.width = (holder.width-Theme.paddingSmall)/2
placeholder1.height = placeholder1.width
placeholder2.width = placeholder1.width
@ -37,11 +41,12 @@ Item {
placeholder2.x = placeholder1.width + placeholder2.x + Theme.paddingSmall
holder.height = placeholder1.height
break;
case 3:
placeholder1.visible = true;
placeholder2.visible = true;
placeholder3.visible = true;
placeholder4.visible = false;
placeholder1.visible = true
placeholder2.visible = true
placeholder3.visible = true
placeholder4.visible = false
placeholder1.width = holder.width - Theme.paddingSmall - Theme.itemSizeLarge;
placeholder1.height = Theme.itemSizeLarge*2+Theme.paddingSmall
@ -51,30 +56,30 @@ Item {
placeholder3.height = placeholder3.width = placeholder2.height = placeholder2.width
placeholder3.x = placeholder2.x = placeholder1.x + placeholder1.width + Theme.paddingSmall;
placeholder3.y = placeholder2.y + placeholder2.height + Theme.paddingSmall;
break;
case 4:
placeholder1.visible = true;
placeholder2.visible = true;
placeholder3.visible = true;
placeholder4.visible = true;
placeholder1.visible = true
placeholder2.visible = true
placeholder3.visible = true
placeholder4.visible = true
placeholder1.width = placeholder2.width = placeholder3.width = placeholder4.width = (holder.width - 3*Theme.paddingSmall)/4
placeholder1.height = placeholder2.height = placeholder3.height = placeholder4.height = Theme.itemSizeLarge*2+Theme.paddingSmall
placeholder2.x = 1*(placeholder1.width)+ 1*Theme.paddingSmall;
placeholder3.x = 2*(placeholder1.width)+ 2*Theme.paddingSmall;
placeholder4.x = 3*(placeholder1.width)+ 3*Theme.paddingSmall;
placeholder2.x = 1*(placeholder1.width)+ 1*Theme.paddingSmall
placeholder3.x = 2*(placeholder1.width)+ 2*Theme.paddingSmall
placeholder4.x = 3*(placeholder1.width)+ 3*Theme.paddingSmall
holder.height = placeholder1.height
holder.height = placeholder1.height
break;
default:
holder.height = 0
placeholder1.visible = placeholder2.visible = placeholder3.visible = placeholder4.visible = false;
}
}
MyImage {
MyMedia {
id: placeholder1
width: 2
height: 1
@ -84,7 +89,7 @@ Item {
type = model.get(0).type
previewURL = model.get(0).preview_url
mediaURL = model.get(0).url
height = 200
height = Theme.itemSizeLarge
return true
} else {
height = 0
@ -92,7 +97,8 @@ Item {
}
}
}
MyImage {
MyMedia {
id: placeholder2
width: 2
height: 1
@ -102,7 +108,7 @@ Item {
type = model.get(1).type
previewURL = model.get(1).preview_url
mediaURL = model.get(1).url
height = 200
height = Theme.itemSizeLarge
return true
} else {
height = 0
@ -110,7 +116,8 @@ Item {
}
}
}
MyImage {
MyMedia {
id: placeholder3
width: 2
height: 1
@ -120,7 +127,7 @@ Item {
type = model.get(2).type
previewURL = model.get(2).preview_url
mediaURL = model.get(2).url
height = 200
height = Theme.itemSizeLarge
return true
} else {
height = 0
@ -128,7 +135,8 @@ Item {
}
}
}
MyImage {
MyMedia {
id: placeholder4
width: 2
height: 1
@ -138,7 +146,7 @@ Item {
type = model.get(3).type
previewURL = model.get(3).preview_url
mediaURL = model.get(3).url
height = 200
height = Theme.itemSizeLarge
return true
} else {
height = 0
@ -147,7 +155,3 @@ Item {
}
}
}

View file

@ -1,68 +1,57 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtMultimedia 5.0
import QtMultimedia 5.6
FullscreenContentPage {
id: imagePage
id: mediaPage
property string type: ""
property string previewURL: ""
property string mediaURL: ""
allowedOrientations: Orientation.All
Component.onCompleted: function(){
Component.onCompleted: function() {
console.log(type)
console.log(previewURL)
console.log(mediaURL)
if (type != 'gifv' && type != 'video') {
imagePreview.source = mediaURL
imageFlickable.visible = true;
imageFlickable.visible = true
} else {
video.source = mediaURL
video.fillMode = VideoOutput.PreserveAspectFit
videoFlickable.visible = true
playerIcon.visible = true
playerProgress.visible = true
video.play()
videoFlickable.visible = true;
hideTimer.start()
}
}
Item {
id: overlay
z: 100
property bool active: true
enabled: active
anchors.fill: parent
opacity: active ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {}}
IconButton {
y: Theme.paddingLarge
anchors {
right: parent.right
rightMargin: Theme.horizontalPageMargin
}
icon.source: "image://theme/icon-m-dismiss"
onClicked: pageStack.pop()
}
}
Flickable {
SilicaFlickable {
id: videoFlickable
visible: false
contentWidth: imageContainer.width
contentHeight: imageContainer.height
anchors.fill: parent
contentWidth: imageContainer.width; contentHeight: imageContainer.height
clip: true
Image {
id: videoPreview
fillMode: Image.PreserveAspectFit
anchors.fill: parent
source: previewURL
}
Video {
id: video
anchors.fill: parent
onErrorStringChanged: function(){
videoError.visible = true;
onErrorStringChanged: function() {
videoError.visible = true
}
onStatusChanged: {
console.log(status)
switch (status){
switch (status) {
case MediaPlayer.Loading:
console.log("loading")
return;
@ -71,10 +60,9 @@ FullscreenContentPage {
return;
}
}
onPlaybackStateChanged: {
console.log(playbackState)
switch (playbackState){
switch (playbackState) {
case MediaPlayer.PlayingState:
playerIcon.icon.source = "image://theme/icon-m-pause"
return;
@ -82,12 +70,11 @@ FullscreenContentPage {
playerIcon.icon.source = "image://theme/icon-m-play"
return;
case MediaPlayer.StoppedState:
playerIcon.icon.source = "image://theme/icon-m-stop"
playerIcon.icon.source = "image://theme/icon-m-reload"
return;
}
}
onPositionChanged: function(){
onPositionChanged: function() {
//console.log(duration)
//console.log(bufferProgress)
//console.log(position)
@ -97,51 +84,32 @@ FullscreenContentPage {
playerProgress.minimumValue = 0
playerProgress.value = position
}
}
onStopped: function() {
if (type == 'gifv') {
video.play()
} else {
video.stop()
overlayIcons.active = true
hideTimer.stop()
}
}
onStopped: function(){
play()
}
IconButton {
id: playerIcon
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: Theme.paddingLarge
anchors.bottomMargin: Theme.paddingLarge*1.5
icon.source: "image://theme/icon-m-play"
MouseArea {
anchors.fill: parent
onClicked: function() {
if (video.playbackState === MediaPlayer.PlayingState)
if (video.playbackState === MediaPlayer.PlayingState) {
video.pause()
else
overlayIcons.active = true
hideTimer.stop()
} else {
video.play()
hideTimer.start()
}
}
}
ProgressBar {
indeterminate: true
id: playerProgress
anchors.left: playerIcon.right
anchors.right: videoDlBtn.left
anchors.verticalCenter: playerIcon.verticalCenter
anchors.leftMargin: 0
anchors.bottomMargin: Theme.paddingLarge*1.5
}
IconButton {
id: videoDlBtn
visible: true
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: Theme.paddingLarge
anchors.bottomMargin: Theme.paddingLarge*1.5
icon.source: "image://theme/icon-m-device-download"
icon.opacity: 0.0
onClicked: {
var filename = mediaURL.split("/");
FileDownloader.downloadFile(mediaURL, filename[filename.length-1]);
}
}
Rectangle {
visible: videoError.text != ""
anchors.left: parent.left
@ -150,39 +118,32 @@ FullscreenContentPage {
color: Theme.highlightDimmerColor
height: videoError.height + 2*Theme.paddingMedium
width: parent.width
Label {
anchors.centerIn: parent
id: videoError
width: parent.width - 2*Theme.paddingMedium
wrapMode: Text.Wrap
height: contentHeight
visible: false;
font.pixelSize: Theme.fontSizeSmall;
visible: false
text: video.errorString
font.pixelSize: Theme.fontSizeSmall
color: Theme.highlightColor
}
}
MouseArea {
anchors.fill: parent
onClicked: function() {
if (video.playbackState === MediaPlayer.PlayingState)
video.pause()
else
video.play()
wrapMode: Text.Wrap
width: parent.width - 2*Theme.paddingMedium
height: contentHeight
anchors.centerIn: parent
}
}
}
}
Flickable {
SilicaFlickable {
id: imageFlickable
visible: false
contentWidth: imageContainer.width
contentHeight: imageContainer.height
anchors.fill: parent
contentWidth: imageContainer.width; contentHeight: imageContainer.height
clip: true
onHeightChanged: if (imagePreview.status === Image.Ready) imagePreview.fitToScreen();
onHeightChanged: if (imagePreview.status === Image.Ready) {
imagePreview.fitToScreen()
}
Item {
id: imageContainer
@ -191,18 +152,21 @@ FullscreenContentPage {
Image {
id: imagePreview
property real prevScale
function fitToScreen() {
scale = Math.min(imageFlickable.width / width, imageFlickable.height / height, 1)
scale = Math.min(imageFlickable.width / width, imageFlickable.height / height, imageFlickable.width, imageFlickable.height)
pinchArea.minScale = scale
prevScale = scale
}
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
cache: true
asynchronous: true
sourceSize.height: 1000;
smooth: false
sourceSize.width: mediaPage.width
smooth: true
anchors.centerIn: parent
onStatusChanged: {
if (status == Image.Ready) {
fitToScreen()
@ -235,14 +199,15 @@ FullscreenContentPage {
PinchArea {
id: pinchArea
opacity: 0.3
property real minScale: 1.0
property real maxScale: 3.0
anchors.fill: parent
enabled: imagePreview.status === Image.Ready
pinch.target: imagePreview
pinch.minimumScale: minScale * 0.5 // This is to create "bounce back effect"
pinch.maximumScale: maxScale * 1.5 // when over zoomed
pinch.maximumScale: maxScale * 1.5 // when over zoomed}
onPinchFinished: {
imageFlickable.returnToBounds()
@ -255,6 +220,7 @@ FullscreenContentPage {
bounceBackAnimation.start()
}
}
NumberAnimation {
id: bounceBackAnimation
target: imagePreview
@ -262,6 +228,11 @@ FullscreenContentPage {
property: "scale"
from: imagePreview.scale
}
MouseArea {
anchors.fill: parent
onClicked: overlayIcons.active = !overlayIcons.active
}
}
}
@ -281,35 +252,109 @@ FullscreenContentPage {
Component {
id: loadingIndicator
Item {
width: mediaPage.width
height: childrenRect.height
width: imagePage.width
ProgressCircle {
id: imageLoadingIndicator
anchors.horizontalCenter: parent.horizontalCenter
progressValue: imagePreview.progress
progressColor: inAlternateCycle ? Theme.highlightColor : Theme.highlightDimmerColor
backgroundColor: inAlternateCycle ? Theme.highlightDimmerColor : Theme.highlightColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Component {
id: failedLoading
Text {
font.pixelSize: Theme.fontSizeSmall;
text: qsTr("Error loading")
font.pixelSize: Theme.fontSizeSmall
color: Theme.highlightColor
}
}
IconButton {
visible: true
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: Theme.paddingLarge
anchors.bottomMargin: Theme.paddingLarge*1.5
icon.source: "image://theme/icon-m-device-download"
onClicked: {
var filename = mediaURL.split("/");
FileDownloader.downloadFile(mediaURL, filename[filename.length-1]);
Item {
id: overlayIcons
property bool active: true
enabled: active
anchors.fill: parent
opacity: active ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {}}
IconButton {
y: Theme.paddingLarge
icon.source: "image://theme/icon-m-dismiss"
onClicked: pageStack.pop()
anchors {
right: parent.right
rightMargin: Theme.horizontalPageMargin
}
}
IconButton {
id: mediaDlBtn
icon.source: "image://theme/icon-m-cloud-download"
anchors {
right: parent.right
rightMargin: Theme.horizontalPageMargin
bottom: parent.bottom
bottomMargin: Theme.horizontalPageMargin
}
onClicked: {
var filename = mediaURL.split("/")
FileDownloader.downloadFile(mediaURL, filename[filename.length-1])
}
}
IconButton {
id: playerIcon
visible: false
icon.source: "image://theme/icon-m-play"
anchors {
left: parent.left
bottom: parent.bottom
leftMargin: Theme.horizontalPageMargin
bottomMargin: Theme.horizontalPageMargin
}
onClicked: function() {
if (video.playbackState === MediaPlayer.PlayingState) {
video.pause()
hideTimer.stop()
} else {
video.play()
hideTimer.start()
}
}
}
ProgressBar {
id: playerProgress
visible: false
indeterminate: true
width: 400
anchors {
verticalCenter: playerIcon.verticalCenter
left: playerIcon.right
right: parent.right
rightMargin: Theme.horizontalPageMargin + Theme.iconSizeMedium
bottomMargin: Theme.horizontalPageMargin
}
}
Timer {
id: hideTimer
running: false
interval: 2000
onTriggered: {
overlayIcons.active = !overlayIcons.active
}
}
}
VerticalScrollDecorator { flickable: imageFlickable }
}

View file

@ -1,70 +1,69 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Item {
id: miniheader
id: miniHeader
height: lblName.height
width: parent.width
Label {
id: lblName
text: account_display_name ? account_display_name : account_username.split('@')[0]
font.weight: Font.Bold
font.pixelSize: Theme.fontSizeSmall
color: if ( myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) {
( pressed ? Theme.secondaryHighlightColor : (!highlight ? Theme.secondaryColor : Theme.secondaryHighlightColor ))
} else ( pressed ? Theme.highlightColor : ( !highlight ? Theme.primaryColor : Theme.secondaryColor ))
truncationMode: TruncationMode.Fade
width: myList.type !== "follow" ? ( contentWidth > parent.width /2 ? parent.width /2 : contentWidth ) : parent.width - Theme.paddingMedium
anchors {
left: parent.left
leftMargin: Theme.paddingMedium
}
text:
if (account_display_name === "") {
account_username.split('@')[0]
}
else account_display_name
width: contentWidth > parent.width /2 ? parent.width /2 : contentWidth
truncationMode: TruncationMode.Fade
font.weight: Font.Bold
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
}
Image {
id: iconVerified
y: Theme.paddingLarge
anchors {
left: lblName.right
leftMargin: Theme.paddingSmall
verticalCenter: lblName.verticalCenter
}
visible: account_locked
width: account_locked ? Theme.iconSizeExtraSmall*0.8 : 0
opacity: 0.8
height: width
source: "image://theme/icon-s-secure?" + (pressed
? Theme.highlightColor
: Theme.primaryColor)
}
Label {
id: lblScreenName
anchors {
left: iconVerified.right
right: lblDate.left
leftMargin: Theme.paddingMedium
baseline: lblName.baseline
}
truncationMode: TruncationMode.Fade
visible: model.type !== "follow"
text: '@'+account_username
font.pixelSize: Theme.fontSizeExtraSmall
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
color: ( pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor )
truncationMode: TruncationMode.Fade
anchors {
left: lblName.right
leftMargin: Theme.paddingMedium
right: lblDate.left
rightMargin: Theme.paddingMedium
verticalCenter: lblName.verticalCenter
}
}
Label {
Label {
id: lblScreenNameFollow
visible: model.type === "follow"
text: '@'+account_username
font.pixelSize: Theme.fontSizeExtraSmall
color: ( pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor )
width: parent.width - Theme.paddingMedium
truncationMode: TruncationMode.Fade
anchors {
top: lblName.bottom
left: parent.left
leftMargin: Theme.paddingMedium
}
}
Label {
id: lblDate
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
text: Format.formatDate(created_at, new Date() - created_at < 60*60*1000 ? Formatter.DurationElapsedShort : Formatter.TimeValueTwentyFourHours)
font.pixelSize: Theme.fontSizeExtraSmall
color: ( pressed ? Theme.highlightColor : Theme.secondaryColor )
horizontalAlignment: Text.AlignRight
anchors {
right: parent.right
baseline: lblName.baseline
rightMargin: Theme.horizontalPageMargin
verticalCenter: lblName.verticalCenter
}
}
}

View file

@ -1,34 +1,32 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Item {
id: ministatus
id: miniStatus
visible: true
height: icon.height+Theme.paddingMedium
width: parent.width
Image {
height: icon.height+Theme.paddingMedium
Icon {
id: icon
anchors {
top: parent.top
topMargin: Theme.paddingMedium
bottomMargin: Theme.paddingMedium
left: parent.left
leftMargin: Theme.horizontalPageMargin + Theme.iconSizeMedium - width
}
visible: type.length
color: Theme.highlightColor
width: Theme.iconSizeExtraSmall
height: width
source: typeof typeIcon !== "undefined" ? typeIcon : ""
anchors {
top: parent.top
topMargin: Theme.paddingMedium
left: parent.left
leftMargin: Theme.horizontalPageMargin + Theme.iconSizeMedium - width
bottomMargin: Theme.paddingMedium
}
}
Label {
id: lblRtByName
visible: type.length
anchors {
left: icon.right
leftMargin: Theme.paddingMedium
verticalCenter: icon.verticalCenter
}
text: {
var action = "";
switch(type){
@ -42,13 +40,17 @@ Item {
action = qsTr('followed you');
break;
default:
ministatus.visible = false
miniStatus.visible = false
action = type;
}
return typeof reblog_account_username !== "undefined" ? '@' + reblog_account_username + ' ' + action : ''
return typeof reblog_account_username !== "undefined" ? '@' + reblog_account_username + " " + action : " "
}
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
anchors {
left: icon.right
leftMargin: Theme.paddingMedium
verticalCenter: icon.verticalCenter
}
}
}

View file

@ -3,31 +3,30 @@ import Sailfish.Silica 1.0
import "../../lib/API.js" as Logic
import "."
SilicaListView {
id: myList
property string type;
property string type
property string title
property string vwPlaceholderText: qsTr("Loading")
property string vwPlaceholderHint: qsTr("please wait...")
property string description
property ListModel mdl: []
property variant params: []
property var locale: Qt.locale()
property bool autoLoadMore : true;
property bool loadStarted : false;
property int scrollOffset;
property bool autoLoadMore: true
property bool loadStarted: false
property int scrollOffset
property string action: ""
property variant vars
property variant conf
property bool notifier : false;
property bool notifier: false
model: mdl
signal notify (string what, int num)
onNotify: {
console.log(what + " - " + num)
}
signal openDrawer (bool setDrawer)
onOpenDrawer: {
//console.log("Open drawer: " + setDrawer)
@ -37,53 +36,74 @@ SilicaListView {
console.log("LIST send signal emitted with notice: " + notice)
}
BusyIndicator {
size: BusyIndicatorSize.Large
running: myList.model.count === 0 && !viewPlaceHolder.visible
anchors.centerIn: parent
}
header: PageHeader {
title: myList.title
description: myList.description
}
BusyLabel {
id: myListBusyLabel
running: model.count === 0
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
Timer {
interval: 5000
running: true
onTriggered: {
myListBusyLabel.visible = false
loadStatusPlaceholder.visible = true
}
}
}
ViewPlaceholder {
id: viewPlaceHolder
id: loadStatusPlaceholder
visible: false
enabled: model.count === 0
text: vwPlaceholderText
hintText: vwPlaceholderHint
text: qsTr("Nothing found")
}
PullDownMenu {
id: mainPulleyMenu
MenuItem {
text: qsTr("Settings")
visible: !profilePage
onClicked: {
pageStack.push(Qt.resolvedUrl("../Settings.qml"), {})
pageStack.push(Qt.resolvedUrl("../SettingsPage.qml"), {})
}
}
MenuItem {
text: qsTr("Load more")
text: qsTr("New Toot")
visible: !profilePage
onClicked: {
pageStack.push(Qt.resolvedUrl("../ConversationPage.qml"), {
headerTitle: qsTr("New Toot"),
type: "new"
})
}
}
MenuItem {
text: qsTr("Open in Browser")
visible: !mainPage
onClicked: {
Qt.openUrlExternally(url)
}
}
MenuItem {
text: qsTr("Reload")
onClicked: {
loadData("prepend")
}
}
}
clip: true
section {
property: 'section'
delegate: SectionHeader {
height: Theme.itemSizeExtraSmall
text: Format.formatDate(section, Formatter.DateMedium)
}
}
delegate: VisualContainer {
} //Toot {}
delegate: VisualContainer {}
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 800 }
@ -95,13 +115,12 @@ SilicaListView {
}
onCountChanged: {
loadStarted = false;
loadStarted = false
/*contentY = scrollOffset
console.log("CountChanged!")*/
}
footer: Item{
footer: Item {
visible: autoLoadMore
width: parent.width
height: Theme.itemSizeLarge
@ -114,24 +133,29 @@ SilicaListView {
loadData("append")
}
}
BusyIndicator {
running: loadStarted
visible: myListBusyLabel.running ? false : true
size: BusyIndicatorSize.Small
running: loadStarted;
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
}
onContentYChanged: {
if (Math.abs(contentY - scrollOffset) > Theme.itemSizeMedium) {
openDrawer(contentY - scrollOffset > 0 ? false : true )
scrollOffset = contentY
}
if(contentY+height > footerItem.y && !loadStarted && autoLoadMore){
if(contentY+height > footerItem.y && !loadStarted && autoLoadMore) {
loadData("append")
loadStarted = true;
loadStarted = true
}
}
VerticalScrollDecorator {}
WorkerScript {
@ -144,7 +168,6 @@ SilicaListView {
if (messageObject.fireNotification && notifier){
Logic.notifier(messageObject.data)
}
}
}
@ -159,17 +182,18 @@ SilicaListView {
loadData("prepend")
}
}
function loadData(mode){
var p = [];
if (params.length)
function loadData(mode) {
var p = []
if (params.length) {
for(var i = 0; i<params.length; i++)
p.push(params[i])
if (mode === "append" && model.count){
p.push({name: 'max_id', data: model.get(model.count-1).id});
}
if (mode === "prepend" && model.count){
p.push({name:'since_id', data: model.get(0).id});
if (mode === "append" && model.count) {
p.push({name: 'max_id', data: model.get(model.count-1).id})
}
if (mode === "prepend" && model.count) {
p.push({name:'since_id', data: model.get(0).id})
}
var msg = {
@ -178,10 +202,10 @@ SilicaListView {
'model' : model,
'mode' : mode,
'conf' : Logic.conf
};
}
console.log(JSON.stringify(msg))
if (type !== "")
worker.sendMessage(msg);
worker.sendMessage(msg)
}
}

View file

@ -2,34 +2,61 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import QtMultimedia 5.0
Item {
id: myMedia
property string type : ""
property string previewURL: ""
property string mediaURL: ""
Rectangle {
opacity: 0.2
anchors.fill: parent
opacity: 0.4
color: Theme.highlightDimmerColor
anchors.fill: parent
}
Image {
visible: type == 'image'
opacity: img.status === Image.Ready ? 0.0 : 1.0
Behavior on opacity { FadeAnimator {} }
source: "image://theme/icon-m-image?"
anchors.centerIn: parent
source: "image://theme/icon-m-image"
}
Image {
visible: type == 'video' || type == "gifv"
opacity: img.status === Image.Ready ? 0.0 : 1.0
Behavior on opacity { FadeAnimator {} }
source: "image://theme/icon-m-file-video?"
anchors.centerIn: parent
}
Image {
visible: type == 'audio'
//opacity: img.status === Image.Ready ? 0.0 : 1.0
Behavior on opacity { FadeAnimator {} }
source: "image://theme/icon-m-file-audio?"
anchors.centerIn: parent
}
Rectangle {
id: progressRec
anchors.bottom: parent.bottom
width: 0
height: Theme.paddingSmall
color: Theme.highlightBackgroundColor
anchors.bottom: parent.bottom
}
Image {
id: img
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
visible: type != 'audio'
asynchronous: true
opacity: status === Image.Ready ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {} }
source: previewURL
fillMode: Image.PreserveAspectCrop
anchors.fill: parent
onProgressChanged: {
if (progress != 1)
progressRec.width = parent.width * progress
@ -38,38 +65,49 @@ Item {
}
}
MouseArea {
anchors.fill: parent
onClicked: {
pageStack.push(Qt.resolvedUrl("./ImageFullScreen.qml"), {"previewURL": previewURL, "mediaURL": mediaURL, "type": type})
pageStack.push(Qt.resolvedUrl("./MediaFullScreen.qml"), {
"previewURL": previewURL,
"mediaURL": mediaURL,
"type": type
})
}
}
Image {
id: videoIcon
visible: type === "video" || type === "gifv"
source: "image://theme/icon-l-play?"
anchors.centerIn: parent
source: "image://theme/icon-l-play"
}
BusyIndicator {
id: mediaLoader
visible: type != 'audio'
size: BusyIndicatorSize.Large
running: img.status !== Image.Ready
opacity: img.status === Image.Ready ? 0.0 : 1.0
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
Rectangle {
anchors.fill: parent
id: mediaWarning
color: Theme.highlightDimmerColor
visible: typeof status_sensitive != 'undefined' && status_sensitive ? true : false
visible: typeof status_sensitive != "undefined" && status_sensitive ? true : false
Image {
source: "image://theme/icon-l-attention?"+Theme.highlightColor
anchors.centerIn: parent
}
anchors.fill: parent
MouseArea {
anchors.fill: parent
onClicked: parent.visible = false;
onClicked: parent.visible = false
}
}
}
}

View file

@ -2,46 +2,53 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0
SilicaGridView {
signal slideshowShow(int vIndex);
signal slideshowIndexChanged(int vIndex);
id: gridView
property bool isPortrait: false
signal slideshowShow(int vIndex)
signal slideshowIndexChanged(int vIndex)
onSlideshowIndexChanged: {
navigateTo(vIndex)
}
id: gridView
property bool isPortrait: false
ListModel {
id: listModel
ListElement {
icon: "image://theme/icon-m-home"
icon: "image://theme/icon-m-home?"
slug: "home"
name: "Home"
active: true
unread: false
}
ListElement {
icon: "image://theme/icon-m-alarm"
icon: "image://theme/icon-m-alarm?"
slug: "notifications"
name: "Notifications"
active: false
}
ListElement {
icon: "image://theme/icon-m-whereami"
icon: "image://theme/icon-m-whereami?"
slug: "local"
name: "Local"
active: false
unread: false
}
ListElement {
icon: "image://theme/icon-m-website"
icon: "image://theme/icon-m-website?"
slug: "federated"
name: "Federated"
active: false
unread: false
}
ListElement {
icon: "image://theme/icon-m-search"
icon: "image://theme/icon-m-search?"
slug: "search"
name: "Search"
active: false
@ -49,16 +56,13 @@ SilicaGridView {
}
}
model: listModel
anchors.fill: parent
currentIndex: -1
cellWidth: isPortrait ? gridView.width : gridView.width / model.count
cellHeight: isPortrait ? gridView.height/model.count : gridView.height
anchors.fill: parent
delegate: BackgroundItem {
clip: true
id: rectangle
clip: true
width: gridView.cellWidth
height: gridView.cellHeight
GridView.onAdd: AddAnimation {
@ -67,97 +71,58 @@ SilicaGridView {
GridView.onRemove: RemoveAnimation {
target: rectangle
}
GlassItem {
id: effect
visible: !isPortrait && unread
dimmed: true
color: Theme.highlightColor
width: Theme.itemSizeMedium
height: Theme.itemSizeMedium
dimmed: true
anchors.bottom: parent.bottom
anchors.bottomMargin: -height/2
anchors.horizontalCenter: parent.horizontalCenter
color: Theme.highlightColor
anchors {
bottom: parent.bottom
bottomMargin: -height/2
horizontalCenter: parent.horizontalCenter
}
}
GlassItem {
id: effect2
visible: isPortrait && unread
dimmed: false
color: Theme.highlightColor
width: Theme.itemSizeMedium
height: Theme.itemSizeMedium
dimmed: false
anchors.right: parent.right;
anchors.rightMargin: -height/2;
anchors.verticalCenter: parent.verticalCenter
color: Theme.highlightColor
anchors {
right: parent.right
rightMargin: -height/2
verticalCenter: parent.verticalCenter
}
}
OpacityRampEffect {
sourceItem: label
offset: 0.5
}
/*Image {
source: model.icon + (highlighted
? Theme.highlightColor
: (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
anchors.centerIn: parent
}*/
ColorOverlay {
anchors.fill: image
source: image
color: (highlighted ? Theme.highlightColor : (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
}
Image {
id: image
visible: false
source: model.icon
sourceSize.width: Theme.iconSizeMedium
sourceSize.height: Theme.iconSizeMedium
source: model.icon// +'?'+ (highlighted ? Theme.highlightColor : (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
anchors.centerIn: parent
visible: false
// smooth: true
}
Text {
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.paddingSmall
anchors.left: parent.left
anchors.right: parent.right
horizontalAlignment: Text.AlignHCenter
visible: false
text: model.name
font.pixelSize: Theme.fontSizeExtraSmall/2
color: (highlighted
? Theme.highlightColor
: (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
ColorOverlay {
source: image
color: (highlighted ? Theme.highlightColor : (model.active ? Theme.secondaryHighlightColor : Theme.primaryColor))
anchors.fill: image
}
Label {
id: label
visible: false
anchors {
bottom: parent.bottom
}
horizontalAlignment : Text.AlignHCente
width: parent.width
color: (highlighted ? Theme.highlightColor : Theme.secondaryHighlightColor)
text: {
return model.name.toUpperCase();
}
font {
pixelSize: Theme.fontSizeExtraSmall
family: Theme.fontFamilyHeading
}
}
onClicked: {
slideshowShow(index)
console.log(index)
navigateTo(model.slug)
effect.state = "right"
}
}
function navigateTo(slug){
for(var i = 0; i < listModel.count; i++){
if (listModel.get(i).slug === slug || i===slug)
@ -166,7 +131,6 @@ SilicaGridView {
listModel.setProperty(i, 'active', false);
}
console.log(slug)
}
VerticalScrollDecorator {}

View file

@ -1,83 +1,192 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Item {
id: header
property int value: 0;
property string title: "";
property string description: "";
property string image: "";
property string bg: "";
id: profileHeader
property int value: 0
property string title: ""
property string description: ""
property string image: ""
property string bg: ""
width: parent.width
height: icon.height + Theme.paddingLarge*2
height: isPortrait ? (avatarImage.height + Theme.paddingLarge*3 + infoLbl.height) : (avatarImage.height + Theme.paddingLarge*2.5 + infoLbl.height)
Rectangle {
id: bgImage
anchors.fill: parent
opacity: 0.2
opacity: 0.7
gradient: Gradient {
GradientStop { position: 0.0; color: Theme.highlightBackgroundColor }
GradientStop { position: 1.0; color: Theme.highlightBackgroundColor }
GradientStop { position: 0.0; color: Theme.highlightDimmerColor }
GradientStop { position: 2.0; color: Theme.highlightBackgroundColor }
}
anchors.fill: parent
Image {
anchors.fill: bgImage
asynchronous: true
fillMode: Image.PreserveAspectCrop
source: bg
opacity: 0.8
}
}
Image {
id: icon
anchors {
left: parent.left
leftMargin: Theme.paddingLarge
top: parent.top
topMargin: Theme.paddingLarge
}
asynchronous: true
width: description === "" ? Theme.iconSizeMedium : Theme.iconSizeLarge
height: width
source:
if (icon.status === Image.Error)
source = "../../images/icon-l-profile.svg?" + (pressed
? Theme.highlightColor
: Theme.primaryColor)
else image
}
Column {
anchors {
left: icon.right
leftMargin: Theme.paddingLarge
right: parent.right
rightMargin: Theme.paddingLarge
verticalCenter: parent.verticalCenter
}
Label {
id: ttl
text:
if (title === "") {
description.split('@')[0]
}
else title
height: contentHeight
color: Theme.highlightColor
font.pixelSize: Theme.fontSizeLarge
font.family: Theme.fontFamilyHeading
horizontalAlignment: Text.AlignRight
truncationMode: TruncationMode.Fade
width: parent.width
}
Label {
height: description === "" ? 0 : contentHeight
text: "@"+description
color: Theme.secondaryHighlightColor
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamilyHeading
horizontalAlignment: Text.AlignRight
truncationMode: TruncationMode.Fade
width: parent.width
opacity: 0.6
anchors.fill: parent
}
}
Image {
id: avatarImage
asynchronous: true
source: if (avatarImage.status === Image.Error)
source = "../../images/icon-l-profile.svg?" + Theme.primaryColor
else image
width: isPortrait ? Theme.iconSizeLarge : Theme.iconSizeExtraLarge
height: width
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin
top: parent.top
topMargin: Theme.paddingLarge * 1.5
}
Button {
id: imageButton
opacity: 0
width: Theme.iconSizeExtraLarge * 1.2
anchors {
top: parent.top
left: parent.left
bottom: parent.bottom
}
onClicked: {
pageStack.push(Qt.resolvedUrl("ProfileImage.qml"), {
"image": image
})
}
}
}
Column {
anchors {
top: parent.top
topMargin: Theme.paddingLarge
left: avatarImage.right
leftMargin: Theme.horizontalPageMargin
right: parent.right
rightMargin: Theme.horizontalPageMargin
verticalCenter: parent.verticalCenter
}
Label {
id: profileTitle
text: title ? title : description.split('@')[0]
font.pixelSize: Theme.fontSizeLarge
font.family: Theme.fontFamilyHeading
color: Theme.highlightColor
truncationMode: TruncationMode.Fade
width: parent.width
height: contentHeight
horizontalAlignment: Text.AlignRight
}
Label {
id: profileDescription
text: "@"+description
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamilyHeading
color: Theme.secondaryHighlightColor
truncationMode: TruncationMode.Fade
width: parent.width
height: contentHeight
horizontalAlignment: Text.AlignRight
}
}
Row {
id: infoLbl
spacing: Theme.paddingLarge
layoutDirection: Qt.RightToLeft
height: followed_by || locked || bot || group ? Theme.iconSizeSmall + Theme.paddingSmall : 0
anchors {
top: avatarImage.bottom
topMargin: isPortrait ? Theme.paddingMedium : 0
left: parent.left
leftMargin: Theme.horizontalPageMargin
right: parent.right
rightMargin: Theme.horizontalPageMargin
}
Rectangle {
id: groupBg
visible: (group ? true : false)
radius: Theme.paddingSmall
color: Theme.secondaryHighlightColor
width: groupLbl.width + 2*Theme.paddingLarge
height: parent.height
Label {
id: groupLbl
text: qsTr("Group")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
id: followingBg
visible: (followed_by ? true : false)
radius: Theme.paddingSmall
color: Theme.secondaryHighlightColor
width: followingLbl.width + 2*Theme.paddingLarge
height: parent.height
Label {
id: followingLbl
text: qsTr("Follows you")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
id: lockedBg
visible: (locked ? true : false)
radius: Theme.paddingSmall
color: Theme.secondaryHighlightColor
width: lockedImg.width + 2*Theme.paddingLarge
height: parent.height
HighlightImage {
id: lockedImg
source: "image://theme/icon-s-secure?"
width: Theme.fontSizeExtraSmall
height: width
color: Theme.primaryColor
anchors.horizontalCenter: lockedBg.horizontalCenter
anchors.verticalCenter: lockedBg.verticalCenter
}
}
Rectangle {
id: botBg
visible: (bot ? true : false)
radius: Theme.paddingSmall
color: Theme.secondaryHighlightColor
width: botLbl.width + 2*Theme.paddingLarge
height: parent.height
Label {
id: botLbl
text: qsTr("Bot")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
}
}

View file

@ -0,0 +1,27 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
FullscreenContentPage {
id: profileImage
property string image: ""
allowedOrientations: Orientation.All
Image {
source: image
fillMode: Image.PreserveAspectFit
anchors.fill: parent
}
IconButton {
icon.source: "image://theme/icon-m-dismiss"
onClicked: pageStack.pop()
anchors {
top: profileImage.top
topMargin: Theme.horizontalPageMargin
right: parent.right
rightMargin: Theme.horizontalPageMargin
}
}
}

View file

@ -1,190 +0,0 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0
BackgroundItem {
signal send (string notice)
id: delegate
//property string text: "0"
width: parent.width
signal navigateTo(string link)
height: lblText.paintedHeight + (lblText.text.length > 0 ? Theme.paddingLarge : 0 )+ lblName.paintedHeight + (type.length ? Theme.paddingLarge + iconRT.height : 0) + Theme.paddingLarge
Image {
id: iconRT
y: Theme.paddingLarge
anchors {
right: avatar.right
}
visible: type.length
width: Theme.iconSizeExtraSmall
height: width
source: "../../images/boosted.svg"
}
Label {
id: lblRtByName
visible: type.length
anchors {
left: lblName.left
bottom: iconRT.bottom
}
text: {
var action;
switch(type){
case "reblog":
action = qsTr('boosted');
break;
case "favourite":
action = qsTr('favourited');
break;
case "follow":
action = qsTr('followed you');
break;
default:
action = type;
}
return '@' + retweetScreenName + ' ' + action
}
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.secondaryColor
}
Image {
id: avatar
x: Theme.horizontalPageMargin
y: Theme.paddingLarge + (type.length ? iconRT.height+Theme.paddingMedium : 0)
asynchronous: true
width: Theme.iconSizeMedium
height: width
smooth: true
source: account_avatar
visible: true
MouseArea {
anchors.fill: parent
onClicked: {
pageStack.push(Qt.resolvedUrl("../Profile.qml"), {
"display_name": account_display_name,
"username": account_username,
"profileImage": account_avatar
})
}
}
}
Label {
id: lblName
anchors {
top: avatar.top
topMargin: 0
left: avatar.right
leftMargin: Theme.paddingMedium
}
text: account_display_name
font.weight: Font.Bold
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
}
Image {
id: iconVerified
y: Theme.paddingLarge
anchors {
left: lblName.right
leftMargin: Theme.paddingSmall
verticalCenter: lblName.verticalCenter
}
visible: account_locked
width: account_locked ? Theme.iconSizeExtraSmall*0.8 : 0
opacity: 0.8
height: width
source: "image://theme/icon-s-secure?" + (pressed
? Theme.highlightColor
: Theme.primaryColor)
}
Label {
id: lblScreenName
anchors {
left: iconVerified.right
right: lblDate.left
leftMargin: Theme.paddingMedium
baseline: lblName.baseline
}
truncationMode: TruncationMode.Fade
text: '@'+account_username
font.pixelSize: Theme.fontSizeExtraSmall
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
}
Label {
function timestamp() {
var txt = Format.formatDate(created_at, Formatter.Timepoint)
var elapsed = Format.formatDate(created_at, Formatter.DurationElapsedShort)
return (elapsed ? elapsed : txt )
}
id: lblDate
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
text: Format.formatDate(created_at, new Date() - created_at < 60*60*1000 ? Formatter.DurationElapsedShort : Formatter.TimeValueTwentyFourHours)
font.pixelSize: Theme.fontSizeExtraSmall
horizontalAlignment: Text.AlignRight
anchors {
right: parent.right
baseline: lblName.baseline
rightMargin: Theme.paddingLarge
}
}
Label {
id: lblText
anchors {
left: lblName.left
right: parent.right
top: lblScreenName.bottom
topMargin: Theme.paddingSmall
rightMargin: Theme.paddingLarge
}
height: content.length ? paintedHeight : 0
onLinkActivated: {
console.log(link)
if (link[0] === "@") {
pageStack.push(Qt.resolvedUrl("../Profile.qml"), {
"name": "",
"username": link.substring(1),
"profileImage": ""
})
} else if (link[0] === "#") {
pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true;
if (check)
page.onLinkActivated(link)
return check;
}));
send(link)
} else {
Qt.openUrlExternally(link);
}
}
text: content
textFormat: Text.RichText
linkColor : Theme.highlightColor
wrapMode: Text.Wrap
maximumLineCount: 6
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
}
onClicked: {
pageStack.push(Qt.resolvedUrl("../Conversation.qml"), {
toot_id: id,
title: account_display_name,
description: '@'+account_username,
avatar: account_avatar,
type: "reply"
})
}
}

View file

@ -2,24 +2,35 @@ import QtQuick 2.2
import Sailfish.Silica 1.0
import "../../lib/API.js" as Logic
BackgroundItem {
id: delegate
signal send (string notice)
signal navigateTo(string link)
width: parent.width
height: mnu.height + miniHeader.height + (typeof attachments !== "undefined" && attachments.count ? media.height + Theme.paddingLarge + Theme.paddingMedium: Theme.paddingLarge) + lblContent.height + Theme.paddingLarge + (ministatus.visible ? ministatus.height : 0)
height: if (myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) {
mnu.height + miniHeader.height + Theme.paddingLarge + lblContent.height + Theme.paddingLarge + (miniStatus.visible ? miniStatus.height : 0)
} else mnu.height + miniHeader.height + (typeof attachments !== "undefined" && attachments.count ? media.height + Theme.paddingLarge + Theme.paddingMedium: Theme.paddingLarge) + lblContent.height + Theme.paddingLarge + (miniStatus.visible ? miniStatus.height : 0) + (iconDirectMsg.visible ? iconDirectMsg.height : 0)
// Background for Direct Messages in Notification View
Rectangle {
x: 0;
y: 0;
visible: status_visibility == 'direct'
id: bgDirect
x: 0
y: 0
visible: model.status_visibility === "direct"
width: parent.width
height: parent.height
opacity: 0.3
color: Theme.highlightBackgroundColor;
gradient: Gradient {
GradientStop { position: -1.5; color: "transparent" }
GradientStop { position: 0.6; color: Theme.highlightBackgroundColor }
}
}
// Element showing reblog, favourite, follow status on top of Toot
MiniStatus {
id: ministatus
id: miniStatus
anchors {
leftMargin: Theme.horizontalPageMargin
rightMargin: Theme.horizontalPageMargin
@ -28,55 +39,74 @@ BackgroundItem {
}
}
// Account avatar
Image {
id: avatar
anchors {
top: ministatus.visible ? ministatus.bottom : parent.top
topMargin: ministatus.visible ? Theme.paddingMedium : Theme.paddingLarge
left: parent.left
leftMargin: Theme.horizontalPageMargin
}
opacity: status === Image.Ready ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {} }
asynchronous: true
width: Theme.iconSizeMedium
height: width
smooth: true
source: account_avatar
visible: true
width: Theme.iconSizeMedium
height: width
anchors {
top: miniStatus.visible ? miniStatus.bottom : parent.top
topMargin: miniStatus.visible ? Theme.paddingMedium : Theme.paddingLarge
left: parent.left
leftMargin: Theme.horizontalPageMargin
}
onStatusChanged: {
if (avatar.status === Image.Error)
source = "../../images/icon-m-profile.svg?" + (pressed
? Theme.highlightColor
: Theme.primaryColor)
source = "../../images/icon-m-profile.svg?" + Theme.primaryColor
}
MouseArea {
anchors.fill: parent
onClicked: {
pageStack.push(Qt.resolvedUrl("../Profile.qml"), {
pageStack.push(Qt.resolvedUrl("../ProfilePage.qml"), {
"display_name": model.account_display_name,
"username": model.account_acct,
"user_id": model.account_id,
"profileImage": model.account_avatar,
"profileBackground": model.account_header
})
"profileBackground": model.account_header,
"note": model.account_note,
"url": model.account_url,
"followers_count": model.account_followers_count,
"following_count": model.account_following_count,
"statuses_count": model.account_statuses_count,
"locked": model.account_locked,
"bot": model.account_bot,
"group": model.account_group
} )
}
}
Image {
id: iconTR
// Avatar dimmer for facourite and reblog notifications
Rectangle {
visible: myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )
opacity: 0.5
color: Theme.highlightDimmerColor
anchors.fill: avatar
}
Icon {
id: iconDirectMsg
visible: status_visibility === "direct"
width: Theme.iconSizeMedium
height: width
source: "image://theme/icon-m-mail?" + Theme.primaryColor
color: Theme.primaryColor
anchors {
horizontalCenter: avatar.horizontalCenter
top: avatar.bottom
topMargin: Theme.paddingMedium
left: avatar.left
}
visible: typeof status_reblogged !== "undefined" && status_reblogged
width: Theme.iconSizeExtraSmall
height: width
source: "image://theme/icon-s-retweet"
}
}
Rectangle {
color: Theme.highlightDimmerColor
id: bgReblogAvatar
color: Theme.secondaryColor
width: Theme.iconSizeSmall
height: width
visible: typeof status_reblog !== "undefined" && status_reblog
@ -86,18 +116,43 @@ BackgroundItem {
left: parent.left
leftMargin: -width/3
}
Image {
id: reblogAvatar
asynchronous: true
width: Theme.iconSizeSmall
height: width
smooth: true
opacity: status === Image.Ready ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {} }
source: typeof reblog_account_avatar !== "undefined" ? reblog_account_avatar : ''
visible: typeof status_reblog !== "undefined" && status_reblog
width: Theme.iconSizeSmall
height: width
}
MouseArea {
anchors.fill: parent
onClicked: {
pageStack.push(Qt.resolvedUrl("../ProfilePage.qml"), {
"display_name": model.reblog_account_display_name,
"username": model.reblog_account_acct,
"user_id": model.reblog_account_id,
"profileImage": model.reblog_account_avatar,
"profileBackground": model.account_header,
"note": model.reblog_account_note,
"url": model.reblog_account_url,
"followers_count": model.reblog_account_followers_count,
"following_count": model.reblog_account_following_count,
"statuses_count": model.reblog_account_statuses_count,
"locked": model.reblog_account_locked,
"bot": model.reblog_account_bot,
"group": model.reblog_account_group
} )
}
}
}
}
// Display name, username, date of Toot
MiniHeader {
id: miniHeader
anchors {
@ -106,24 +161,43 @@ BackgroundItem {
right: parent.right
}
}
Text {
// Toot content
Label {
id: lblContent
visible: model.type !== "follow"
text: if (myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) {
content
} else content.replace(new RegExp("<a ", 'g'), '<a style="text-decoration: none; color:'+(pressed ? Theme.secondaryColor : Theme.highlightColor)+'" ')
textFormat: myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" ) ? Text.StyledText : Text.RichText
font.pixelSize: Theme.fontSizeSmall
wrapMode: Text.Wrap
truncationMode: TruncationMode.Elide
color: if (myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) {
(pressed ? Theme.secondaryHighlightColor : (!highlight ? Theme.secondaryColor : Theme.secondaryHighlightColor))
} else (pressed ? Theme.highlightColor : (!highlight ? Theme.primaryColor : Theme.secondaryColor))
linkColor: if (myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) {
Theme.secondaryHighlightColor
} else Theme.highlightColor
height: if (model.type === "follow") {
Theme.paddingLarge
} else if (myList.type === "notifications" && ( model.type === "favourite" || model.type === "reblog" )) {
Math.min( implicitHeight, Theme.itemSizeExtraLarge * 1.5 )
} else content.length ? ( contentWarningLabel.paintedHeight > paintedHeight ? contentWarningLabel.paintedHeight : paintedHeight ) : 0
anchors {
left: miniHeader.left
leftMargin: Theme.paddingMedium
right: miniHeader.right
rightMargin: Theme.horizontalPageMargin
rightMargin: Theme.horizontalPageMargin + Theme.paddingMedium
top: miniHeader.bottom
topMargin: Theme.paddingSmall
bottomMargin: Theme.paddingLarge
}
height: content.length ? (contentWarningLabel.paintedHeight > paintedHeight ? contentWarningLabel.paintedHeight : paintedHeight) : 0
onLinkActivated: {
var test = link.split("/")
console.log(link)
console.log(JSON.stringify(test))
console.log(JSON.stringify(test.length))
if (test.length === 5 && (test[3] === "tags" || test[3] === "tag") ) {
pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true;
@ -134,36 +208,33 @@ BackgroundItem {
send(link)
// temporary solution for access to user profiles via toots
} else if (test.length === 4 && test[3][0] === "@" ) {
tlSearch.search = decodeURIComponent("@"+test[3].substring(1)+"@"+test[2])
slideshow.positionViewAtIndex(4, ListView.SnapToItem)
navigation.navigateTo('search')
// Original component
/* pageStack.push(Qt.resolvedUrl("../Profile.qml"), {
"name": "",
"username": test[3].substring(1)+"@"+test[2],
"profileImage": ""
}) */
pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true;
if (check)
page.onLinkActivated(link)
return check;
}));
} else {
Qt.openUrlExternally(link);
}
}
text: content.replace(new RegExp("<a ", 'g'), '<a style="text-decoration: none; color:'+(pressed ? Theme.secondaryColor : Theme.highlightColor)+'" ')
linkColor : Theme.highlightColor
wrapMode: Text.Wrap
textFormat: Text.RichText
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : (!highlight ? Theme.primaryColor : Theme.secondaryColor))
// Content warning cover for Toots
Rectangle {
anchors.fill: parent
radius: 2
id: contentWarningBg
color: Theme.highlightDimmerColor
visible: status_spoiler_text.length > 0
anchors.fill: parent
Label {
id: contentWarningLabel
text: model.status_spoiler_text
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
truncationMode: TruncationMode.Fade
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
width: parent.width
anchors {
topMargin: Theme.paddingSmall
left: parent.left
@ -173,40 +244,43 @@ BackgroundItem {
rightMargin: Theme.paddingMedium
bottomMargin: Theme.paddingSmall
}
width: parent.width
truncationMode: TruncationMode.Fade
color: Theme.highlightColor
wrapMode: Text.Wrap
text: model.status_spoiler_text
}
MouseArea {
anchors.fill: parent
onClicked: parent.visible = false;
onClicked: parent.visible = false
}
}
}
// Displays media in Toots
MediaBlock {
id: media
visible: (myList.type === "notifications" && ( type === "favourite" || type === "reblog" )) ? false : true
model: typeof attachments !== "undefined" ? attachments : Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject')
height: Theme.iconSizeExtraLarge * 2
anchors {
left: lblContent.left
leftMargin: isPortrait ? 0 : Theme.itemSizeSmall
right: lblContent.right
rightMargin: isPortrait ? 0 : Theme.itemSizeLarge * 1.2
top: lblContent.bottom
topMargin: Theme.paddingSmall
topMargin: Theme.paddingMedium
bottomMargin: Theme.paddingLarge
}
model: typeof attachments !== "undefined" ? attachments : Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
height: 100
}
// Context menu for Toots
ContextMenu {
id: mnu
MenuItem {
enabled: model.type !== "follow"
text: typeof model.reblogged !== "undefined" && model.reblogged ? qsTr("Unboost") : qsTr("Boost")
id: mnuBoost
visible: model.type !== "follow"
enabled: model.status_visibility !== "direct"
text: typeof model.status_reblogged !== "undefined" && model.status_reblogged ? qsTr("Unboost") : qsTr("Boost")
onClicked: {
var status = typeof model.reblogged !== "undefined" && model.reblogged
var status = typeof model.status_reblogged !== "undefined" && model.status_reblogged
worker.sendMessage({
"conf" : Logic.conf,
"params" : [],
@ -214,36 +288,40 @@ BackgroundItem {
"bgAction": true,
"action" : "statuses/"+model.status_id+"/" + (status ? "unreblog" : "reblog")
})
model.reblogs_count = !status ? model.reblogs_count+1 : (model.reblogs_count > 0 ? model.reblogs_count-1 : model.reblogs_count);
model.reblogged = !model.reblogged
model.status_reblogs_count = !status ? model.status_reblogs_count+1 : (model.status_reblogs_count > 0 ? model.status_reblogs_count-1 : model.status_reblogs_count);
model.status_reblogged = !model.status_reblogged
}
Image {
Icon {
id: icRT
source: "image://theme/icon-s-retweet?" + (!model.status_reblogged ? Theme.highlightColor : Theme.primaryColor)
width: Theme.iconSizeSmall
height: width
anchors {
leftMargin: Theme.horizontalPageMargin
left: parent.left
verticalCenter: parent.verticalCenter
}
width: Theme.iconSizeExtraSmall
height: width
source: "image://theme/icon-s-retweet?" + (!model.reblogged ? Theme.highlightColor : Theme.primaryColor)
}
Label {
text: status_reblogs_count
font.pixelSize: Theme.fontSizeSmall
color: !model.status_reblogged ? Theme.highlightColor : Theme.primaryColor
anchors {
left: icRT.right
leftMargin: Theme.paddingMedium
verticalCenter: parent.verticalCenter
}
text: reblogs_count
font.pixelSize: Theme.fontSizeExtraSmall
color: !model.reblogged ? Theme.highlightColor : Theme.primaryColor
}
}
MenuItem {
enabled: model.type !== "follow"
text: typeof model.favourited !== "undefined" && model.favourited ? qsTr("Unfavorite") : qsTr("Favorite")
id: mnuFavourite
visible: model.type !== "follow"
text: typeof model.status_favourited !== "undefined" && model.status_favourited ? qsTr("Unfavorite") : qsTr("Favorite")
onClicked: {
var status = typeof model.favourited !== "undefined" && model.favourited
var status = typeof model.status_favourited !== "undefined" && model.status_favourited
worker.sendMessage({
"conf" : Logic.conf,
"params" : [],
@ -251,54 +329,129 @@ BackgroundItem {
"bgAction": true,
"action" : "statuses/"+model.status_id+"/" + (status ? "unfavourite" : "favourite")
})
model.favourites_count = !status ? model.favourites_count+1 : (model.favourites_count > 0 ? model.favourites_count-1 : model.favourites_count);
model.favourited = !model.favourited
model.status_favourites_count = !status ? model.status_favourites_count+1 : (model.status_favourites_count > 0 ? model.status_favourites_count-1 : model.status_favourites_count);
model.status_favourited = !model.status_favourited
}
Image {
Icon {
id: icFA
source: "image://theme/icon-s-favorite?" + (!model.status_favourited ? Theme.highlightColor : Theme.primaryColor)
width: Theme.iconSizeSmall
height: width
anchors {
leftMargin: Theme.horizontalPageMargin
left: parent.left
leftMargin: Theme.horizontalPageMargin
verticalCenter: parent.verticalCenter
}
width: Theme.iconSizeExtraSmall
height: width
source: "image://theme/icon-s-favorite?" + (!model.favourited ? Theme.highlightColor : Theme.primaryColor)
}
Label {
text: status_favourites_count
font.pixelSize: Theme.fontSizeSmall
color: !model.status_favourited ? Theme.highlightColor : Theme.primaryColor
anchors {
left: icFA.right
leftMargin: Theme.paddingMedium
verticalCenter: parent.verticalCenter
}
text: favourites_count
font.pixelSize: Theme.fontSizeExtraSmall
color: !model.favourited ? Theme.highlightColor : Theme.primaryColor
}
}
MenuItem {
id: mnuBookmark
visible: model.type !== "follow"
text: typeof model.status_bookmarked !== "undefined" && model.status_bookmarked ? qsTr("Remove Bookmark") : qsTr("Bookmark")
onClicked: {
var status = typeof model.status_bookmarked !== "undefined" && model.status_bookmarked
worker.sendMessage({
"conf" : Logic.conf,
"params" : [],
"method" : "POST",
"bgAction": true,
"action" : "statuses/"+model.status_id+"/" + (status ? "unbookmark" : "bookmark")
})
model.status_bookmarked = !model.status_bookmarked
}
Icon {
id: icBM
source: "../../images/icon-s-bookmark.svg?"
color: !model.status_bookmarked ? Theme.highlightColor : Theme.primaryColor
width: Theme.iconSizeSmall
height: width
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin + Theme.paddingMedium
verticalCenter: parent.verticalCenter
}
}
}
MenuItem {
id: mnuMention
visible: model.type === "follow"
text: qsTr("Mention")
onClicked: {
pageStack.push(Qt.resolvedUrl("../ConversationPage.qml"), {
headerTitle: qsTr("Mention"),
description: "@"+reblog_account_acct,
type: "new"
})
}
Icon {
id: icMT
source: "image://theme/icon-s-chat?" + (!model.status_favourited ? Theme.highlightColor : Theme.primaryColor)
width: Theme.iconSizeSmall
height: width
anchors {
left: parent.left
leftMargin: Theme.horizontalPageMargin + Theme.paddingMedium
verticalCenter: parent.verticalCenter
}
}
}
}
// Open ConversationPage and show other Toots in thread (if available) or ProfilePage if new Follower
onClicked: {
var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
if (typeof mdl !== "undefined")
m.append(mdl.get(index))
pageStack.push(Qt.resolvedUrl("../Conversation.qml"), {
headerTitle: "Conversation",
toot_id: status_id,
toot_url: status_url,
title: account_display_name,
description: '@'+account_acct,
avatar: account_avatar,
mdl: m,
type: "reply"
})
if (model.type !== "follow") {
pageStack.push(Qt.resolvedUrl("../ConversationPage.qml"), {
headerTitle: qsTr("Conversation"),
"status_id": status_id,
"status_url": status_url,
"status_uri": status_uri,
"username": '@'+account_acct,
mdl: m,
type: "reply"
})
} else pageStack.push(Qt.resolvedUrl("../ProfilePage.qml"), {
"display_name": model.account_display_name,
"username": model.account_acct,
"user_id": model.account_id,
"profileImage": model.account_avatar,
"profileBackground": model.account_header,
"note": model.account_note,
"url": model.account_url,
"followers_count": model.account_followers_count,
"following_count": model.account_following_count,
"statuses_count": model.account_statuses_count,
"locked": model.account_locked,
"bot": model.account_bot,
"group": model.account_group
} )
}
onPressAndHold: {
console.log(JSON.stringify(mdl.get(index)))
mnu.show(delegate)
mnu.open(delegate)
}
onDoubleClicked: {
console.log("double click")
}
}

View file

@ -1,3 +1,53 @@
*Sun Jul 12 2020 molan <mol_an@sunrise.ch> 1.0.7-0
- Fix missing / wrong reblog and favourite counts in Retoots (issue #90)
- Added full landscape support
- Added new Pulley Menu options
- Improved Toot context menu
- Improved media page
- Improved loading indicators
- Small changes for some UI-elements
- New Emojis
- New translated strings
*Fri Jun 18 2020 molan <mol_an@sunrise.ch> 1.0.6-3
- Fix broken reblog indication
*Fri Jun 18 2020 molan <mol_an@sunrise.ch> 1.0.6-2
- Fix reported small UI issue
- Updated translations
*Thu Jun 18 2020 molan <mol_an@sunrise.ch> 1.0.6-1
- Fix app crash when open some Profile pages
- Fix sometimes missing favourite / reblog counts
- Fix various QML warnings, replace deprecated Silica items
- Add save to Bookmarks feature
- Add Follows you / Locked / Bot / Group labels to Profile Page header
- Add Bot icon to user display name
- Add clicking on reblog-avatar opens reblog user profile
- Remove Locked icon from user display name
- Further improved Notification Page / general UI
- Code refactoring & other changes under the hood
- Translation updates
*Fri Jun 12 2020 molan <mol_an@sunrise.ch> 1.0.5-1
- [hotfix] fix missing images in mentions on Notification page
*Thu Jun 11 2020 molan <mol_an@sunrise.ch> 1.0.5-0
- fixed: show search results without entering # before term
- fixed: non-clickable user mentions in Toots
- fixed: Copy link to clipboard in Conversations
- Notifications Page: Reworked UI and context menus for notifications
- Profile Page: Open fullscreen profile image
- Profile Page: Show bot label
- Profile Page: New expander for Profile details
- Conversation Page: Possibility to hide and reopen Toot text field
- Conversation Page: Improved display of uploaded images
- Media Page: Adjust size of images to screen width or height
- Media Page: Only automatically restart videos if shorter than 30 seconds
- new Settings Page
- bigger custom emojis in Toots
- overall improvement of UI
*Mon May 25 2020 molan <mol_an@sunrise.ch> 1.0.4-3
- Show user profile background image (if available)
- New Sailfish 3-styled image/video viewer page (WIP)

View file

@ -13,8 +13,8 @@ Name: harbour-tooterb
%{!?qtc_make:%define qtc_make make}
%{?qtc_builddir:%define _builddir %qtc_builddir}
Summary: Tooter β
Version: 1.0.4
Release: 3
Version: 1.0.7
Release: 0
Group: Qt/Qt
License: LICENSE
URL: http://example.org/
@ -25,7 +25,10 @@ BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Qml)
BuildRequires: pkgconfig(Qt5Quick)
BuildRequires: pkgconfig(Qt5DBus)
BuildRequires: pkgconfig(Qt5Multimedia)
BuildRequires: pkgconfig(nemonotifications-qt5)
BuildRequires: pkgconfig(openssl)
BuildRequires: desktop-file-utils
%description

View file

@ -1,7 +1,7 @@
Name: harbour-tooterb
Summary: Tooter β
Version: 1.0.4
Release: 3
Version: 1.0.7
Release: 0
# The contents of the Group field should be one of the groups listed here:
# https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
Group: Qt/Qt
@ -25,12 +25,14 @@ PkgConfigBR:
- Qt5Core
- Qt5Qml
- Qt5Quick
- Qt5DBus
- Qt5Multimedia
- nemonotifications-qt5
- openssl
# Build dependencies without a pkgconfig setup can be listed here
# PkgBR:
# - package-needed-to-build
# PkgBR:
# - qt5-qtmultimedia-plugin-mediaservice-gstmediaplayer
# Runtime dependencies which are not automatically detected
Requires:

View file

@ -24,7 +24,7 @@ class FileDownloader : public QObject
{
Q_OBJECT
public:
explicit FileDownloader(QQmlEngine *engine, QObject *parent = 0);
explicit FileDownloader(QQmlEngine *engine, QObject *parent = nullptr);
Q_INVOKABLE void downloadFile(QUrl url, QString filename);
Q_INVOKABLE void open(QString filename);

View file

@ -8,18 +8,17 @@
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
//static const QUrl IMGUR_UPLOAD_URL("https://httpbin.org/post");
//static const QUrl IMGUR_UPLOAD_URL();
ImageUploader::ImageUploader(QObject *parent) : QObject(parent), m_networkAccessManager(0), m_reply(0) {
ImageUploader::ImageUploader(QObject *parent) : QObject(parent), m_networkAccessManager(nullptr), m_reply(nullptr) {
m_networkAccessManager = new QNetworkAccessManager(this);
}
ImageUploader::~ImageUploader() {
if (m_reply != 0) {
if (m_reply != nullptr) {
m_reply->disconnect();
m_reply->deleteLater();
m_reply = 0;
m_reply = nullptr;
}
}
@ -58,10 +57,10 @@ void ImageUploader::upload() {
return;
}
if (m_reply != 0) {
if (m_reply != nullptr) {
m_reply->disconnect();
m_reply->deleteLater();
m_reply = 0;
m_reply = nullptr;
}
/*QFileInfo fileInfo(QUrl(m_fileName).toLocalFile());
@ -101,12 +100,8 @@ void ImageUploader::upload() {
//imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(fileInfo));
//POST data
QNetworkRequest request(m_uploadUrl);
request.setRawHeader("Authorization", m_authorizationHeader);
m_reply = m_networkAccessManager->post(request, multiPart);
@ -114,8 +109,6 @@ void ImageUploader::upload() {
connect(m_reply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(uploadProgress(qint64,qint64)));
connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
//connect(m_reply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(uploadProgress(qint64,qint64)));
//connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));*/
}
@ -146,6 +139,6 @@ void ImageUploader::replyFinished() {
}
m_reply->deleteLater();
m_reply = 0;
m_reply = nullptr;
postdata.clear();
}

View file

@ -12,7 +12,7 @@ class ImageUploader : public QObject
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
public:
explicit ImageUploader(QObject *parent = 0);
explicit ImageUploader(QObject *parent = nullptr);
~ImageUploader();
Q_INVOKABLE void setFile(const QString &fileName);

View file

@ -17,7 +17,7 @@ class Notifications : public QObject
{
Q_OBJECT
public:
explicit Notifications(QObject *parent = 0);
explicit Notifications(QObject *parent = nullptr);
Q_INVOKABLE void notify(QString appName, QString summary, QString body, bool preview, QString ts, QString issuekey);
};

View file

@ -21,23 +21,22 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tippen um einzufügen</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Link kopieren</translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Inhaltswarnung</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>Was gibt&apos;s Neues?</translation>
</message>
<message>
<source>Public</source>
<translation>Öffentlich</translation>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation>Direktnachricht</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation>Was gibt&apos;s Neues?</translation>
</message>
<message>
<source>Toot sent!</source>
<translation>Toot gesendet!</translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation>Link kopieren</translation>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Antworten</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Antwort verbergen</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Im Browser öffnen</translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation>Ladefehler</translation>
<source>New Toot</source>
<translation>Neuer Toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tippen um einzufügen</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Benachrichtigungen</translation>
</message>
<message>
<source>New Toot</source>
<translation>Neuer Toot</translation>
<source>Local</source>
<translation>Lokal</translation>
</message>
<message>
<source>Federated</source>
<translation>Föderiert</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@Benutzer oder #Ausdruck</translation>
</message>
<message>
<source>Local</source>
<translation>Lokal</translation>
<source>New Toot</source>
<translation>Neuer Toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Föderation</translation>
<source>Error loading</source>
<translation>Ladefehler</translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Lade mehr</translation>
</message>
<message>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
<source>Loading</source>
<translation>Wird geladen</translation>
<source>New Toot</source>
<translation>Neuer Toot</translation>
</message>
<message>
<source>please wait...</source>
<translation>bitte warten...</translation>
<source>Reload</source>
<translation>Neu laden</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Im Browser öffnen</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Nichts gefunden</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Entfolgen</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Folge-Anfrage gesendet!</translation>
<source>Follows you</source>
<translation>Folgt dir</translation>
</message>
<message>
<source>Following</source>
<translation>Folgt</translation>
<source>Group</source>
<translation>Gruppe</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>Mute</source>
<translation>Stummschalten</translation>
</message>
<message>
<source>Unmute</source>
<translation>Nicht stummschalten</translation>
</message>
<message>
<source>Unblock</source>
<translation>Nicht blockieren</translation>
</message>
<message>
<source>Block</source>
<translation>Blockieren</translation>
</message>
<message>
<source>Statuses</source>
<translation>Beiträge</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favoriten</translation>
</message>
<message>
<source>Follow</source>
<translation>Folgen</translation>
</message>
<message>
<source>Summary</source>
<translation>Zusammenfassung</translation>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>Details</translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Folgende</translation>
</message>
<message>
<source>Bio</source>
<translation>Bio</translation>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Folgt</translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation>Profil im Browser öffnen</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Beiträge</translation>
</message>
<message>
<source>Mention</source>
<translation>Erwähnen</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Entfolgen</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Angefragt</translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Folgen</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Nicht stumm</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Stumm schalten</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Zulassen</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Blockieren</translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
<source>Options</source>
<translation>Optionen</translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Bilder in Toots laden</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Diese Option deaktivieren um Datenvolumen zu sparen</translation>
</message>
<message>
<source>Account</source>
<translation>Konto</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Konto entfernen</translation>
@ -243,7 +303,7 @@
<translation>Konto hinzufügen</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Konto entfernen und für diese Anwendung deaktivieren</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Zugriff durch diese Anwendung auf eigenes Mastodon-Konto erlauben</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Diese Option deaktivieren um Datenvolumen zu sparen</translation>
<source>Translate</source>
<translation>Übersetzungen</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Über</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation>Visuelle Identität</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Entwicklung und Übersetzungen</translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation>Französische Übersetzung</translation>
</message>
<message>
<source>Chinese translation</source>
<translation>Chinesische Übersetzung</translation>
</message>
<message>
<source>Dutch translation</source>
<translation>Niederländische Übersetzung</translation>
@ -279,43 +348,13 @@
<translation>Spanische Übersetzung</translation>
</message>
<message>
<source>Added README file</source>
<translation>Erstellung README-Datei</translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Benutze</translation>
</message>
<message>
<source>Chinese translation</source>
<translation>Chinesische Übersetzung</translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Bilder in Toots laden</translation>
</message>
<message>
<source>Translate</source>
<translation>Übersetzungen</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Transifex benutzen um bei den Übersetzungen mitzuhelfen</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Entwicklung und Übersetzungen</translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>hat geteilt</translation>
</message>
<message>
<source>favourited</source>
<translation>hat favorisiert</translation>
</message>
<message>
<source>followed you</source>
<translation>folgt dir</translation>
<source>to help with app translation to your language.</source>
<translation>um bei den Übersetzungen mitzuhelfen.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Favorisieren</translation>
</message>
<message>
<source>Mention</source>
<translation>Erwähnen</translation>
</message>
<message>
<source>Conversation</source>
<translation>Konversation</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Lesezeichen entfernen</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Lesezeichen</translation>
</message>
</context>
</TS>

View file

@ -21,21 +21,20 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Διαγραφή</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emoji</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Κτυπήστε για εισαγωγή</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide Reply</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Νέος</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emoji</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Κτυπήστε για εισαγωγή</translation>
</message>
</context>
<context>
@ -101,7 +116,7 @@
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Επαναφόρτωση</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Ειδοποιήσεις</translation>
</message>
<message>
<source>New Toot</source>
<translation>Νέος</translation>
<source>Local</source>
<translation>Τοπικός</translation>
</message>
<message>
<source>Federated</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search</source>
@ -127,11 +146,14 @@
<translation>@χρήστη ή #όρος</translation>
</message>
<message>
<source>Local</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Νέος</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Φόρτωση περισσοτέρων</translation>
</message>
<message>
<source>Settings</source>
<translation>Ρυθμίσεις</translation>
</message>
<message>
<source>Loading</source>
<translation>Φόρτωση</translation>
<source>New Toot</source>
<translation>Νέος</translation>
</message>
<message>
<source>please wait...</source>
<source>Reload</source>
<translation>Φόρτωση περισσοτέρων</translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Nothing found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Αναίρεση παρακολούθησης</translation>
<source>Bot</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Η αίτηση παρακολούθησης εστάλη!</translation>
<source>Follows you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Group</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Σας ακολουθούν</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Σε παρακολούθηση</translation>
</message>
<message>
<source>Mute</source>
<translation>Σίγαση</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Κατάσταση</translation>
</message>
<message>
<source>Mention</source>
<translation>Φραγή</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Αναίρεση παρακολούθησης</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Παρακολούθηση</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Αναίρεση σίγασης</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Σίγαση</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Αναίρεση φραγής</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Φραγή</translation>
</message>
<message>
<source>Statuses</source>
<translation>Κατάσταση</translation>
</message>
<message>
<source>Favourites</source>
<translation>Σελιδοδείκτες</translation>
</message>
<message>
<source>Follow</source>
<translation>Παρακολούθηση</translation>
</message>
<message>
<source>Summary</source>
<translation>Σύνοψη</translation>
</message>
<message>
<source>Followers</source>
<translation>Σας ακολουθούν</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Ρυθμίσεις</translation>
</message>
<message>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Απενεργοποιήστε αυτήν την επιλογή αν θέλετε να διατηρήσετε την σύνδεση των δεδομένων σας</translation>
</message>
<message>
<source>Account</source>
<translation>λογαριασμού</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Αφαίρεση λογαριασμού</translation>
@ -243,7 +303,7 @@
<translation>Προσθήκη λογαριασμού</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Άρση της αδειοδότησης της εφαρμογής και αφαίρεση του λογαριασμού σας</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Να επιτρέπεται στην εφαρμογή να χρησιμοποιεί τον λογαριασμό σας στο Mastodon εκ μέρους σας</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Απενεργοποιήστε αυτήν την επιλογή αν θέλετε να διατηρήσετε την σύνδεση των δεδομένων σας</translation>
<source>Translate</source>
<translation>Μετάφραση</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Ευχαριστίες</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
@ -279,43 +348,13 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Χρησιμοποιήστε το</translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Translate</source>
<translation>Μετάφραση</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Χρησιμοποιήστε το Transifex για να βοηθήσετε την μετάφραση της εφαρμογής στην γλώσσα σας</translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>προωθημένο</translation>
</message>
<message>
<source>favourited</source>
<translation>στους σελιδοδείκτες</translation>
</message>
<message>
<source>followed you</source>
<translation>σας ακολουθούν</translation>
<source>to help with app translation to your language.</source>
<translation>για να βοηθήσετε την μετάφραση της εφαρμογής στην γλώσσα σας.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Σελιδοδείκτης</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished">Φραγή</translation>
</message>
<message>
<source>Conversation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bookmark</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -21,23 +21,22 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Borrar</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emoticonos</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Toca para insertar</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Copiar enlace al portapapeles</translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Escribe aquí tu advertencia</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>¿En qué estás pensando?</translation>
</message>
<message>
<source>Public</source>
<translation>Público</translation>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation>Directo</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation>¿En qué estás pensando?</translation>
</message>
<message>
<source>Toot sent!</source>
<translation>¡Toot enviado!</translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation>Copiar enlace al portapapeles</translation>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Respuesta</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Cerrar respuesta</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Abrir en el navegador</translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation>Error al cargar</translation>
<source>New Toot</source>
<translation>Nuevo toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emoticonos</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Toca para insertar</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Notificaciones</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nuevo toot</translation>
<source>Local</source>
<translation>Local</translation>
</message>
<message>
<source>Federated</source>
<translation>Federada</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@usuario o #término</translation>
</message>
<message>
<source>Local</source>
<translation>Local</translation>
<source>New Toot</source>
<translation>Nuevo toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Federada</translation>
<source>Error loading</source>
<translation>Error al cargar</translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Cargar más</translation>
</message>
<message>
<source>Settings</source>
<translation>Ajustes</translation>
</message>
<message>
<source>Loading</source>
<translation>Cargando</translation>
<source>New Toot</source>
<translation>Nuevo toot</translation>
</message>
<message>
<source>please wait...</source>
<translation>por favor, espera...</translation>
<source>Reload</source>
<translation>Volver a cargar</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Abrir en el navegador</translation>
</message>
<message>
<source>Nothing found</source>
<translation>No encontrado nada</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Dejar de seguir</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>¡Solicitud de seguidor enviada!</translation>
<source>Follows you</source>
<translation>Te sigue</translation>
</message>
<message>
<source>Group</source>
<translation>Grupo</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>Detalles</translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Seguidores</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Siguiendo</translation>
</message>
<message>
<source>Mute</source>
<translation>Silenciar</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Estados</translation>
</message>
<message>
<source>Mention</source>
<translation>Mencionar</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Dejar de seguir</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Requerido</translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Seguir</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Dejar de silenciar</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Silenciar</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Desbloquear</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Bloquear</translation>
</message>
<message>
<source>Statuses</source>
<translation>Estados</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favoritos</translation>
</message>
<message>
<source>Follow</source>
<translation>Seguir</translation>
</message>
<message>
<source>Summary</source>
<translation>Resumen</translation>
</message>
<message>
<source>Followers</source>
<translation>Seguidores</translation>
</message>
<message>
<source>Bio</source>
<translation>Bio</translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation>Abrir perfil en el navegador</translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Ajustes</translation>
</message>
<message>
<source>Options</source>
<translation>Opciones</translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Cargar imágenes en messages</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Deshabilita esta opción si quieres ahorrar en tu conexión de datos</translation>
</message>
<message>
<source>Account</source>
<translation>Cuenta</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Eliminar cuenta</translation>
@ -243,7 +303,7 @@
<translation>Añadir cuenta</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Retira la autorización a esta aplicación y elimina tu cuenta</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Autoriza a esta aplicación para usar tu cuenta de Mastodon en tu nombre</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Deshabilita esta opción si quieres ahorrar en tu conexión de datos</translation>
<source>Translate</source>
<translation>Traducir</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Créditos</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation>Identidad visual</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Desarrollo y traducciones</translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation>Traducción al occitano y francés</translation>
</message>
<message>
<source>Chinese translation</source>
<translation>Traducción al chino</translation>
</message>
<message>
<source>Dutch translation</source>
<translation>Traducción al holandés</translation>
@ -279,43 +348,13 @@
<translation>Traducción al español</translation>
</message>
<message>
<source>Added README file</source>
<translation>Añadido archivo README</translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Usar</translation>
</message>
<message>
<source>Chinese translation</source>
<translation>Traducción al chino</translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Cargar imágenes en messages</translation>
</message>
<message>
<source>Translate</source>
<translation>Traducir</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Usar Transifex para ayudar con traducciones</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Desarrollo y traducciones</translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>retooteó</translation>
</message>
<message>
<source>favourited</source>
<translation>marcó como favorito</translation>
</message>
<message>
<source>followed you</source>
<translation>te empezó a seguir</translation>
<source>to help with app translation to your language.</source>
<translation>para ayudar con traducciones.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Marcar como favorito</translation>
</message>
<message>
<source>Mention</source>
<translation>Mencionar</translation>
</message>
<message>
<source>Conversation</source>
<translation>Conversación</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Eliminar marcador</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Marcador</translation>
</message>
</context>
</TS>

View file

@ -1,340 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fi">
<context>
<name>API</name>
<message>
<source>favourited</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>followed you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>boosted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>said</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Conversation</name>
<message>
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Emojis</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Tap to insert</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Public</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unlisted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers-only</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageUploader</name>
<message>
<source>The file %1 does not exists</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>LoginPage</name>
<message>
<source>Login</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Instance</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enter a valid Mastodon instance URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainPage</name>
<message>
<source>Home</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notifications</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New Toot</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>@user or #term</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Local</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Federated</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MiniStatus</name>
<message>
<source>boosted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>favourited</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>followed you</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Loading</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>please wait...</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Profile</name>
<message>
<source>Unfollow</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow request sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Following</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mute</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unmute</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unblock</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Block</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Statuses</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Favourites</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Summary</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<message>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add Account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Authorize this app to access your Mastodon account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Credits</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UI/UX design and development</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Spanish translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Translate</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>favourited</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>followed you</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>VisualContainer</name>
<message>
<source>Unboost</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Boost</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unfavorite</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Favorite</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -21,23 +21,22 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Supprimer</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Appuyez pour insérer</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Copier le lien</translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Rédigez votre alerte ici</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>Qu&apos;avez-vous en tête?</translation>
</message>
<message>
<source>Public</source>
<translation>Public</translation>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation>Direct</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation>Qu&apos;avez-vous en tête?</translation>
</message>
<message>
<source>Toot sent!</source>
<translation>Pouet envoyé !</translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation>Copier le lien</translation>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Répondre</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Masquer la réponse</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Ouvrir dans le navigateur</translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Nouveau pouet</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Appuyez pour insérer</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Notifications</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nouveau pouet</translation>
<source>Local</source>
<translation>Fil public local</translation>
</message>
<message>
<source>Federated</source>
<translation>Fil public global</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@personne ou #terme</translation>
</message>
<message>
<source>Local</source>
<translation>Fil public local</translation>
<source>New Toot</source>
<translation>Nouveau pouet</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Fil public global</translation>
<source>Error loading</source>
<translation>Erreur au chargement</translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Charger plus</translation>
</message>
<message>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<source>Loading</source>
<translation>Chargement</translation>
<source>New Toot</source>
<translation>Nouveau pouet</translation>
</message>
<message>
<source>please wait...</source>
<translation>patientez...</translation>
<source>Reload</source>
<translation>Recharger</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Ouvrir dans le navigateur</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Rien trouvé</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Ne plus suivre</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Demande dabonnement envoyée !</translation>
<source>Follows you</source>
<translation>Vous suit</translation>
</message>
<message>
<source>Group</source>
<translation>Groupe</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>Détails</translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Abonné(e)s</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Abonnements</translation>
</message>
<message>
<source>Mute</source>
<translation>Masquer</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Pouets</translation>
</message>
<message>
<source>Mention</source>
<translation>Mentionner</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Ne plus suivre</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Demandé</translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Suivre</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Démasquer</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Masquer</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Débloquer</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Bloquer</translation>
</message>
<message>
<source>Statuses</source>
<translation>Pouets</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favoris</translation>
</message>
<message>
<source>Follow</source>
<translation>Suivre</translation>
</message>
<message>
<source>Summary</source>
<translation>Résumé</translation>
</message>
<message>
<source>Followers</source>
<translation>Abonné(e)s</translation>
</message>
<message>
<source>Bio</source>
<translation>Bio</translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation>Ouvrir dans le navigateur</translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<source>Options</source>
<translation>Options</translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Charger images dans les pouets</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Désactiver cette option pour économiser des données mobiles</translation>
</message>
<message>
<source>Account</source>
<translation>Compte</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Déconnecter votre compte</translation>
@ -243,7 +303,7 @@
<translation>Ajouter compte</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Désautoriser cette application et enlever votre compte</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Autoriser laccès à votre compte pour cette application</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Désactiver cette option pour économiser des données mobiles</translation>
<source>Translate</source>
<translation>Traduire</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Développement</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation>Identité visuelle</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Développement et traductions</translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation>Traduction français</translation>
</message>
<message>
<source>Chinese translation</source>
<translation>Traduction chinoise</translation>
</message>
<message>
<source>Dutch translation</source>
<translation>Traduction néerlandaise</translation>
@ -279,43 +348,13 @@
<translation>Traduction espagnole</translation>
</message>
<message>
<source>Chinese translation</source>
<translation>Traduction chinoise</translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Utiliser</translation>
</message>
<message>
<source>Added README file</source>
<translation>Fichier README ajouté</translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Charger images dans les pouets</translation>
</message>
<message>
<source>Translate</source>
<translation>Traduire</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Utiliser Transifex pour aider à traduire cette application</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Développement et traductions</translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>a partagé</translation>
</message>
<message>
<source>favourited</source>
<translation>a ajouté à ses favoris</translation>
</message>
<message>
<source>followed you</source>
<translation>vous suit</translation>
<source>to help with app translation to your language.</source>
<translation>pour aider à traduire cette application.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Ajouter aux favoris</translation>
</message>
<message>
<source>Mention</source>
<translation>Mentionner</translation>
</message>
<message>
<source>Conversation</source>
<translation>Conversation</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Retirer marque-page</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Ajouter aux marque-pages</translation>
</message>
</context>
</TS>

View file

@ -4,97 +4,94 @@
<context>
<name>API</name>
<message>
<location filename="../qml/lib/API.js" line="158"/>
<source>favourited</source>
<translation>ha apprezzato</translation>
</message>
<message>
<location filename="../qml/lib/API.js" line="169"/>
<source>followed you</source>
<translation>ha iniziato a seguirti</translation>
</message>
<message>
<location filename="../qml/lib/API.js" line="179"/>
<source>boosted</source>
<translation>ha condiviso</translation>
</message>
<message>
<location filename="../qml/lib/API.js" line="189"/>
<location filename="../qml/lib/API.js" line="191"/>
<source>said</source>
<translation>ha detto</translation>
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<location filename="../qml/pages/Conversation.qml" line="108"/>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Copia link</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="200"/>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Contenuto avviso</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="230"/>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>A cosa stai pensando?</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="293"/>
<source>Delete</source>
<translation>Elimina</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="392"/>
<source>Public</source>
<translation>Pubblico</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="395"/>
<source>Unlisted</source>
<translation>Non elencato</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="398"/>
<source>Followers-only</source>
<translation>Solo ai seguaci</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="401"/>
<source>Direct</source>
<translation>Diretto</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="449"/>
<source>Toot sent!</source>
<translation>Toot è stato pubblicato!</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="515"/>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Rispondere</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Chuidere risposta</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Aprire nel browser</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>New Toot</source>
<translation>Nuovo Toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<location filename="../qml/pages/Conversation.qml" line="516"/>
<source>Tap to insert</source>
<translation>Tap per inserire</translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<message>
<location filename="../qml/pages/components/ImageFullScreen.qml" line="298"/>
<source>Error loading</source>
<translation>Errore durante caricamento</translation>
</message>
</context>
<context>
<name>ImageUploader</name>
<message>
<location filename="../src/imageuploader.cpp" line="83"/>
<source>The file %1 does not exists</source>
<translation>Il file %1 non esiste</translation>
</message>
@ -102,27 +99,22 @@
<context>
<name>LoginPage</name>
<message>
<location filename="../qml/pages/LoginPage.qml" line="52"/>
<source>Login</source>
<translation>Accesso</translation>
</message>
<message>
<location filename="../qml/pages/LoginPage.qml" line="56"/>
<source>Instance</source>
<translation>Istanza</translation>
</message>
<message>
<location filename="../qml/pages/LoginPage.qml" line="62"/>
<source>Enter a valid Mastodon instance URL</source>
<translation>Inserire URL di una istanza Mastodon valida</translation>
</message>
<message>
<location filename="../qml/pages/LoginPage.qml" line="119"/>
<source>Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.</source>
<translation>Mastodon è un servizio di rete sociale in software libero, costituito in una federazione d&apos;istanze. Mastodon fa parte del più ampio Fediverso, permettendo ai suoi utenti di interagire anche con utenti su diverse piattaforme aperte che supportano lo stesso protocollo.</translation>
</message>
<message>
<location filename="../qml/pages/LoginPage.qml" line="190"/>
<source>Reload</source>
<translation>Ricarica</translation>
</message>
@ -130,55 +122,52 @@
<context>
<name>MainPage</name>
<message>
<location filename="../qml/pages/MainPage.qml" line="65"/>
<source>Home</source>
<translation>Home</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="74"/>
<source>Notifications</source>
<translation>Notifiche</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="84"/>
<source>Local</source>
<translation>Locale</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="94"/>
<source>Federated</source>
<translation>Federazione</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="121"/>
<source>Search</source>
<translation>Cerca</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="126"/>
<source>@user or #term</source>
<translation>@utente o #termine</translation>
<translation>@utente o #terme</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="251"/>
<source>New Toot</source>
<translation>Nuovo toot</translation>
<translation>Nuovo Toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Error loading</source>
<translation>Errore durante caricamento</translation>
</message>
</context>
<context>
<name>MiniStatus</name>
<message>
<location filename="../qml/pages/components/MiniStatus.qml" line="36"/>
<source>boosted</source>
<translation>ha condiviso</translation>
</message>
<message>
<location filename="../qml/pages/components/MiniStatus.qml" line="39"/>
<source>favourited</source>
<translation>ha apprezzato</translation>
</message>
<message>
<location filename="../qml/pages/components/MiniStatus.qml" line="42"/>
<source>followed you</source>
<translation>ha iniziato a seguirti</translation>
</message>
@ -186,231 +175,221 @@
<context>
<name>MyList</name>
<message>
<location filename="../qml/pages/components/MyList.qml" line="10"/>
<source>Loading</source>
<translation>Caricamento</translation>
</message>
<message>
<location filename="../qml/pages/components/MyList.qml" line="11"/>
<source>please wait...</source>
<translation>Attendere un momento...</translation>
</message>
<message>
<location filename="../qml/pages/components/MyList.qml" line="63"/>
<source>Settings</source>
<translation>Impostazioni</translation>
</message>
<message>
<location filename="../qml/pages/components/MyList.qml" line="70"/>
<source>Load more</source>
<translation>Caricare altri</translation>
<source>New Toot</source>
<translation>Nuovo Toot</translation>
</message>
<message>
<source>Reload</source>
<translation>Ricarica</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Aprire nel browser</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Niente trovato</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<location filename="../qml/pages/Profile.qml" line="171"/>
<source>Summary</source>
<translation>Sintesi</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follows you</source>
<translation>Ti segue</translation>
</message>
<message>
<source>Group</source>
<translation>Gruppo</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>Dettagli</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="177"/>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Seguaci</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="182"/>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Segue</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="187"/>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Toots</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="192"/>
<source>Favourites</source>
<translation>Apprezzati</translation>
<source>Mention</source>
<translation>Menzionare</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="201"/>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Smetti di seguire</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="201"/>
<source>Follow request sent!</source>
<translation>Richiesta di seguito inviata!</translation>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Richiesto</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="201"/>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Segui</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="214"/>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Non silenziare</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="214"/>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Silenzia</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="227"/>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Sblocca</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="227"/>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Blocca</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="246"/>
<source>Bio</source>
<translation>Biografia</translation>
</message>
<message>
<location filename="../qml/pages/Profile.qml" line="290"/>
<source>Open Profile in Browser</source>
<translation>Aprire profile nel browser</translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<location filename="../qml/pages/Settings.qml" line="19"/>
<source>Settings</source>
<translation>Impostazione</translation>
<translation>Impostazioni</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="26"/>
<source>Remove Account</source>
<translation>Rimozione del account</translation>
<source>Options</source>
<translation>Opzioni</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="26"/>
<source>Add Account</source>
<translation>Aggiungi account</translation>
<source>Load Images in Toots</source>
<translation>Caricare immagini nei Toots</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="27"/>
<source>Deauthorize this app and remove your account</source>
<translation>Annullare l&apos;autorizzazione dell&apos;app e rimuovere l&apos;account</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="27"/>
<source>Authorize this app to access your Mastodon account</source>
<translation>Autorizzare l&apos;app all&apos;utilizzo del conto Mastodon</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="59"/>
<source>Load images in toots</source>
<translation>Caricare immagini nei toots</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="60"/>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Disabilitare questa opzione per conservare connessione dati</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="67"/>
<source>Account</source>
<translation>Account</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Rimozione del account</translation>
</message>
<message>
<source>Add Account</source>
<translation>Aggiungi account</translation>
</message>
<message>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Annullare l&apos;autorizzazione dell&apos;app e rimuovere l&apos;account</translation>
</message>
<message>
<source>Authorize this app to access your Mastodon account</source>
<translation>Autorizzare l&apos;app all&apos;utilizzo del conto Mastodon</translation>
</message>
<message>
<source>Translate</source>
<translation>Tradurre</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="68"/>
<source>Use Transifex to help with app translation to your language</source>
<translation>Utilizzare Transifex per aiutare nella traduzione dell&apos;app</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="84"/>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Sviluppo</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="98"/>
<source>UI/UX design and development</source>
<translation>Design UI/UX e sviluppo</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="104"/>
<source>Visual identity</source>
<translation>Identità visiva</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="110"/>
<source>Development and translations</source>
<translation>Sviluppo e traduzioni</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="116"/>
<source>Occitan &amp; French translation</source>
<translation>Traduzione francese e occitanica</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="122"/>
<source>Chinese translation</source>
<translation>Traduzione cinese</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="128"/>
<source>Dutch translation</source>
<translation>Traduzione olandese</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="134"/>
<source>Spanish translation</source>
<translation>Traduzione spagnola</translation>
</message>
<message>
<location filename="../qml/pages/Settings.qml" line="140"/>
<source>Added README file</source>
<translation>Aggiunto file README</translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<location filename="../qml/pages/components/Toot.qml" line="35"/>
<source>boosted</source>
<translation>ha condiviso</translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Utilizzare</translation>
</message>
<message>
<location filename="../qml/pages/components/Toot.qml" line="38"/>
<source>favourited</source>
<translation>ha apprezzato</translation>
</message>
<message>
<location filename="../qml/pages/components/Toot.qml" line="41"/>
<source>followed you</source>
<translation>ha iniziato a seguirti</translation>
<source>to help with app translation to your language.</source>
<translation>per aiutare nella traduzione dell&apos;app.</translation>
</message>
</context>
<context>
<name>VisualContainer</name>
<message>
<location filename="../qml/pages/components/VisualContainer.qml" line="207"/>
<source>Unboost</source>
<translation>Annulla condivisione</translation>
</message>
<message>
<location filename="../qml/pages/components/VisualContainer.qml" line="207"/>
<source>Boost</source>
<translation>Condividi</translation>
</message>
<message>
<location filename="../qml/pages/components/VisualContainer.qml" line="244"/>
<source>Unfavorite</source>
<translation>Annulla apprezzamento</translation>
</message>
<message>
<location filename="../qml/pages/components/VisualContainer.qml" line="244"/>
<source>Favorite</source>
<translation>Apprezzato</translation>
</message>
<message>
<source>Mention</source>
<translation>Menzionare</translation>
</message>
<message>
<source>Conversation</source>
<translation>Conversazione</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Elimina segnalibro</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Aggiungi segnalibro</translation>
</message>
</context>
</TS>

View file

@ -21,11 +21,65 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Verwijderen</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Linkadres kopiëren</translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Waarschuwingstekst</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>Wat wil je kwijt?</translation>
</message>
<message>
<source>Public</source>
<translation>Openbaar</translation>
</message>
<message>
<source>Unlisted</source>
<translation>Minder openbaar</translation>
</message>
<message>
<source>Followers-only</source>
<translation>Alleen volgers</translation>
</message>
<message>
<source>Direct</source>
<translation>Direct</translation>
</message>
<message>
<source>Toot sent!</source>
<translation>Toot verzonden!</translation>
</message>
<message>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Antwoord</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Antwoord verbergen</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Open een Browser</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>New Toot</source>
<translation>Nieuwe Toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
@ -34,45 +88,6 @@
<source>Tap to insert</source>
<translation>Tikken om in te voegen</translation>
</message>
<message>
<source>Write your warning here</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Public</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unlisted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers-only</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageUploader</name>
@ -93,7 +108,7 @@
</message>
<message>
<source>Enter a valid Mastodon instance URL</source>
<translation type="unfinished"></translation>
<translation>Geldig Mastodon URL</translation>
</message>
<message>
<source>Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.</source>
@ -115,8 +130,12 @@
<translation>Meldingen</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nieuwe Toot</translation>
<source>Local</source>
<translation>Lokaal</translation>
</message>
<message>
<source>Federated</source>
<translation>Gefedereerd</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@user of #term</translation>
</message>
<message>
<source>Local</source>
<translation>Lokaal</translation>
<source>New Toot</source>
<translation>Nieuwe Toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Gefedereerd</translation>
<source>Error loading</source>
<translation>Laadfout</translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Meer laden</translation>
</message>
<message>
<source>Settings</source>
<translation>Instellingen</translation>
</message>
<message>
<source>Loading</source>
<translation>Laden</translation>
<source>New Toot</source>
<translation>Nieuwe Toot</translation>
</message>
<message>
<source>please wait...</source>
<translation>even geduld</translation>
<source>Reload</source>
<translation>Herladen</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Open een Browser</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Niets gevonden</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Ontvolgen</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Volgverzoek verstuurd!</translation>
<source>Follows you</source>
<translation>Volgt jou</translation>
</message>
<message>
<source>Group</source>
<translation>Groep</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>Gegevens</translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Volgers</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Volgend</translation>
</message>
<message>
<source>Mute</source>
<translation>Dempen</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Statussen</translation>
</message>
<message>
<source>Mention</source>
<translation>Vermelden</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Ontvolgen</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Gevraagd</translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Volgen</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Ontdempen</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Dempen</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Deblokkeren</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Blokkeren</translation>
</message>
<message>
<source>Statuses</source>
<translation>Statussen</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favorieten</translation>
</message>
<message>
<source>Follow</source>
<translation>Volgen</translation>
</message>
<message>
<source>Summary</source>
<translation>Samenvatting</translation>
</message>
<message>
<source>Followers</source>
<translation>Volgers</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Instellingen</translation>
</message>
<message>
<source>Options</source>
<translation>Opties</translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Laden afbeeldingen in toots</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Schakel deze optie uit als je je dataverbinding wilt behouden</translation>
</message>
<message>
<source>Account</source>
<translation>Account</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Verwijderen account</translation>
@ -243,7 +303,7 @@
<translation>Toevoegen account</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Trek autorisaties van deze app in en verwijder je account</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Autoriseer deze app om je Mastodon namens jou te gebruiken</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Schakel deze optie uit als je je dataverbinding wilt behouden</translation>
<source>Translate</source>
<translation>Vertalen</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Credits</translation>
</message>
<message>
@ -264,58 +325,36 @@
</message>
<message>
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Spanish translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Laden afbeeldingen in toots</translation>
</message>
<message>
<source>Translate</source>
<translation>Vertalen</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Gebruik Transifex om deze app te helpen vertalen in jouw taal</translation>
<translation>Visuele identiteit</translation>
</message>
<message>
<source>Development and translations</source>
<translation>Ontwikkeling en vertalingen</translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>boostte</translation>
<source>Occitan &amp; French translation</source>
<translation>Occitaanse &amp; Franse vertaling</translation>
</message>
<message>
<source>favourited</source>
<translation>maakte favoriet</translation>
<source>Chinese translation</source>
<translation>Chinese vertaling</translation>
</message>
<message>
<source>followed you</source>
<translation>volgde jou</translation>
<source>Dutch translation</source>
<translation>Nederlandse vertaling</translation>
</message>
<message>
<source>Spanish translation</source>
<translation>Spaanse vertaling</translation>
</message>
<message>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Gebruik</translation>
</message>
<message>
<source>to help with app translation to your language.</source>
<translation>om deze app te helpen vertalen in jouw taal.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Markeren als favoriet</translation>
</message>
<message>
<source>Mention</source>
<translation>Vermelden</translation>
</message>
<message>
<source>Conversation</source>
<translation>Conversatie</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Bookmarken</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Bladwijzer verwijderen</translation>
</message>
</context>
</TS>

View file

@ -21,21 +21,20 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Verwijderen</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tikt voor in te voegen</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide Reply</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Nieuwen toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tikt voor in te voegen</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Meldingen</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nieuwen toot</translation>
<source>Local</source>
<translation>Lokaal</translation>
</message>
<message>
<source>Federated</source>
<translation>Gefedereerd</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@gebruiker of #term</translation>
</message>
<message>
<source>Local</source>
<translation>Lokaal</translation>
<source>New Toot</source>
<translation>Nieuwen toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Gefedereerd</translation>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Meer laden</translation>
</message>
<message>
<source>Settings</source>
<translation>Instellingen</translation>
</message>
<message>
<source>Loading</source>
<translation>Laden</translation>
<source>New Toot</source>
<translation>Nieuwen toot</translation>
</message>
<message>
<source>please wait...</source>
<translation>efkens geduld</translation>
<source>Reload</source>
<translation>Herladen</translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Nothing found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Ontvolgen</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Volgverzoek verzonden!</translation>
<source>Follows you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Group</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Volgers</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Volgend</translation>
</message>
<message>
<source>Mute</source>
<translation>Dempen</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Statussen</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Ontvolgen</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Volgen</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Ontdempen</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Dempen</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Deblokkeren</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Blokkeren</translation>
</message>
<message>
<source>Statuses</source>
<translation>Statussen</translation>
</message>
<message>
<source>Favourites</source>
<translation>Duimen</translation>
</message>
<message>
<source>Follow</source>
<translation>Volgen</translation>
</message>
<message>
<source>Summary</source>
<translation>Samenvatting</translation>
</message>
<message>
<source>Followers</source>
<translation>Volgers</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Instellingen</translation>
</message>
<message>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Afbeeldingen in toots laden</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Schakelt dees optie uit als ge uw verbinding wilt behouden</translation>
</message>
<message>
<source>Account</source>
<translation>Account</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Account verwijderen</translation>
@ -243,7 +303,7 @@
<translation>Account toevoegen</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Trekt autorisaties van dezen app in en verwijdert uwen account</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Autoriseert dezen app voor uwe Mastodon-account namens u te gebruiken</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Schakelt dees optie uit als ge uw verbinding wilt behouden</translation>
<source>Translate</source>
<translation>Vertalen</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Credits</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
@ -279,43 +348,13 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Gebruikt</translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Afbeeldingen in toots laden</translation>
</message>
<message>
<source>Translate</source>
<translation>Vertalen</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Gebruikt Transifex voor te helpen met dezen app in uw taal te vertalen</translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>heeft geboost</translation>
</message>
<message>
<source>favourited</source>
<translation>heeft geduimd voor</translation>
</message>
<message>
<source>followed you</source>
<translation>volgt u nu</translation>
<source>to help with app translation to your language.</source>
<translation>voor te helpen met dezen app in uw taal te vertalen.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Duim toevoegen</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Conversation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bookmark</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -21,21 +21,20 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Escafar</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tustejar per inserir</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide Reply</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Nòu Tut</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tustejar per inserir</translation>
</message>
</context>
<context>
@ -108,31 +123,38 @@
<name>MainPage</name>
<message>
<source>Home</source>
<translation>Acuèlh</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notifications</source>
<translation>Notificacions</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nòu Tut</translation>
</message>
<message>
<source>Search</source>
<translation>Cercar</translation>
</message>
<message>
<source>@user or #term</source>
<translation>@utilizaire o #tèrm</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Local</source>
<translation>Local</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Federated</source>
<translation>Federat</translation>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>@user or #term</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New Toot</source>
<translation type="unfinished">Nòu Tut</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Cargar mai</translation>
</message>
<message>
<source>Settings</source>
<translation>Parmètres</translation>
</message>
<message>
<source>Loading</source>
<translation>Cargament</translation>
<source>New Toot</source>
<translation>Nòu Tut</translation>
</message>
<message>
<source>please wait...</source>
<translation>esperatz....</translation>
<source>Reload</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Nothing found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Quitar de seguir</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Demanda de seguir enviada !</translation>
<source>Follows you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Group</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Seguidors</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Abonaments</translation>
</message>
<message>
<source>Mute</source>
<translation>Amagar</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Estatuts</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Quitar de seguir</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Seguir</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Mostrar</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Amagar</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Desblocar</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Blocar</translation>
</message>
<message>
<source>Statuses</source>
<translation>Estatuts</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favorits</translation>
</message>
<message>
<source>Follow</source>
<translation>Seguir</translation>
</message>
<message>
<source>Summary</source>
<translation>Resumit</translation>
</message>
<message>
<source>Followers</source>
<translation>Seguidors</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Parmètres</translation>
</message>
<message>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Cargar los imatges dels tuts</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Desactivar aquesta opcion per estalviar vòstra connexion de donadas</translation>
</message>
<message>
<source>Account</source>
<translation>Compte</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Levar un compte</translation>
@ -243,7 +303,7 @@
<translation>Ajustar un compte</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Revocar laplicacion e levar vòstre compte</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Autorizar aquesta aplicacion a utilizar vòstre compte Mastodon per vos</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Desactivar aquesta opcion per estalviar vòstra connexion de donadas</translation>
<source>Translate</source>
<translation>Traduire</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Crèdits</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
@ -279,43 +348,13 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Utilizar</translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Cargar los imatges dels tuts</translation>
</message>
<message>
<source>Translate</source>
<translation>Traduire</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Utilizar Transifex per ajudar a traduire laplicacion dins vòstra lenga</translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>a tornat partejar</translation>
</message>
<message>
<source>favourited</source>
<translation>a mes en favorit</translation>
</message>
<message>
<source>followed you</source>
<translation>vos sèc</translation>
<source>to help with app translation to your language.</source>
<translation>per ajudar a traduire laplicacion dins vòstra lenga.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Ajustar als favorits</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Conversation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bookmark</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -5,7 +5,7 @@
<name>API</name>
<message>
<source>favourited</source>
<translation type="unfinished">dodał(a) do ulubionych</translation>
<translation>dodał(a) do ulubionych</translation>
</message>
<message>
<source>followed you</source>
@ -21,21 +21,20 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Usuń</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emoji</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Dotknij aby wstawić</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide Reply</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished">Otwarte w przeglądarce</translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Nowy wpis</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emoji</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Dotknij aby wstawić</translation>
</message>
</context>
<context>
@ -85,7 +100,7 @@
<name>LoginPage</name>
<message>
<source>Login</source>
<translation type="unfinished"></translation>
<translation>Login</translation>
</message>
<message>
<source>Instance</source>
@ -101,7 +116,7 @@
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Załaduj ponownie</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Powiadomienia</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nowy wpis</translation>
<source>Local</source>
<translation>Lokalne</translation>
</message>
<message>
<source>Federated</source>
<translation>Globalne</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@użytkownik lub #tag</translation>
</message>
<message>
<source>Local</source>
<translation>Lokalne</translation>
<source>New Toot</source>
<translation>Nowy wpis</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Globalne</translation>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -153,86 +175,124 @@
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Załaduj więcej</translation>
<source>Settings</source>
<translation>Ustawienia</translation>
</message>
<message>
<source>New Toot</source>
<translation>Nowy wpis</translation>
</message>
<message>
<source>Reload</source>
<translation>Załaduj ponownie</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Otwarte w przeglądarce</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Nic nie znaleziono</translation>
</message>
</context>
<context>
<name>ProfileHeader</name>
<message>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follows you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Group</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Śledzisz</translation>
</message>
<message>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Przestań śledzić</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Wycisz</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Ustawienia</translation>
</message>
<message>
<source>Loading</source>
<translation>Ładowanie</translation>
</message>
<message>
<source>please wait...</source>
<translation>proszę czekać</translation>
</message>
</context>
<context>
<name>Profile</name>
<message>
<source>Unfollow</source>
<translation>Przestań śledzić</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Wysłano prośbę o możliwość śledzenia!</translation>
</message>
<message>
<source>Following</source>
<translation>Śledzisz</translation>
</message>
<message>
<source>Mute</source>
<translation>Wycisz</translation>
</message>
<message>
<source>Unmute</source>
<translation>Unmute</translation>
</message>
<message>
<source>Unblock</source>
<translation>Unblock</translation>
</message>
<message>
<source>Block</source>
<translation>Block</translation>
</message>
<message>
<source>Statuses</source>
<translation>Statuses</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favourites</translation>
</message>
<message>
<source>Follow</source>
<translation>Follow</translation>
</message>
<message>
<source>Summary</source>
<translation>Summary</translation>
</message>
<message>
<source>Followers</source>
<translation>Followers</translation>
</message>
<message>
<source>Bio</source>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<source>Load Images in Toots</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<message>
<source>Settings</source>
<translation type="unfinished">Ustawienia</translation>
<source>Disable this option if you want to preserve your data connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Account</source>
@ -243,7 +303,7 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<source>Translate</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
@ -279,44 +348,14 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<source>to help with app translation to your language.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Translate</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>podbił(a)</translation>
</message>
<message>
<source>favourited</source>
<translation>dodał(a) do ulubionych</translation>
</message>
<message>
<source>followed you</source>
<translation>zaczął(-ęła Cię śledzić)</translation>
</message>
</context>
<context>
<name>VisualContainer</name>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Conversation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bookmark</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -21,11 +21,65 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Удалить</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Копировать ссылку</translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Текст предупреждения</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>О чём думаете?</translation>
</message>
<message>
<source>Public</source>
<translation>Публичный</translation>
</message>
<message>
<source>Unlisted</source>
<translation>Скрытый</translation>
</message>
<message>
<source>Followers-only</source>
<translation>Приватный</translation>
</message>
<message>
<source>Direct</source>
<translation>Адресованный</translation>
</message>
<message>
<source>Toot sent!</source>
<translation>Поста отправлено!</translation>
</message>
<message>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Ответ</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Скрыть ответ</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Открыть в браузере</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>New Toot</source>
<translation>Новый</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>айликов</translation>
@ -34,45 +88,6 @@
<source>Tap to insert</source>
<translation>Нажмите, чтобы вставить</translation>
</message>
<message>
<source>Write your warning here</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Public</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unlisted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers-only</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageUploader</name>
@ -85,11 +100,11 @@
<name>LoginPage</name>
<message>
<source>Login</source>
<translation type="unfinished"></translation>
<translation>Авторизоваться</translation>
</message>
<message>
<source>Instance</source>
<translation type="unfinished"></translation>
<translation>Экземпляра</translation>
</message>
<message>
<source>Enter a valid Mastodon instance URL</source>
@ -101,7 +116,7 @@
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation>Перезарядка</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Уведомления</translation>
</message>
<message>
<source>New Toot</source>
<translation>Новый</translation>
<source>Local</source>
<translation>Локальны</translation>
</message>
<message>
<source>Federated</source>
<translation>Федеративные</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@пользователь или #срок</translation>
</message>
<message>
<source>Local</source>
<translation>Локальный</translation>
<source>New Toot</source>
<translation>Новый</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Федеративные</translation>
<source>Error loading</source>
<translation>Ошибка при загрузке</translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Загрузи больше</translation>
</message>
<message>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<source>Loading</source>
<translation>Загрузка</translation>
<source>New Toot</source>
<translation>Новый</translation>
</message>
<message>
<source>please wait...</source>
<translation>Пожалуйста, подождите...</translation>
<source>Reload</source>
<translation>Перезагрузить</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Открыть в браузере</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Ничего не найдено</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Отписаться</translation>
<source>Bot</source>
<translation>бот</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Следуйте запрошенному запросу!</translation>
<source>Follows you</source>
<translation>Подписан(а) на вас</translation>
</message>
<message>
<source>Group</source>
<translation>Группа</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>Подробности</translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Читают</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Следующий</translation>
</message>
<message>
<source>Mute</source>
<translation>Безгласный</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Статусы</translation>
</message>
<message>
<source>Mention</source>
<translation>Упоминание</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Отписаться</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Запрошенный</translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Следить</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Нет безгласный</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Безгласный</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Открыть</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Блокировать</translation>
</message>
<message>
<source>Statuses</source>
<translation>Статусы</translation>
</message>
<message>
<source>Favourites</source>
<translation>Избранные</translation>
</message>
<message>
<source>Follow</source>
<translation>Следить</translation>
</message>
<message>
<source>Summary</source>
<translation>Резюме</translation>
</message>
<message>
<source>Followers</source>
<translation>Читают</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<source>Options</source>
<translation>Параметры</translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Загружать изображения</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Отключите эту опцию, если вы хотите сохранить подключение к данным</translation>
</message>
<message>
<source>Account</source>
<translation>Aккаунт</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Удалить учетную запись</translation>
@ -243,7 +303,7 @@
<translation>Добавить аккаунт</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>удалить учетную запись с устройства</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Уполномочить это приложение использовать свою учетную запись Mastodon от вашего имени</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Отключите эту опцию, если вы хотите сохранить подключение к данным</translation>
<source>Translate</source>
<translation>Переведите</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Зачет</translation>
</message>
<message>
@ -264,58 +325,36 @@
</message>
<message>
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Spanish translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Загружать изображения</translation>
</message>
<message>
<source>Translate</source>
<translation>Переведите</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Используйте Transifex, чтобы помочь с переводом приложения на ваш язык</translation>
<translation>Визуальная идентичность</translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>росту</translation>
<translation>Разработка и переводы</translation>
</message>
<message>
<source>favourited</source>
<translation>имеет любимый</translation>
<source>Occitan &amp; French translation</source>
<translation>французский перевод</translation>
</message>
<message>
<source>followed you</source>
<translation>следую за тобой</translation>
<source>Chinese translation</source>
<translation>Китайский перевод</translation>
</message>
<message>
<source>Dutch translation</source>
<translation>Голландский перевод</translation>
</message>
<message>
<source>Spanish translation</source>
<translation>Испанский перевод</translation>
</message>
<message>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Используйте</translation>
</message>
<message>
<source>to help with app translation to your language.</source>
<translation>чтобы помочь с переводом приложения на ваш язык.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Избранные</translation>
</message>
<message>
<source>Mention</source>
<translation>Упоминание</translation>
</message>
<message>
<source>Conversation</source>
<translation>беседа</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Убрать из закладок</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Добавить в закладки</translation>
</message>
</context>
</TS>

View file

@ -21,21 +21,20 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Обриши</translation>
</message>
<message>
<source>Emojis</source>
<translation>Емотикони</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Тапни за убацивање</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide Reply</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Novi toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Емотикони</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Тапни за убацивање</translation>
</message>
</context>
<context>
@ -101,7 +116,7 @@
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation type="unfinished">учитај још</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Обавјештење</translation>
</message>
<message>
<source>New Toot</source>
<translation>Novi toot</translation>
<source>Local</source>
<translation>Локална</translation>
</message>
<message>
<source>Federated</source>
<translation>Федеративна</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@korisnik ili #pojam</translation>
</message>
<message>
<source>Local</source>
<translation>Локална</translation>
<source>New Toot</source>
<translation>Novi toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Федеративна</translation>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>учитај још</translation>
</message>
<message>
<source>Settings</source>
<translation>Подешавања</translation>
</message>
<message>
<source>Loading</source>
<translation>Učitavanje</translation>
<source>New Toot</source>
<translation>Novi toot</translation>
</message>
<message>
<source>please wait...</source>
<translation>молимо вас, сачекајте...</translation>
<source>Reload</source>
<translation>учитај још</translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Nothing found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Одпрати</translation>
<source>Bot</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Захтјев за праћењем поднесен!</translation>
<source>Follows you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Group</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Пратиоци</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Пратите</translation>
</message>
<message>
<source>Mute</source>
<translation>Утишај</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Статуси</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Одпрати</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Прати</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Укини утишање</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Утишај</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Одблокирати</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Блокирати</translation>
</message>
<message>
<source>Statuses</source>
<translation>Статуси</translation>
</message>
<message>
<source>Favourites</source>
<translation>Омиљени</translation>
</message>
<message>
<source>Follow</source>
<translation>Прати</translation>
</message>
<message>
<source>Summary</source>
<translation>Детаљи</translation>
</message>
<message>
<source>Followers</source>
<translation>Пратиоци</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Подешавања</translation>
</message>
<message>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Прикажи слике у објавама</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Искључите ову опцију уколико желите да уштедите на преносу података</translation>
</message>
<message>
<source>Account</source>
<translation>Hалог</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Уклони налог</translation>
@ -243,7 +303,7 @@
<translation>Додај налог</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Укините дозволе за кориштење и уклоните налог с телефона</translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>Дозволите овој апликацији да користи ваш Mastodon налог</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Искључите ову опцију уколико желите да уштедите на преносу података</translation>
<source>Translate</source>
<translation>Преведи</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Спомен плоча</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
@ -279,43 +348,13 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Користите</translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Прикажи слике у објавама</translation>
</message>
<message>
<source>Translate</source>
<translation>Преведи</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>Користите Transifex и помозите у преводу апликације на други језик</translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>разглашено</translation>
</message>
<message>
<source>favourited</source>
<translation>омиљено</translation>
</message>
<message>
<source>followed you</source>
<translation>вас прати</translation>
<source>to help with app translation to your language.</source>
<translation>и помозите у преводу апликације на други језик.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Conversation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bookmark</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -21,21 +21,20 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Radera</translation>
</message>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tryck för att infoga</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide Reply</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation>Ny toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tryck för att infoga</translation>
</message>
</context>
<context>
@ -101,7 +116,7 @@
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Ladda mer</translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation>Notifieringar</translation>
</message>
<message>
<source>New Toot</source>
<translation>Ny toot</translation>
<source>Local</source>
<translation>Lokalt</translation>
</message>
<message>
<source>Federated</source>
<translation>Förenade</translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@user eller #term</translation>
</message>
<message>
<source>Local</source>
<translation>Lokalt</translation>
<source>New Toot</source>
<translation>Ny toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation>Förenade</translation>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Ladda mer</translation>
</message>
<message>
<source>Settings</source>
<translation>Inställningar</translation>
</message>
<message>
<source>Loading</source>
<translation>Laddar</translation>
<source>New Toot</source>
<translation>Ny toot</translation>
</message>
<message>
<source>please wait...</source>
<translation>Vänligen vänta...</translation>
<source>Reload</source>
<translation>Ladda mer</translation>
</message>
<message>
<source>Open in Browser</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Nothing found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation>Sluta följa</translation>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Följarförfrågan har skickats!</translation>
<source>Follows you</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Group</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Följare</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Följer</translation>
</message>
<message>
<source>Mute</source>
<translation>Tysta</translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Statusar</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Sluta följa</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Följ</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Avtysta</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Tysta</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Avblockera</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Blockera</translation>
</message>
<message>
<source>Statuses</source>
<translation>Statusar</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favoriter</translation>
</message>
<message>
<source>Follow</source>
<translation>Följ</translation>
</message>
<message>
<source>Summary</source>
<translation>Översikt</translation>
</message>
<message>
<source>Followers</source>
<translation>Följare</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Inställningar</translation>
</message>
<message>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation>Ladda bilder i toots</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Inaktivera det här alternativet om du vill behålla din dataanslutning</translation>
</message>
<message>
<source>Account</source>
<translation>Konto</translation>
</message>
<message>
<source>Remove Account</source>
<translation>Radera konto</translation>
@ -243,19 +303,20 @@
<translation>Lägg till konto</translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<translation>Avauktorisera denna app och radera ditt konto</translation>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Avauktorisera denna app och radera ditt konto</translation>
</message>
<message>
<source>Authorize this app to access your Mastodon account</source>
<translation>Godkänn denna app att använda ditt Mastodon-konto dina vägnar</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation>Inaktivera det här alternativet om du vill behålla din dataanslutning</translation>
<source>Translate</source>
<translation>Översätt</translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Erkännanden</translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
@ -279,43 +348,13 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Använd</translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation>Ladda bilder i toots</translation>
</message>
<message>
<source>Translate</source>
<translation>Översätt</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Development and translations</source>
<translation>Använd Transifex för att hjälpa med app-översättningar till ditt språk</translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>puffade</translation>
</message>
<message>
<source>favourited</source>
<translation>favoriserad</translation>
</message>
<message>
<source>followed you</source>
<translation>följer dig</translation>
<source>to help with app translation to your language.</source>
<translation>för att hjälpa med app-översättningar till ditt språk.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation>Favorisera</translation>
</message>
<message>
<source>Mention</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Conversation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Bookmark</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -21,23 +21,22 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation></translation>
</message>
<message>
<source>Emojis</source>
<translation></translation>
</message>
<message>
<source>Tap to insert</source>
<translation></translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation></translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>?</translation>
</message>
<message>
<source>Public</source>
<translation></translation>
@ -54,24 +53,40 @@
<source>Direct</source>
<translation></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation>?</translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation></translation>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation></translation>
</message>
<message>
<source>Hide Reply</source>
<translation></translation>
</message>
<message>
<source>Open in Browser</source>
<translation></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<name>CoverPage</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
<source>New Toot</source>
<translation></translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation></translation>
</message>
<message>
<source>Tap to insert</source>
<translation></translation>
</message>
</context>
<context>
@ -115,8 +130,12 @@
<translation></translation>
</message>
<message>
<source>New Toot</source>
<translation></translation>
<source>Local</source>
<translation></translation>
</message>
<message>
<source>Federated</source>
<translation></translation>
</message>
<message>
<source>Search</source>
@ -127,12 +146,15 @@
<translation>@用户或#</translation>
</message>
<message>
<source>Local</source>
<translation></translation>
<source>New Toot</source>
<translation></translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Federated</source>
<translation></translation>
<source>Error loading</source>
<translation></translation>
</message>
</context>
<context>
@ -152,88 +174,126 @@
</context>
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation></translation>
</message>
<message>
<source>Settings</source>
<translation></translation>
</message>
<message>
<source>Loading</source>
<translation></translation>
<source>New Toot</source>
<translation></translation>
</message>
<message>
<source>please wait...</source>
<translation>......</translation>
<source>Reload</source>
<translation></translation>
</message>
<message>
<source>Open in Browser</source>
<translation></translation>
</message>
<message>
<source>Nothing found</source>
<translation>西</translation>
</message>
</context>
<context>
<name>Profile</name>
<name>ProfileHeader</name>
<message>
<source>Unfollow</source>
<translation></translation>
<source>Bot</source>
<translation></translation>
</message>
<message>
<source>Follow request sent!</source>
<translation></translation>
<source>Follows you</source>
<translation></translation>
</message>
<message>
<source>Group</source>
<translation></translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation></translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation></translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation></translation>
</message>
<message>
<source>Mute</source>
<translation></translation>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation></translation>
</message>
<message>
<source>Mention</source>
<translation></translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation></translation>
</message>
<message>
<source>Statuses</source>
<translation></translation>
</message>
<message>
<source>Favourites</source>
<translation></translation>
</message>
<message>
<source>Follow</source>
<translation></translation>
</message>
<message>
<source>Summary</source>
<translation></translation>
</message>
<message>
<source>Followers</source>
<translation></translation>
</message>
<message>
<source>Bio</source>
<translation></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation></translation>
</message>
</context>
<context>
<name>Settings</name>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation></translation>
</message>
<message>
<source>Options</source>
<translation></translation>
</message>
<message>
<source>Load Images in Toots</source>
<translation></translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation></translation>
</message>
<message>
<source>Account</source>
<translation></translation>
</message>
<message>
<source>Remove Account</source>
<translation></translation>
@ -243,7 +303,7 @@
<translation></translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation></translation>
</message>
<message>
@ -251,11 +311,12 @@
<translation>使 Mastodon </translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation></translation>
<source>Translate</source>
<translation></translation>
</message>
<message>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation></translation>
</message>
<message>
@ -266,10 +327,18 @@
<source>Visual identity</source>
<translation></translation>
</message>
<message>
<source>Development and translations</source>
<translation></translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation>西</translation>
</message>
<message>
<source>Chinese translation</source>
<translation></translation>
</message>
<message>
<source>Dutch translation</source>
<translation></translation>
@ -279,43 +348,13 @@
<translation>西</translation>
</message>
<message>
<source>Added README file</source>
<translation> README </translation>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>使</translation>
</message>
<message>
<source>Chinese translation</source>
<translation></translation>
</message>
<message>
<source>Load images in toots</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Translate</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation>使 Transifex </translation>
</message>
<message>
<source>Development and translations</source>
<translation></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation></translation>
</message>
<message>
<source>favourited</source>
<translation></translation>
</message>
<message>
<source>followed you</source>
<translation></translation>
<source>to help with app translation to your language.</source>
<translation>使.</translation>
</message>
</context>
<context>
@ -336,5 +375,21 @@
<source>Favorite</source>
<translation></translation>
</message>
<message>
<source>Mention</source>
<translation></translation>
</message>
<message>
<source>Conversation</source>
<translation></translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation></translation>
</message>
<message>
<source>Bookmark</source>
<translation></translation>
</message>
</context>
</TS>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<TS version="2.1" language="en">
<context>
<name>API</name>
<message>
@ -21,11 +21,65 @@
</message>
</context>
<context>
<name>Conversation</name>
<name>ConversationPage</name>
<message>
<source>Delete</source>
<translation>Delete</translation>
<source>Copy Link to Clipboard</source>
<extracomment>Use the translation of &quot;Copy Link&quot; for a shorter PullDownMenu label</extracomment>
<translation>Copy Link to Clipboard</translation>
</message>
<message>
<source>Write your warning here</source>
<extracomment>placeholderText in Toot content warning panel</extracomment>
<translation>Write your warning here</translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<extracomment>placeholderText in Toot text panel</extracomment>
<translation>What&apos;s on your mind?</translation>
</message>
<message>
<source>Public</source>
<translation>Public</translation>
</message>
<message>
<source>Unlisted</source>
<translation>Unlisted</translation>
</message>
<message>
<source>Followers-only</source>
<translation>Followers-only</translation>
</message>
<message>
<source>Direct</source>
<translation>Direct</translation>
</message>
<message>
<source>Toot sent!</source>
<translation>Toot sent!</translation>
</message>
<message>
<source>Reply</source>
<extracomment>&quot;Reply&quot; will show the Toot text entry Panel. &quot;Hide Reply&quot; closes it. Alternative: Use &quot;Close Reply&quot;</extracomment>
<translation>Reply</translation>
</message>
<message>
<source>Hide Reply</source>
<translation>Hide Reply</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Open in Browser</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>New Toot</source>
<translation>New Toot</translation>
</message>
</context>
<context>
<name>EmojiSelect</name>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
@ -34,45 +88,6 @@
<source>Tap to insert</source>
<translation>Tap to insert</translation>
</message>
<message>
<source>Write your warning here</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Public</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unlisted</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Followers-only</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Direct</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toot sent!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy Link to Clipboard</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageFullScreen</name>
<message>
<source>Error loading</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ImageUploader</name>
@ -85,54 +100,61 @@
<name>LoginPage</name>
<message>
<source>Login</source>
<translation type="unfinished"></translation>
<translation>Login</translation>
</message>
<message>
<source>Instance</source>
<translation type="unfinished"></translation>
<translation>Instance</translation>
</message>
<message>
<source>Enter a valid Mastodon instance URL</source>
<translation type="unfinished"></translation>
<translation>Enter a valid Mastodon instance URL</translation>
</message>
<message>
<source>Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.</source>
<translation type="unfinished"></translation>
<translation>Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly.</translation>
</message>
<message>
<source>Reload</source>
<translation type="unfinished"></translation>
<translation>Reload</translation>
</message>
</context>
<context>
<name>MainPage</name>
<message>
<source>Home</source>
<translation></translation>
<translation>Home</translation>
</message>
<message>
<source>Notifications</source>
<translation></translation>
</message>
<message>
<source>New Toot</source>
<translation></translation>
</message>
<message>
<source>Search</source>
<translation></translation>
</message>
<message>
<source>@user or #term</source>
<translation></translation>
<translation>Notifications</translation>
</message>
<message>
<source>Local</source>
<translation></translation>
<translation>Local</translation>
</message>
<message>
<source>Federated</source>
<translation></translation>
<translation>Federated</translation>
</message>
<message>
<source>Search</source>
<translation>Search</translation>
</message>
<message>
<source>@user or #term</source>
<translation>@user or #term</translation>
</message>
<message>
<source>New Toot</source>
<translation>New Toot</translation>
</message>
</context>
<context>
<name>MediaFullScreen</name>
<message>
<source>Error loading</source>
<translation>Error loading</translation>
</message>
</context>
<context>
@ -153,188 +175,221 @@
<context>
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Load more</translation>
<source>Settings</source>
<translation>Settings</translation>
</message>
<message>
<source>New Toot</source>
<translation>New Toot</translation>
</message>
<message>
<source>Reload</source>
<translation>Reload</translation>
</message>
<message>
<source>Open in Browser</source>
<translation>Open in Browser</translation>
</message>
<message>
<source>Nothing found</source>
<translation>Nothing found</translation>
</message>
</context>
<context>
<name>ProfileHeader</name>
<message>
<source>Bot</source>
<translation>Bot</translation>
</message>
<message>
<source>Follows you</source>
<translation>Follows you</translation>
</message>
<message>
<source>Group</source>
<translation>Group</translation>
</message>
</context>
<context>
<name>ProfilePage</name>
<message>
<source>About</source>
<extracomment>If there&apos;s no good translation for &quot;About&quot;, use &quot;Details&quot; (in details about profile).</extracomment>
<translation>About</translation>
</message>
<message>
<source>Followers</source>
<extracomment>Will show as: &quot;35 Followers&quot;</extracomment>
<translation>Followers</translation>
</message>
<message>
<source>Following</source>
<extracomment>Will show as: &quot;23 Following&quot;</extracomment>
<translation>Following</translation>
</message>
<message>
<source>Statuses</source>
<extracomment>Will show as: &quot;115 Statuses&quot;</extracomment>
<translation>Statuses</translation>
</message>
<message>
<source>Mention</source>
<translation>Mention</translation>
</message>
<message>
<source>Unfollow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Unfollow</translation>
</message>
<message>
<source>Requested</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Requested</translation>
</message>
<message>
<source>Follow</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Follow</translation>
</message>
<message>
<source>Unmute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Unmute</translation>
</message>
<message>
<source>Mute</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Mute</translation>
</message>
<message>
<source>Unblock</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Unblock</translation>
</message>
<message>
<source>Block</source>
<extracomment>Is a button. Keep it as short as possible.</extracomment>
<translation>Block</translation>
</message>
</context>
<context>
<name>SettingsPage</name>
<message>
<source>Settings</source>
<translation>Settings</translation>
</message>
<message>
<source>Loading</source>
<translation></translation>
<source>Options</source>
<translation>Options</translation>
</message>
<message>
<source>please wait...</source>
<translation></translation>
</message>
</context>
<context>
<name>Profile</name>
<message>
<source>Unfollow</source>
<translation>Unfollow</translation>
</message>
<message>
<source>Follow request sent!</source>
<translation>Follow request sent!</translation>
</message>
<message>
<source>Following</source>
<translation>Following</translation>
</message>
<message>
<source>Mute</source>
<translation>Mute</translation>
</message>
<message>
<source>Unmute</source>
<translation>Unmute</translation>
</message>
<message>
<source>Unblock</source>
<translation>Unblock</translation>
</message>
<message>
<source>Block</source>
<translation>Block</translation>
</message>
<message>
<source>Statuses</source>
<translation>Statuses</translation>
</message>
<message>
<source>Favourites</source>
<translation>Favourites</translation>
</message>
<message>
<source>Follow</source>
<translation>Follow</translation>
</message>
<message>
<source>Summary</source>
<translation>Summary</translation>
</message>
<message>
<source>Followers</source>
<translation>Followers</translation>
</message>
<message>
<source>Bio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open Profile in Browser</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Settings</name>
<message>
<source>Settings</source>
<translation type="unfinished">Settings</translation>
</message>
<message>
<source>Remove Account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Add Account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Deauthorize this app and remove your account</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Authorize this app to access your Mastodon account</source>
<translation type="unfinished"></translation>
<source>Load Images in Toots</source>
<translation>Load Images in Toots</translation>
</message>
<message>
<source>Disable this option if you want to preserve your data connection</source>
<translation type="unfinished"></translation>
<translation>Disable this option if you want to preserve your data connection</translation>
</message>
<message>
<source>Credits</source>
<translation type="unfinished"></translation>
<source>Account</source>
<translation>Account</translation>
</message>
<message>
<source>UI/UX design and development</source>
<translation type="unfinished"></translation>
<source>Remove Account</source>
<translation>Remove Account</translation>
</message>
<message>
<source>Visual identity</source>
<translation type="unfinished"></translation>
<source>Add Account</source>
<translation>Add Account</translation>
</message>
<message>
<source>Occitan &amp; French translation</source>
<translation type="unfinished"></translation>
<source>Deauthorize this app from using your account and remove account data from phone</source>
<translation>Deauthorize this app from using your account and remove account data from phone</translation>
</message>
<message>
<source>Dutch translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Spanish translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Added README file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Chinese translation</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load images in toots</source>
<translation type="unfinished"></translation>
<source>Authorize this app to access your Mastodon account</source>
<translation>Authorize this app to access your Mastodon account</translation>
</message>
<message>
<source>Translate</source>
<translation type="unfinished"></translation>
<translation>Translate</translation>
</message>
<message>
<source>Use Transifex to help with app translation to your language</source>
<translation type="unfinished"></translation>
<source>Credits</source>
<extracomment>Translation alternative: &quot;Development&quot;</extracomment>
<translation>Credits</translation>
</message>
<message>
<source>UI/UX design and development</source>
<translation>UI/UX design and development</translation>
</message>
<message>
<source>Visual identity</source>
<translation>Visual identity</translation>
</message>
<message>
<source>Development and translations</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Toot</name>
<message>
<source>boosted</source>
<translation>boosted</translation>
<translation>Development and translations</translation>
</message>
<message>
<source>favourited</source>
<translation>favourited</translation>
<source>Occitan &amp; French translation</source>
<translation>Occitan &amp; French translation</translation>
</message>
<message>
<source>followed you</source>
<translation>followed you</translation>
<source>Chinese translation</source>
<translation>Chinese translation</translation>
</message>
<message>
<source>Dutch translation</source>
<translation>Dutch translation</translation>
</message>
<message>
<source>Spanish translation</source>
<translation>Spanish translation</translation>
</message>
<message>
<source>Use</source>
<extracomment>Full sentence for translation: &quot;Use Transifex to help with app translation to your language.&quot; - The word Transifex is a link and doesn&apos;t need translation.</extracomment>
<translation>Use</translation>
</message>
<message>
<source>to help with app translation to your language.</source>
<translation>to help with app translation to your language.</translation>
</message>
</context>
<context>
<name>VisualContainer</name>
<message>
<source>Unboost</source>
<translation type="unfinished"></translation>
<translation>Unboost</translation>
</message>
<message>
<source>Boost</source>
<translation type="unfinished"></translation>
<translation>Boost</translation>
</message>
<message>
<source>Unfavorite</source>
<translation type="unfinished"></translation>
<translation>Unfavourite</translation>
</message>
<message>
<source>Favorite</source>
<translation type="unfinished"></translation>
<translation>Favourite</translation>
</message>
<message>
<source>Mention</source>
<translation>Mention</translation>
</message>
<message>
<source>Conversation</source>
<translation>Conversation</translation>
</message>
<message>
<source>Remove Bookmark</source>
<translation>Remove Bookmark</translation>
</message>
<message>
<source>Bookmark</source>
<translation>Bookmark</translation>
</message>
</context>
</TS>