Add / improve UI elements

- new ProfilePage expander
- flexible UI elements for various screensizes
- various UI changes
- code refactoring
This commit is contained in:
molan-git 2020-05-29 20:05:05 +02:00
parent 41041a77aa
commit fd2f317f25
25 changed files with 868 additions and 779 deletions

View file

@ -4,8 +4,3 @@ X-Nemo-Application-Type=silica-qt5
Icon=harbour-tooter Icon=harbour-tooter
Exec=harbour-tooter Exec=harbour-tooter
Name=Tooter 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

@ -53,6 +53,9 @@ HEADERS += src/dbusAdaptor.h
HEADERS += src/dbus.h HEADERS += src/dbus.h
DISTFILES += qml/harbour-tooter.qml \ DISTFILES += qml/harbour-tooter.qml \
qml/pages/ConversationPage.qml \
qml/pages/ProfilePage.qml \
qml/pages/SettingsPage.qml \
qml/pages/components/InfoBanner.qml \ qml/pages/components/InfoBanner.qml \
qml/pages/components/VisualContainer.qml \ qml/pages/components/VisualContainer.qml \
qml/pages/components/MiniStatus.qml \ qml/pages/components/MiniStatus.qml \
@ -67,11 +70,8 @@ DISTFILES += qml/harbour-tooter.qml \
qml/cover/CoverPage.qml \ qml/cover/CoverPage.qml \
qml/pages/MainPage.qml \ qml/pages/MainPage.qml \
qml/pages/LoginPage.qml \ qml/pages/LoginPage.qml \
qml/pages/Conversation.qml \
qml/pages/components/Toot.qml \ qml/pages/components/Toot.qml \
qml/pages/Browser.qml \ qml/pages/Browser.qml \
qml/pages/Profile.qml \
qml/pages/Settings.qml \
qml/lib/API.js \ qml/lib/API.js \
qml/images/notification.svg \ qml/images/notification.svg \
qml/images/verified.svg \ qml/images/verified.svg \
@ -95,7 +95,7 @@ SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
# to disable building translations every time, comment out the # to disable building translations every time, comment out the
# following CONFIG line # following CONFIG line
CONFIG += sailfishapp_i18n # CONFIG += sailfishapp_i18n
# German translation is enabled as an example. If you aren't # German translation is enabled as an example. If you aren't
# planning to localize your app, remember to comment out the # planning to localize your app, remember to comment out the

View file

@ -30,9 +30,9 @@
import QtQuick 2.0 import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import "../lib/API.js" as Logic import "../lib/API.js" as Logic
CoverBackground { CoverBackground {
onStatusChanged: { onStatusChanged: {
switch (status ){ switch (status ){
@ -135,5 +135,5 @@ CoverBackground {
notificationsLbl.text = notificationsNum; notificationsLbl.text = notificationsNum;
Logic.conf.notificationLastID = notificationLastID; Logic.conf.notificationLastID = notificationLastID;
} }
}
}

View file

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

View file

@ -56,8 +56,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader("Connection", "close"); http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() { // Call a function when the state changes. http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) { if (http.readyState === 4) {
if (http.status == 200) { if (http.status === 200) {
console.log("Successful GET API request to " +apiBase+endpoint); console.log("Successful GET API request to " +apiBase+endpoint);
callback(JSON.parse(http.response),http.status) callback(JSON.parse(http.response),http.status)
} else { } else {
@ -91,8 +91,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader("Connection", "close"); http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() { // Call a function when the state changes. http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) { if (http.readyState === 4) {
if (http.status == 200) { if (http.status === 200) {
console.log("Successful POST API request to " +apiBase+endpoint); console.log("Successful POST API request to " +apiBase+endpoint);
callback(JSON.parse(http.response),http.status) callback(JSON.parse(http.response),http.status)
} else { } else {
@ -180,8 +180,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() { // Call a function when the state changes. http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) { if (http.readyState === 4) {
if (http.status == 200) { if (http.status === 200) {
console.log("Registered Application: " + http.response); console.log("Registered Application: " + http.response);
callback(http.response) callback(http.response)
} else { } else {
@ -221,8 +221,8 @@ var MastodonAPI = function(config) {
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() { // Call a function when the state changes. http.onreadystatechange = function() { // Call a function when the state changes.
if (http.readyState == 4) { if (http.readyState === 4) {
if (http.status == 200) { if (http.status === 200) {
console.log("Got Token: " + http.response); console.log("Got Token: " + http.response);
callback(http.response) callback(http.response)
} else { } else {

View file

@ -9,9 +9,9 @@ Page {
id: conversationPage id: conversationPage
property string headerTitle: "" property string headerTitle: ""
property string type property string type
property alias title: header.title property alias title: header.title
property alias description: header.description property alias description: header.description
property alias avatar: header.image property alias avatar: header.image
property string suggestedUser: "" property string suggestedUser: ""
property ListModel suggestedModel property ListModel suggestedModel
property string toot_id: "" property string toot_id: ""
@ -66,6 +66,7 @@ Page {
id: header id: header
visible: false visible: false
} }
SilicaListView { SilicaListView {
id: conversationList id: conversationList
header: PageHeader { header: PageHeader {
@ -97,6 +98,7 @@ Page {
} }
} }
} }
PullDownMenu { PullDownMenu {
visible: type == "reply" && toot_url != "" visible: type == "reply" && toot_url != ""
/* MenuItem { /* MenuItem {
@ -110,19 +112,24 @@ Page {
} }
} }
} }
Rectangle { Rectangle {
id: predictionList id: predictionList
visible: false visible: false
anchors.bottom: panel.top anchors.bottom: panel.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: panel.right anchors.right: panel.right
height: suggestedModel.count > 6 ? Theme.itemSizeMedium * 6 : Theme.itemSizeMedium * suggestedModel.count anchors.top: parent.top
height: implicitHeight
//height: suggestedModel.count > 6 ? Theme.itemSizeMedium * 6 : Theme.itemSizeMedium * suggestedModel.count
color: Theme.highlightDimmerColor color: Theme.highlightDimmerColor
SilicaListView { SilicaListView {
anchors.fill: parent anchors.fill: parent
model: suggestedModel model: suggestedModel
clip: true clip: true
quickScroll: false
VerticalScrollDecorator {}
delegate: ItemUser { delegate: ItemUser {
onClicked: { onClicked: {
var start = toot.cursorPosition var start = toot.cursorPosition
@ -149,19 +156,19 @@ Page {
DockedPanel { DockedPanel {
id: panel id: panel
open: true open: true
onExpandedChanged: { //onExpandedChanged: {
if (!expanded) { // if (!expanded) {
show() // show()
} // }
} //}
width: parent.width width: parent.width
height: progressBar.height + toot.height + (mediaModel.count ? uploadedImages.height : 0) height: progressBar.height + toot.height + (mediaModel.count ? uploadedImages.height : 0)
+ btnContentWarning.height + Theme.paddingMedium + btnContentWarning.height + Theme.paddingMedium
+ (warningContent.visible ? warningContent.height : 0) + (warningContent.visible ? warningContent.height : 0)
dock: Dock.Bottom dock: Dock.Bottom
Rectangle {
Rectangle {
width: parent.width width: parent.width
height: progressBar.height height: progressBar.height
color: Theme.highlightBackgroundColor color: Theme.highlightBackgroundColor
@ -172,15 +179,16 @@ Page {
top: parent.top top: parent.top
} }
} }
Rectangle { Rectangle {
id: progressBar id: progressBar
width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0 width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0
height: Theme.itemSizeSmall * 0.05 height: Theme.itemSizeSmall * 0.05
color: Theme.highlightBackgroundColor color: Theme.highlightBackgroundColor
opacity: 0.7 opacity: 0.7
anchors { anchors {
left: parent.left left: parent.left
top: parent.top top: parent.top
} }
} }
@ -189,7 +197,7 @@ Page {
visible: false visible: false
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
anchors { anchors {
top: parent.top top: parent.top
topMargin: Theme.paddingMedium topMargin: Theme.paddingMedium
left: parent.left left: parent.left
right: parent.right right: parent.right
@ -201,10 +209,9 @@ Page {
placeholderColor: palette.highlightColor placeholderColor: palette.highlightColor
color: palette.highlightColor color: palette.highlightColor
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
EnterKey.onClicked: { EnterKey.onClicked: {}
//tweet()
}
} }
TextInput { TextInput {
id: textOperations id: textOperations
visible: false visible: false
@ -221,17 +228,19 @@ Page {
} }
autoScrollEnabled: true autoScrollEnabled: true
labelVisible: false labelVisible: false
//focus: true text: description !== "" && (description.charAt(0) === '@'
text: description !== "" && (description.charAt(0) == '@'
|| description.charAt( || description.charAt(
0) == '#') ? description + ' ' : '' 0) === '#') ? description + ' ' : ''
height: Math.max(270, Math.min(900, implicitHeight)) height: if (type !== "reply") {
Math.max(conversationPage.height / 3, Math.min(conversationPage.height * 0.65, implicitHeight))
}
else {
Math.max(conversationPage.height / 4, Math.min(conversationPage.height * 0.65, implicitHeight))
}
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
placeholderText: qsTr("What's on your mind?") placeholderText: qsTr("What's on your mind?")
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
EnterKey.onClicked: { EnterKey.onClicked: {}
//tweet()
}
onTextChanged: { onTextChanged: {
textOperations.text = toot.text textOperations.text = toot.text
textOperations.cursorPosition = toot.cursorPosition textOperations.cursorPosition = toot.cursorPosition
@ -247,45 +256,46 @@ Page {
} }
} }
} }
IconButton { IconButton {
id: btnSmileys id: btnSmileys
property string selection property string selection
onSelectionChanged: { onSelectionChanged: {
console.log(selection) console.log(selection)
} }
anchors { anchors {
top: warningContent.bottom top: warningContent.bottom
bottom: bottom.top bottom: bottom.top
right: parent.right right: parent.right
rightMargin: Theme.paddingSmall rightMargin: Theme.paddingSmall
} }
opacity: 0.8 opacity: 0.6
icon.source: "../../qml/images/emojiselect.svg" + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor)) icon.source: "../../qml/images/emojiselect.svg"
onClicked: pageStack.push(firstWizardPage) onClicked: pageStack.push(emojiSelect)
} }
SilicaGridView { SilicaGridView {
id: uploadedImages id: uploadedImages
width: parent.width width: parent.width
anchors.top: bottom.toot anchors.top: bottom.toot
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
height: mediaModel.count ? Theme.itemSizeSmall : 0 height: mediaModel.count ? Theme.itemSizeExtraLarge : 0
model: mediaModel model: mediaModel
cellWidth: uploadedImages.width / 4 cellWidth: uploadedImages.width / 4
cellHeight: Theme.itemSizeSmall cellHeight: Theme.itemSizeExtraLarge
delegate: BackgroundItem { delegate: BackgroundItem {
id: myDelegate id: myDelegate
width: uploadedImages.cellWidth width: uploadedImages.cellWidth
height: uploadedImages.cellHeight height: uploadedImages.cellHeight
RemorseItem { RemorseItem {
id: remorse id: remorse
} }
Image { Image {
anchors.fill: parent anchors.fill: parent
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
source: model.preview_url source: model.preview_url
} }
onClicked: { onClicked: {
var idx = index var idx = index
console.log(idx) console.log(idx)
@ -303,7 +313,6 @@ Page {
duration: 800 duration: 800
} }
} }
remove: Transition { remove: Transition {
NumberAnimation { NumberAnimation {
property: "opacity" property: "opacity"
@ -320,6 +329,7 @@ Page {
} }
} }
} }
IconButton { IconButton {
id: btnContentWarning id: btnContentWarning
anchors { anchors {
@ -332,6 +342,7 @@ Page {
+ (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor)) + (pressed ? Theme.highlightColor : (warningContent.visible ? Theme.secondaryHighlightColor : Theme.primaryColor))
onClicked: warningContent.visible = !warningContent.visible onClicked: warningContent.visible = !warningContent.visible
} }
IconButton { IconButton {
id: btnAddImage id: btnAddImage
enabled: mediaModel.count < 4 enabled: mediaModel.count < 4
@ -357,21 +368,18 @@ Page {
}) })
} }
} }
ImageUploader { ImageUploader {
id: imageUploader id: imageUploader
onProgressChanged: { onProgressChanged: {
console.log("progress " + progress) console.log("progress " + progress)
uploadProgress.width = parent.width * progress uploadProgress.width = parent.width * progress
} }
onSuccess: { onSuccess: {
uploadProgress.width = 0 uploadProgress.width = 0
console.log(replyData) console.log(replyData)
mediaModel.append(JSON.parse(replyData)) mediaModel.append(JSON.parse(replyData))
} }
onFailure: { onFailure: {
uploadProgress.width = 0 uploadProgress.width = 0
btnAddImage.enabled = true btnAddImage.enabled = true
@ -379,15 +387,16 @@ Page {
console.log(statusText) console.log(statusText)
} }
} }
ComboBox { ComboBox {
id: privacy id: privacy
anchors { anchors {
top: toot.bottom top: toot.bottom
topMargin: -Theme.paddingSmall * 1.5 topMargin: -Theme.paddingSmall * 1.5
left: btnAddImage.right left: btnAddImage.right
right: btnSend.left right: btnSend.left
} }
menu: ContextMenu { menu: ContextMenu {
MenuItem { MenuItem {
text: qsTr("Public") text: qsTr("Public")
} }
@ -421,7 +430,6 @@ Page {
console.log(mediaModel.get(k).id) console.log(mediaModel.get(k).id)
media_ids.push(mediaModel.get(k).id) media_ids.push(mediaModel.get(k).id)
} }
var msg = { var msg = {
"action": 'statuses', "action": 'statuses',
"method": 'POST', "method": 'POST',
@ -445,7 +453,7 @@ Page {
worker.sendMessage(msg) worker.sendMessage(msg)
warningContent.text = "" warningContent.text = ""
toot.text = "" toot.text = ""
mediaModel.clear(); mediaModel.clear()
sentBanner.showText(qsTr("Toot sent!")) sentBanner.showText(qsTr("Toot sent!"))
} }
} }
@ -453,11 +461,12 @@ Page {
Rectangle { Rectangle {
id: uploadProgress id: uploadProgress
color: Theme.highlightBackgroundColor color: Theme.highlightBackgroundColor
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
height: 3 height: Theme.itemSizeSmall * 0.05
} }
} }
Component.onCompleted: { Component.onCompleted: {
toot.cursorPosition = toot.text.length toot.cursorPosition = toot.text.length
if (mdl.count > 0) { if (mdl.count > 0) {
@ -490,157 +499,64 @@ Page {
"conf": Logic.conf "conf": Logic.conf
}) })
} }
Component {
id: firstWizardPage
Dialog { BackgroundItem {
id: emoticonsDialog id: showPanel
canAccept: false //selector.currentIndex >= 0 visible: !panel.open
height: Theme.paddingMedium
width: parent.width
opacity: enabled ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {} }
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
}
//acceptDestination: conversationPage MouseArea {
onAcceptPendingChanged: { anchors.fill: parent
if (acceptPending) { onClicked: panel.open = !panel.open
}
// Tell the destination page what the selected category is Rectangle {
// acceptDestinationInstance.category = selector.value width: parent.width
} height: progressBarShowPanel.height
} color: Theme.highlightBackgroundColor
opacity: 0.2
anchors {
left: parent.left
right: parent.right
top: parent.top
}
}
SilicaGridView { Rectangle {
id: gridView color: Theme.highlightBackgroundColor
anchors.fill: parent opacity: 0.2
cellWidth: gridView.width / 6 height: showPanel.height
cellHeight: cellWidth width: showPanel.width
header: PageHeader { anchors {
title: qsTr("Emojis") horizontalCenter: parent.horizontalCenter
description: qsTr("Tap to insert") top: parent.top
} bottom: parent.bottom
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: "🚀" } Rectangle {
ListElement { section: "Transport and map"; glyph: "🚃" } id: progressBarShowPanel
ListElement { section: "Transport and map"; glyph: "🚀" } width: toot.text.length ? panel.width * (toot.text.length / tootMaxChar) : 0
ListElement { section: "Transport and map"; glyph: "🚄" } height: Theme.itemSizeSmall * 0.05
ListElement { section: "Transport and map"; glyph: "🚅" } color: Theme.highlightBackgroundColor
ListElement { section: "Transport and map"; glyph: "🚇" } opacity: 0.7
ListElement { section: "Transport and map"; glyph: "🚉" } anchors {
ListElement { section: "Transport and map"; glyph: "🚌" } left: parent.left
ListElement { section: "Transport and map"; glyph: "🚏" } top: parent.top
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: "♊" } EmojiSelect {
ListElement { section: "Horoscope Signs"; glyph: "♋" } id: emojiSelect
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

@ -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 QtQuick 2.0
import QtWebKit 3.0 import QtWebKit 3.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
@ -192,5 +162,5 @@ 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 QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import "../lib/API.js" as Logic import "../lib/API.js" as Logic
@ -37,7 +7,7 @@ import "./components/"
Page { Page {
id: mainPage id: mainPage
property bool isFirstPage: true property bool isFirstPage: true
property bool isTablet: true; //Screen.sizeCategory >= Screen.Large property bool isTablet: true //Screen.sizeCategory >= Screen.Large
// The effective value will be restricted by ApplicationWindow.allowedOrientations // The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All allowedOrientations: Orientation.All
@ -185,7 +155,7 @@ Page {
delegate: ItemUser { delegate: ItemUser {
onClicked: { onClicked: {
pageStack.push(Qt.resolvedUrl("Profile.qml"), { pageStack.push(Qt.resolvedUrl("ProfilePage.qml"), {
"display_name": model.account_display_name, "display_name": model.account_display_name,
"username": model.account_acct, "username": model.account_acct,
"user_id": model.account_id, "user_id": model.account_id,
@ -207,7 +177,6 @@ Page {
} }
SlideshowView { SlideshowView {
id: slideshow id: slideshow
width: parent.width width: parent.width
@ -233,6 +202,11 @@ Page {
} }
IconButton { IconButton {
id: newTweet
width: Theme.iconSizeLarge
height: width
visible: !isPortrait ? true : !infoPanel.open
icon.source: "image://theme/icon-l-add"
anchors { anchors {
right: (mainPage.isPortrait ? parent.right : infoPanel.left) right: (mainPage.isPortrait ? parent.right : infoPanel.left)
bottom: (mainPage.isPortrait ? infoPanel.top : parent.bottom) bottom: (mainPage.isPortrait ? infoPanel.top : parent.bottom)
@ -241,14 +215,11 @@ Page {
bottom: Theme.paddingLarge bottom: Theme.paddingLarge
} }
} }
id: newTweet
width: Theme.iconSizeLarge
height: width
visible: !isPortrait ? true : !infoPanel.open
icon.source: "image://theme/icon-l-add"
onClicked: { 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"
})
} }
} }
@ -274,5 +245,5 @@ Page {
Component.onCompleted: { Component.onCompleted: {
console.log("aaa") console.log("aaa")
} }
}
}

View file

@ -1,306 +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: " "
}
}
}
}
}

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

@ -0,0 +1,374 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import "../lib/API.js" as Logic
import "./components/"
import QtGraphicalEffects 1.0
Page {
id: profilePage
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 '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: profileHeader
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
}
// ProfilePage ExpandingSection
ExpandingSectionGroup {
id: expander
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
ExpandingSection {
id: expandingSection1
title: qsTr("About")
content.sourceComponent: Column {
height: Math.min(txtContainer, parent.height*0.7)
spacing: Theme.paddingSmall
anchors.bottomMargin: Theme.paddingLarge
Rectangle {
id: txtContainer
width: expander.width
height: Math.min(txtNote.height, parent.height*0.488)
color: "transparent"
visible: {
if ((note.text === "") && (note.text === "<p></p>") ) {
false
} else {
true
}
}
SilicaListView {
id: txtFlickable
anchors.fill: txtContainer
clip: true
quickScroll: false
VerticalScrollDecorator { flickable: txtNote }
Text {
id: txtNote
text: note
textFormat: Text.StyledText
wrapMode: Text.Wrap
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.secondaryColor
linkColor: Theme.highlightColor
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)
/* Function still missing for user accounts */
// } else if (test.length === 4 && test[3][0] === "@" ) {
} else {
Qt.openUrlExternally(link);
}
}
}
}
}
Row {
id: statsRow
spacing: Theme.paddingLarge
anchors.horizontalCenter: parent.horizontalCenter
anchors.leftMargin: Theme.paddingLarge
anchors.rightMargin: Theme.paddingLarge
Text {
id: txtFollowers
visible: followers_count ? true : false
text: followers_count+" "+qsTr("Followers")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
wrapMode: Text.Wrap
}
Text {
id: txtFollowing
visible: following_count ? true : false
text: following_count+" "+qsTr("Following")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
wrapMode: Text.Wrap
}
Text {
id: txtStatuses
visible: statuses_count ? true : false
text: statuses_count+" "+qsTr("Statuses")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
wrapMode: Text.Wrap
}
/*Text {
id: txtFavourites
visible: favourites_count ? true : false
text: favourites_count+" "+qsTr("Favourites")
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.highlightColor
wrapMode: Text.Wrap
} */
}
Label {
id: separatorLabel1
x: Theme.horizontalPageMargin
width: parent.width - ( 2 * Theme.horizontalPageMargin )
font.pixelSize: Theme.fontSizeExtraSmall
wrapMode: Text.Wrap
anchors {
horizontalCenter: parent.horizontalCenter
}
}
ButtonLayout {
id: btnLayout
Button {
id: btnMention
preferredWidth: Theme.buttonWidthSmall
text: "Mention"
onClicked: {
pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
headerTitle: "Mention",
description: "@"+username,
type: "new"
})
}
}
Button {
id: btnFollow
preferredWidth: Theme.buttonWidthSmall
text: (following ? qsTr("Unfollow") : (requested ? qsTr("Requested") : 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);
// to-do: create notification banner "Follow request sent!"
}
}
Button {
id: btnMute
preferredWidth: Theme.buttonWidthSmall
text: (muting ? qsTr("Unmute") : qsTr("Mute"))
color: (muting ? highlightColor : 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 ? qsTr("Unblock") : 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);
}
}
}
Separator {
id: btnSeparator
width: parent.width
height: Theme.paddingMedium
color: Theme.primaryColor
opacity: 0.0
horizontalAlignment: Qt.AlignHCenter
}
Button {
id: btnBrowser
text: qsTr("Open in Browser")
preferredWidth: Theme.buttonWidthMedium
anchors {
horizontalCenter: parent.horizontalCenter
}
onClicked: {
Qt.openUrlExternally(url);
}
}
Label {
id: separatorLabel2
x: Theme.horizontalPageMargin
width: parent.width - ( 2 * Theme.horizontalPageMargin )
font.pixelSize: Theme.fontSizeExtraSmall
wrapMode: Text.Wrap
anchors {
horizontalCenter: parent.horizontalCenter
}
}
}
}
}
}

View file

@ -1,16 +1,15 @@
import QtQuick 2.0 import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import "../lib/API.js" as Logic import "../lib/API.js" as Logic
Page { Page {
id: settingsPage
SilicaFlickable { SilicaFlickable {
anchors.fill: parent anchors.fill: parent
contentHeight: column.height + Theme.paddingLarge contentHeight: column.height + Theme.paddingLarge
contentWidth: parent.width contentWidth: parent.width
RemorsePopup { id: remorsePopup } RemorsePopup { id: remorsePopup }
VerticalScrollDecorator {} VerticalScrollDecorator {}
Column { Column {
id: column id: column
@ -22,13 +21,12 @@ Page {
Column { Column {
// No spacing in this column // No spacing in this column
width: parent.width width: parent.width
IconTextSwitch { IconTextSwitch {
id: removeAccount id: removeAccount
text: Logic.conf['login'] ? qsTr("Remove Account") : qsTr("Add Account") 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") 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" icon.source: Logic.conf['login'] ? "image://theme/icon-m-contact" : "image://theme/icon-m-add"
onCheckedChanged: { onCheckedChanged: {
remorsePopup.execute(removeAccount.text, function() { remorsePopup.execute(removeAccount.text, function() {
busy = true; busy = true;
@ -42,18 +40,17 @@ Page {
pageStack.push(Qt.resolvedUrl("LoginPage.qml")) pageStack.push(Qt.resolvedUrl("LoginPage.qml"))
}) })
} }
/* busy = true; /* busy = true;
checked = false; checked = false;
timer1.start() timer1.start()
}*/
}*/
Timer { Timer {
id: timer1 id: timer1
interval: 4700 interval: 4700
onTriggered: parent.busy = false onTriggered: parent.busy = false
} }
} }
IconTextSwitch { IconTextSwitch {
//enabled: false //enabled: false
checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages'] checked: typeof Logic.conf['loadImages'] !== "undefined" && Logic.conf['loadImages']
@ -64,6 +61,7 @@ Page {
Logic.conf['loadImages'] = checked Logic.conf['loadImages'] = checked
} }
} }
IconTextSwitch { IconTextSwitch {
text: qsTr("Translate") text: qsTr("Translate")
description: qsTr("Use Transifex to help with app translation to your language") description: qsTr("Use Transifex to help with app translation to your language")
@ -81,6 +79,7 @@ Page {
} }
} }
} }
SectionHeader { SectionHeader {
text: qsTr("Credits") text: qsTr("Credits")
} }
@ -109,8 +108,8 @@ Page {
ListElement { ListElement {
name: "Molan" name: "Molan"
desc: qsTr("Development and translations") desc: qsTr("Development and translations")
mastodon: "" mastodon: "molan@fosstodon.org"
mail: "mol_an@sunrise.ch" mail: ""
} }
ListElement { ListElement {
name: "Quentin PAGÈS / Quenti ♏" name: "Quentin PAGÈS / Quenti ♏"
@ -159,7 +158,7 @@ Page {
onClicked: { onClicked: {
if (model.mastodon !== ""){ if (model.mastodon !== ""){
var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject'); var m = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
pageStack.push(Qt.resolvedUrl("Conversation.qml"), { pageStack.push(Qt.resolvedUrl("ConversationPage.qml"), {
toot_id: 0, toot_id: 0,
title: model.name, title: model.name,
description: '@'+model.mastodon, description: '@'+model.mastodon,
@ -198,4 +197,5 @@ Page {
} }
} }
} }
} }

View file

@ -0,0 +1,165 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
Component {
id: emojiComponent
Dialog {
id: emoticonsDialog
canAccept: false //selector.currentIndex >= 0
onAcceptPendingChanged: {
if (acceptPending) {
// Tell the destination page what the selected category is
// acceptDestinationInstance.category = selector.value
}
}
SilicaGridView {
id: gridView
anchors.fill: parent
//anchors.rightMargin: Theme.paddingLarge
//anchors.leftMargin: Theme.paddingLarge
cellWidth: gridView.width / 6
cellHeight: cellWidth
VerticalScrollDecorator {flickable: listEmojis }
header: PageHeader {
title: qsTr("Emojis")
description: qsTr("Tap to insert")
}
model: ListModel {
id: listEmojis
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: "People and Fantasy"; glyph: "🙅" }
ListElement { section: "People and Fantasy"; glyph: "🙆" }
ListElement { section: "People and Fantasy"; glyph: "🙇" }
ListElement { section: "People and Fantasy"; glyph: "🙈" }
ListElement { section: "People and Fantasy"; glyph: "🙉" }
ListElement { section: "People and Fantasy"; glyph: "🙊" }
ListElement { section: "People and Fantasy"; glyph: "🙋" }
ListElement { section: "People and Fantasy"; glyph: "🙍" }
ListElement { section: "People and Fantasy"; glyph: "🙎" }
ListElement { section: "People and Fantasy"; glyph: "👍" }
ListElement { section: "People and Fantasy"; glyph: "👎" }
ListElement { section: "People and Fantasy"; glyph: "🙌" }
ListElement { section: "People and Fantasy"; glyph: "✊" }
ListElement { section: "People and Fantasy"; glyph: "💪" }
ListElement { section: "People and Fantasy"; glyph: "👉" }
ListElement { section: "People and Fantasy"; 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

@ -2,11 +2,13 @@ import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import QtMultimedia 5.0 import QtMultimedia 5.0
FullscreenContentPage { FullscreenContentPage {
id: imagePage
property string type: "" property string type: ""
property string previewURL: "" property string previewURL: ""
property string mediaURL: "" property string mediaURL: ""
id: imagePage
allowedOrientations: Orientation.All allowedOrientations: Orientation.All
Component.onCompleted: function(){ Component.onCompleted: function(){
console.log(type) console.log(type)
@ -14,31 +16,12 @@ FullscreenContentPage {
console.log(mediaURL) console.log(mediaURL)
if (type != 'gifv' && type != 'video') { if (type != 'gifv' && type != 'video') {
imagePreview.source = mediaURL imagePreview.source = mediaURL
imageFlickable.visible = true; imageFlickable.visible = true
} else { } else {
video.source = mediaURL video.source = mediaURL
video.fillMode = VideoOutput.PreserveAspectFit video.fillMode = VideoOutput.PreserveAspectFit
video.play() video.play()
videoFlickable.visible = true; videoFlickable.visible = true
}
}
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()
} }
} }
@ -46,14 +29,17 @@ FullscreenContentPage {
id: videoFlickable id: videoFlickable
visible: false visible: false
anchors.fill: parent anchors.fill: parent
contentWidth: imageContainer.width; contentHeight: imageContainer.height contentWidth: imageContainer.width
contentHeight: imageContainer.height
clip: true clip: true
Image { Image {
id: videoPreview id: videoPreview
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
anchors.fill: parent anchors.fill: parent
source: previewURL source: previewURL
} }
Video { Video {
id: video id: video
anchors.fill: parent anchors.fill: parent
@ -82,7 +68,7 @@ FullscreenContentPage {
playerIcon.icon.source = "image://theme/icon-m-play" playerIcon.icon.source = "image://theme/icon-m-play"
return; return;
case MediaPlayer.StoppedState: case MediaPlayer.StoppedState:
playerIcon.icon.source = "image://theme/icon-m-stop" playerIcon.icon.source = "image://theme/icon-m-reload"
return; return;
} }
} }
@ -97,11 +83,10 @@ FullscreenContentPage {
playerProgress.minimumValue = 0 playerProgress.minimumValue = 0
playerProgress.value = position playerProgress.value = position
} }
} }
onStopped: function(){ onStopped: function(){
play() stop()
} }
IconButton { IconButton {
@ -128,20 +113,20 @@ FullscreenContentPage {
anchors.leftMargin: 0 anchors.leftMargin: 0
anchors.bottomMargin: Theme.paddingLarge*1.5 anchors.bottomMargin: Theme.paddingLarge*1.5
} }
IconButton { IconButton {
id: videoDlBtn id: videoDlBtn
visible: true
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.rightMargin: Theme.paddingLarge anchors.rightMargin: Theme.paddingLarge
anchors.bottomMargin: Theme.paddingLarge*1.5 anchors.bottomMargin: Theme.paddingLarge*1.5
icon.source: "image://theme/icon-m-device-download" icon.source: "image://theme/icon-m-cloud-download"
icon.opacity: 0.0
onClicked: { onClicked: {
var filename = mediaURL.split("/"); var filename = mediaURL.split("/");
FileDownloader.downloadFile(mediaURL, filename[filename.length-1]); FileDownloader.downloadFile(mediaURL, filename[filename.length-1]);
} }
} }
Rectangle { Rectangle {
visible: videoError.text != "" visible: videoError.text != ""
anchors.left: parent.left anchors.left: parent.left
@ -163,7 +148,6 @@ FullscreenContentPage {
} }
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: function() { onClicked: function() {
@ -180,7 +164,8 @@ FullscreenContentPage {
id: imageFlickable id: imageFlickable
visible: false visible: false
anchors.fill: parent anchors.fill: parent
contentWidth: imageContainer.width; contentHeight: imageContainer.height contentWidth: imageContainer.width
contentHeight: imageContainer.height
clip: true clip: true
onHeightChanged: if (imagePreview.status === Image.Ready) imagePreview.fitToScreen(); onHeightChanged: if (imagePreview.status === Image.Ready) imagePreview.fitToScreen();
@ -201,8 +186,8 @@ FullscreenContentPage {
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
cache: true cache: true
asynchronous: true asynchronous: true
sourceSize.height: 1000; sourceSize.height: 2000;
smooth: false smooth: true // might slower performance
onStatusChanged: { onStatusChanged: {
if (status == Image.Ready) { if (status == Image.Ready) {
fitToScreen() fitToScreen()
@ -255,6 +240,7 @@ FullscreenContentPage {
bounceBackAnimation.start() bounceBackAnimation.start()
} }
} }
NumberAnimation { NumberAnimation {
id: bounceBackAnimation id: bounceBackAnimation
target: imagePreview target: imagePreview
@ -280,17 +266,22 @@ FullscreenContentPage {
Component { Component {
id: loadingIndicator id: loadingIndicator
Item { Item {
height: childrenRect.height height: childrenRect.height
width: imagePage.width width: imagePage.width
ProgressCircle { ProgressCircle {
id: imageLoadingIndicator id: imageLoadingIndicator
progressColor: inAlternateCycle ? Theme.highlightColor : Theme.highlightDimmerColor
backgroundColor: inAlternateCycle ? Theme.highlightDimmerColor : Theme.highlightColor
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
progressValue: imagePreview.progress progressValue: imagePreview.progress
} }
} }
} }
} }
Component { Component {
id: failedLoading id: failedLoading
Text { Text {
@ -299,17 +290,26 @@ FullscreenContentPage {
color: Theme.highlightColor color: Theme.highlightColor
} }
} }
IconButton {
y: Theme.paddingLarge
anchors.right: parent.right
anchors.rightMargin: Theme.horizontalPageMargin
icon.source: "image://theme/icon-m-dismiss"
onClicked: pageStack.pop()
}
IconButton { IconButton {
visible: true
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.rightMargin: Theme.paddingLarge anchors.rightMargin: Theme.paddingLarge
anchors.bottomMargin: Theme.paddingLarge*1.5 anchors.bottomMargin: Theme.paddingLarge*1.5
icon.source: "image://theme/icon-m-device-download" icon.source: "image://theme/icon-m-cloud-download"
onClicked: { onClicked: {
var filename = mediaURL.split("/"); var filename = mediaURL.split("/");
FileDownloader.downloadFile(mediaURL, filename[filename.length-1]); FileDownloader.downloadFile(mediaURL, filename[filename.length-1]);
} }
} }
VerticalScrollDecorator { flickable: imageFlickable } VerticalScrollDecorator { flickable: imageFlickable }
} }

View file

@ -51,11 +51,12 @@ DockedPanel {
Timer { Timer {
id: autoClose id: autoClose
interval: 6000 interval: 4500
running: false running: false
onTriggered: { onTriggered: {
root.hide() root.hide()
stop() stop()
} }
} }
} }

View file

@ -32,14 +32,16 @@ BackgroundItem {
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: pageStack.push(Qt.resolvedUrl("./../Profile.qml"), { onClicked: pageStack.push(Qt.resolvedUrl("./../ProfilePage.qml"), {
"display_name": model.account_display_name, "display_name": model.account_display_name,
"username": model.account_acct, "username": model.account_acct,
"user_id": model.account_id, "user_id": model.account_id,
"profileImage": model.account_avatar "profileImage": model.account_avatar,
"profileBackground": model.account_header
}) })
} }
} }
Column { Column {
anchors.left: avatar.right anchors.left: avatar.right
anchors.leftMargin: Theme.paddingLarge anchors.leftMargin: Theme.paddingLarge
@ -63,6 +65,8 @@ BackgroundItem {
"display_name": model.account_display_name, "display_name": model.account_display_name,
"username": model.account_acct, "username": model.account_acct,
"user_id": model.account_id, "user_id": model.account_id,
"profileImage": model.account_avatar "profileImage": model.account_avatar,
"profileBackground": model.account_header
}) })
} }

View file

@ -146,8 +146,5 @@ Item {
} }
} }
} }
} }

View file

@ -1,8 +1,9 @@
import QtQuick 2.0 import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
Item { Item {
id: miniheader id: miniHeader
height: lblName.height height: lblName.height
width: parent.width width: parent.width
@ -67,4 +68,5 @@ Item {
rightMargin: Theme.horizontalPageMargin rightMargin: Theme.horizontalPageMargin
} }
} }
} }

View file

@ -1,8 +1,9 @@
import QtQuick 2.0 import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
Item { Item {
id: ministatus id: miniStatus
visible: true visible: true
height: icon.height+Theme.paddingMedium height: icon.height+Theme.paddingMedium
width: parent.width width: parent.width
@ -42,7 +43,7 @@ Item {
action = qsTr('followed you'); action = qsTr('followed you');
break; break;
default: default:
ministatus.visible = false miniStatus.visible = false
action = type; action = type;
} }
return typeof reblog_account_username !== "undefined" ? '@' + reblog_account_username + ' ' + action : '' return typeof reblog_account_username !== "undefined" ? '@' + reblog_account_username + ' ' + action : ''

View file

@ -2,7 +2,9 @@ import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import QtMultimedia 5.0 import QtMultimedia 5.0
Item { Item {
id: myImage
property string type : "" property string type : ""
property string previewURL: "" property string previewURL: ""
property string mediaURL: "" property string mediaURL: ""
@ -37,8 +39,6 @@ Item {
progressRec.width = 0; progressRec.width = 0;
} }
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {

View file

@ -3,9 +3,10 @@ import Sailfish.Silica 1.0
import "../../lib/API.js" as Logic import "../../lib/API.js" as Logic
import "." import "."
SilicaListView { SilicaListView {
id: myList id: myList
property string type; property string type
property string title property string title
property string vwPlaceholderText: qsTr("Loading") property string vwPlaceholderText: qsTr("Loading")
property string vwPlaceholderHint: qsTr("please wait...") property string vwPlaceholderHint: qsTr("please wait...")
@ -13,21 +14,19 @@ SilicaListView {
property ListModel mdl: [] property ListModel mdl: []
property variant params: [] property variant params: []
property var locale: Qt.locale() property var locale: Qt.locale()
property bool autoLoadMore : true; property bool autoLoadMore: true
property bool loadStarted : false; property bool loadStarted: false
property int scrollOffset; property int scrollOffset
property string action: "" property string action: ""
property variant vars property variant vars
property variant conf property variant conf
property bool notifier : false; property bool notifier: false
model: mdl model: mdl
signal notify (string what, int num) signal notify (string what, int num)
onNotify: { onNotify: {
console.log(what + " - " + num) console.log(what + " - " + num)
} }
signal openDrawer (bool setDrawer) signal openDrawer (bool setDrawer)
onOpenDrawer: { onOpenDrawer: {
//console.log("Open drawer: " + setDrawer) //console.log("Open drawer: " + setDrawer)
@ -37,7 +36,6 @@ SilicaListView {
console.log("LIST send signal emitted with notice: " + notice) console.log("LIST send signal emitted with notice: " + notice)
} }
BusyIndicator { BusyIndicator {
size: BusyIndicatorSize.Large size: BusyIndicatorSize.Large
running: myList.model.count === 0 && !viewPlaceHolder.visible running: myList.model.count === 0 && !viewPlaceHolder.visible
@ -49,8 +47,6 @@ SilicaListView {
description: myList.description description: myList.description
} }
ViewPlaceholder { ViewPlaceholder {
id: viewPlaceHolder id: viewPlaceHolder
enabled: model.count === 0 enabled: model.count === 0
@ -62,10 +58,16 @@ SilicaListView {
MenuItem { MenuItem {
text: qsTr("Settings") text: qsTr("Settings")
onClicked: { onClicked: {
pageStack.push(Qt.resolvedUrl("../Settings.qml"), {}) pageStack.push(Qt.resolvedUrl("../SettingsPage.qml"), {})
} }
} }
/* MenuItem {
text: qsTr("Open in Browser")
visible: profile_url != ""
onClicked: {
Clipboard.text = profile_url
}
} */
MenuItem { MenuItem {
text: qsTr("Load more") text: qsTr("Load more")
onClicked: { onClicked: {
@ -95,10 +97,9 @@ SilicaListView {
} }
onCountChanged: { onCountChanged: {
loadStarted = false; loadStarted = false
/*contentY = scrollOffset /*contentY = scrollOffset
console.log("CountChanged!")*/ console.log("CountChanged!")*/
} }
footer: Item{ footer: Item{
@ -122,17 +123,16 @@ SilicaListView {
} }
} }
onContentYChanged: { onContentYChanged: {
if (Math.abs(contentY - scrollOffset) > Theme.itemSizeMedium) { if (Math.abs(contentY - scrollOffset) > Theme.itemSizeMedium) {
openDrawer(contentY - scrollOffset > 0 ? false : true ) openDrawer(contentY - scrollOffset > 0 ? false : true )
scrollOffset = contentY scrollOffset = contentY
} }
if(contentY+height > footerItem.y && !loadStarted && autoLoadMore){ if(contentY+height > footerItem.y && !loadStarted && autoLoadMore){
loadData("append") loadData("append")
loadStarted = true; loadStarted = true
} }
} }
VerticalScrollDecorator {} VerticalScrollDecorator {}
WorkerScript { WorkerScript {
@ -161,16 +161,16 @@ SilicaListView {
} }
} }
function loadData(mode){ function loadData(mode){
var p = []; var p = []
if (params.length) if (params.length)
for(var i = 0; i<params.length; i++) for(var i = 0; i<params.length; i++)
p.push(params[i]) p.push(params[i])
if (mode === "append" && model.count){ if (mode === "append" && model.count){
p.push({name: 'max_id', data: model.get(model.count-1).id}); p.push({name: 'max_id', data: model.get(model.count-1).id})
} }
if (mode === "prepend" && model.count){ if (mode === "prepend" && model.count){
p.push({name:'since_id', data: model.get(0).id}); p.push({name:'since_id', data: model.get(0).id})
} }
var msg = { var msg = {
@ -182,7 +182,7 @@ SilicaListView {
}; };
console.log(JSON.stringify(msg)) console.log(JSON.stringify(msg))
if (type !== "") if (type !== "")
worker.sendMessage(msg); worker.sendMessage(msg)
} }
} }

View file

@ -2,13 +2,13 @@ import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
SilicaGridView { SilicaGridView {
signal slideshowShow(int vIndex); signal slideshowShow(int vIndex)
signal slideshowIndexChanged(int vIndex); signal slideshowIndexChanged(int vIndex)
onSlideshowIndexChanged: { onSlideshowIndexChanged: {
navigateTo(vIndex) navigateTo(vIndex)
} }
id: gridView id: gridView
property bool isPortrait: false property bool isPortrait: false
ListModel { ListModel {
@ -55,7 +55,6 @@ SilicaGridView {
cellWidth: isPortrait ? gridView.width : gridView.width / model.count cellWidth: isPortrait ? gridView.width : gridView.width / model.count
cellHeight: isPortrait ? gridView.height/model.count : gridView.height cellHeight: isPortrait ? gridView.height/model.count : gridView.height
delegate: BackgroundItem { delegate: BackgroundItem {
clip: true clip: true
id: rectangle id: rectangle
@ -78,7 +77,6 @@ SilicaGridView {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
color: Theme.highlightColor color: Theme.highlightColor
} }
GlassItem { GlassItem {
id: effect2 id: effect2
visible: isPortrait && unread visible: isPortrait && unread
@ -90,18 +88,10 @@ SilicaGridView {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: Theme.highlightColor color: Theme.highlightColor
} }
OpacityRampEffect { OpacityRampEffect {
sourceItem: label sourceItem: label
offset: 0.5 offset: 0.5
} }
/*Image {
source: model.icon + (highlighted
? Theme.highlightColor
: (model.active ? Theme.primaryColor : Theme.secondaryHighlightColor))
anchors.centerIn: parent
}*/
ColorOverlay { ColorOverlay {
anchors.fill: image anchors.fill: image
source: image source: image
@ -170,4 +160,5 @@ SilicaGridView {
} }
VerticalScrollDecorator {} VerticalScrollDecorator {}
} }

View file

@ -1,13 +1,14 @@
import QtQuick 2.0 import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
Item { Item {
id: header id: profileHeader
property int value: 0; property int value: 0
property string title: ""; property string title: ""
property string description: ""; property string description: ""
property string image: ""; property string image: ""
property string bg: ""; property string bg: ""
width: parent.width width: parent.width
height: icon.height + Theme.paddingLarge*2 height: icon.height + Theme.paddingLarge*2

View file

@ -2,32 +2,30 @@ import QtQuick 2.0
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
BackgroundItem { BackgroundItem {
signal send (string notice) signal send (string notice)
signal navigateTo(string link)
id: delegate id: delegate
//property string text: "0" //property string text: "0"
width: parent.width 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 height: lblText.paintedHeight + (lblText.text.length > 0 ? Theme.paddingLarge : 0 )+ lblName.paintedHeight + (type.length ? Theme.paddingLarge + iconRT.height : 0) + Theme.paddingLarge
Image { Image {
id: iconRT id: iconRT
y: Theme.paddingLarge y: Theme.paddingLarge
anchors { anchors.right: avatar.right
right: avatar.right
}
visible: type.length visible: type.length
width: Theme.iconSizeExtraSmall width: Theme.iconSizeExtraSmall
height: width height: width
source: "../../images/boosted.svg" source: "../../images/boosted.svg"
} }
Label { Label {
id: lblRtByName id: lblRtByName
visible: type.length visible: type.length
anchors { anchors.left: lblName.left
left: lblName.left anchors.bottom: iconRT.bottom
bottom: iconRT.bottom
}
text: { text: {
var action; var action;
switch(type){ switch(type){
@ -45,10 +43,10 @@ BackgroundItem {
} }
return '@' + retweetScreenName + ' ' + action return '@' + retweetScreenName + ' ' + action
} }
font.pixelSize: Theme.fontSizeExtraSmall font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.secondaryColor color: Theme.secondaryColor
} }
Image { Image {
id: avatar id: avatar
x: Theme.horizontalPageMargin x: Theme.horizontalPageMargin
@ -62,28 +60,28 @@ BackgroundItem {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
pageStack.push(Qt.resolvedUrl("../Profile.qml"), { pageStack.push(Qt.resolvedUrl("../ProfilePage.qml"), {
"display_name": account_display_name, "display_name": account_display_name,
"username": account_username, "username": account_username,
"profileImage": account_avatar "profileImage": account_avatar
}) })
} }
} }
} }
Label { Label {
id: lblName id: lblName
text: account_display_name
font.weight: Font.Bold
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
anchors { anchors {
top: avatar.top top: avatar.top
topMargin: 0 topMargin: 0
left: avatar.right left: avatar.right
leftMargin: Theme.paddingMedium leftMargin: Theme.paddingMedium
} }
text: account_display_name
font.weight: Font.Bold
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
} }
Image { Image {
@ -103,7 +101,6 @@ BackgroundItem {
: Theme.primaryColor) : Theme.primaryColor)
} }
Label { Label {
id: lblScreenName id: lblScreenName
anchors { anchors {
@ -117,6 +114,7 @@ BackgroundItem {
font.pixelSize: Theme.fontSizeExtraSmall font.pixelSize: Theme.fontSizeExtraSmall
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor) color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
} }
Label { Label {
function timestamp() { function timestamp() {
var txt = Format.formatDate(created_at, Formatter.Timepoint) var txt = Format.formatDate(created_at, Formatter.Timepoint)
@ -135,7 +133,7 @@ BackgroundItem {
} }
} }
Label { Text {
id: lblText id: lblText
anchors { anchors {
left: lblName.left left: lblName.left
@ -154,20 +152,16 @@ BackgroundItem {
"profileImage": "" "profileImage": ""
}) })
} else if (link[0] === "#") { } else if (link[0] === "#") {
pageStack.pop(pageStack.find(function(page) { pageStack.pop(pageStack.find(function(page) {
var check = page.isFirstPage === true; var check = page.isFirstPage === true;
if (check) if (check)
page.onLinkActivated(link) page.onLinkActivated(link)
return check; return check;
})); }));
send(link) send(link)
} else { } else {
Qt.openUrlExternally(link); Qt.openUrlExternally(link);
} }
} }
text: content text: content
textFormat: Text.RichText textFormat: Text.RichText
@ -178,10 +172,12 @@ BackgroundItem {
color: (pressed ? Theme.highlightColor : Theme.primaryColor) color: (pressed ? Theme.highlightColor : Theme.primaryColor)
} }
onClicked: { onClicked: {
pageStack.push(Qt.resolvedUrl("../Conversation.qml"), { pageStack.push(Qt.resolvedUrl("../ConversationPage.qml"), {
headerTitle: "Conversation",
toot_id: id, toot_id: id,
title: account_display_name, toot_url: status_url,
description: '@'+account_username, //title: account_display_name,
description: '@'+account_acc,
avatar: account_avatar, avatar: account_avatar,
type: "reply" type: "reply"
}) })

View file

@ -2,12 +2,13 @@ import QtQuick 2.2
import Sailfish.Silica 1.0 import Sailfish.Silica 1.0
import "../../lib/API.js" as Logic import "../../lib/API.js" as Logic
BackgroundItem { BackgroundItem {
id: delegate id: delegate
signal send (string notice) signal send (string notice)
signal navigateTo(string link) signal navigateTo(string link)
width: parent.width 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: 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)
Rectangle { Rectangle {
x: 0; x: 0;
y: 0; y: 0;
@ -15,11 +16,11 @@ BackgroundItem {
width: parent.width width: parent.width
height: parent.height height: parent.height
opacity: 0.3 opacity: 0.3
color: Theme.highlightBackgroundColor; color: Theme.highlightBackgroundColor
} }
MiniStatus { MiniStatus {
id: ministatus id: miniStatus
anchors { anchors {
leftMargin: Theme.horizontalPageMargin leftMargin: Theme.horizontalPageMargin
rightMargin: Theme.horizontalPageMargin rightMargin: Theme.horizontalPageMargin
@ -31,8 +32,8 @@ BackgroundItem {
Image { Image {
id: avatar id: avatar
anchors { anchors {
top: ministatus.visible ? ministatus.bottom : parent.top top: miniStatus.visible ? miniStatus.bottom : parent.top
topMargin: ministatus.visible ? Theme.paddingMedium : Theme.paddingLarge topMargin: miniStatus.visible ? Theme.paddingMedium : Theme.paddingLarge
left: parent.left left: parent.left
leftMargin: Theme.horizontalPageMargin leftMargin: Theme.horizontalPageMargin
} }
@ -50,10 +51,11 @@ BackgroundItem {
? Theme.highlightColor ? Theme.highlightColor
: Theme.primaryColor) : Theme.primaryColor)
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
pageStack.push(Qt.resolvedUrl("../Profile.qml"), { pageStack.push(Qt.resolvedUrl("../ProfilePage.qml"), {
"display_name": model.account_display_name, "display_name": model.account_display_name,
"username": model.account_acct, "username": model.account_acct,
"user_id": model.account_id, "user_id": model.account_id,
@ -63,6 +65,7 @@ BackgroundItem {
} }
} }
Image { Image {
id: iconTR id: iconTR
anchors { anchors {
@ -74,7 +77,8 @@ BackgroundItem {
width: Theme.iconSizeExtraSmall width: Theme.iconSizeExtraSmall
height: width height: width
source: "image://theme/icon-s-retweet" source: "image://theme/icon-s-retweet"
} }
Rectangle { Rectangle {
color: Theme.highlightDimmerColor color: Theme.highlightDimmerColor
width: Theme.iconSizeSmall width: Theme.iconSizeSmall
@ -98,6 +102,7 @@ BackgroundItem {
} }
} }
} }
MiniHeader { MiniHeader {
id: miniHeader id: miniHeader
anchors { anchors {
@ -106,6 +111,7 @@ BackgroundItem {
right: parent.right right: parent.right
} }
} }
Text { Text {
id: lblContent id: lblContent
anchors { anchors {
@ -176,6 +182,7 @@ BackgroundItem {
wrapMode: Text.Wrap wrapMode: Text.Wrap
text: model.status_spoiler_text text: model.status_spoiler_text
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: parent.visible = false; onClicked: parent.visible = false;
@ -225,6 +232,7 @@ BackgroundItem {
height: width height: width
source: "image://theme/icon-s-retweet?" + (!model.reblogged ? Theme.highlightColor : Theme.primaryColor) source: "image://theme/icon-s-retweet?" + (!model.reblogged ? Theme.highlightColor : Theme.primaryColor)
} }
Label { Label {
anchors { anchors {
left: icRT.right left: icRT.right
@ -236,6 +244,7 @@ BackgroundItem {
color: !model.reblogged ? Theme.highlightColor : Theme.primaryColor color: !model.reblogged ? Theme.highlightColor : Theme.primaryColor
} }
} }
MenuItem { MenuItem {
enabled: model.type !== "follow" enabled: model.type !== "follow"
text: typeof model.favourited !== "undefined" && model.favourited ? qsTr("Unfavorite") : qsTr("Favorite") text: typeof model.favourited !== "undefined" && model.favourited ? qsTr("Unfavorite") : qsTr("Favorite")
@ -251,6 +260,7 @@ BackgroundItem {
model.favourites_count = !status ? model.favourites_count+1 : (model.favourites_count > 0 ? model.favourites_count-1 : model.favourites_count); model.favourites_count = !status ? model.favourites_count+1 : (model.favourites_count > 0 ? model.favourites_count-1 : model.favourites_count);
model.favourited = !model.favourited model.favourited = !model.favourited
} }
Image { Image {
id: icFA id: icFA
anchors { anchors {
@ -262,6 +272,7 @@ BackgroundItem {
height: width height: width
source: "image://theme/icon-s-favorite?" + (!model.favourited ? Theme.highlightColor : Theme.primaryColor) source: "image://theme/icon-s-favorite?" + (!model.favourited ? Theme.highlightColor : Theme.primaryColor)
} }
Label { Label {
anchors { anchors {
left: icFA.right left: icFA.right
@ -279,7 +290,7 @@ BackgroundItem {
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") if (typeof mdl !== "undefined")
m.append(mdl.get(index)) m.append(mdl.get(index))
pageStack.push(Qt.resolvedUrl("../Conversation.qml"), { pageStack.push(Qt.resolvedUrl("../ConversationPage.qml"), {
headerTitle: "Conversation", headerTitle: "Conversation",
toot_id: status_id, toot_id: status_id,
toot_url: status_url, toot_url: status_url,

View file

@ -23,21 +23,21 @@
<context> <context>
<name>Conversation</name> <name>Conversation</name>
<message> <message>
<source>Delete</source> <source>Copy Link to Clipboard</source>
<translation>Delete</translation> <translation type="unfinished"></translation>
</message>
<message>
<source>Emojis</source>
<translation>Emojis</translation>
</message>
<message>
<source>Tap to insert</source>
<translation>Tap to insert</translation>
</message> </message>
<message> <message>
<source>Write your warning here</source> <source>Write your warning here</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Delete</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Public</source> <source>Public</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -54,16 +54,19 @@
<source>Direct</source> <source>Direct</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>What&apos;s on your mind?</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Toot sent!</source> <source>Toot sent!</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context>
<context>
<name>EmojiPage</name>
<message> <message>
<source>Copy Link to Clipboard</source> <source>Emojis</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Tap to insert</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>