Supporting images in the TL

This commit is contained in:
Dusko Angirevic 2017-06-16 16:45:04 +02:00
parent a3bd2834b7
commit 6a20bc1657
14 changed files with 348 additions and 59 deletions

View file

@ -110,6 +110,7 @@ Qt.include("Mastodon.js")
var modelTLhome = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
var modelTLpublic = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
var modelTLnotifications = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
var modelTLsearch = Qt.createQmlObject('import QtQuick 2.0; ListModel { }', Qt.application, 'InternalQmlObject');
var notificationsList = []
var notificationGenerator = function(item){
var notification;

View file

@ -21,10 +21,20 @@ WorkerScript.onMessage = function(msg) {
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) {
for (var i in data) {
if (data.hasOwnProperty(i)) {
console.log(JSON.stringify(data[i]))
WorkerScript.sendMessage({ 'action': msg.action, 'success': true, key: i, "data": data[i]})
if (msg.action === "statuses"){
// status posted
if(msg.model){
var item = parseToot(data);
msg.model.append(item)
msg.model.sync();
}
} else {
for (var i in data) {
if (data.hasOwnProperty(i)) {
console.log(JSON.stringify(data[i]))
WorkerScript.sendMessage({ 'action': msg.action, 'success': true, key: i, "data": data[i]})
}
}
}
});
@ -83,8 +93,8 @@ WorkerScript.onMessage = function(msg) {
}
if(msg.model && items.length)
addDataToModel(msg.model, msg.mode, items)
if(msg.action === "notifications")
orderNotifications(items)
/*if(msg.action === "notifications")
orderNotifications(items)*/
});
}
@ -124,7 +134,8 @@ function parseNotification(data){
//console.log(JSON.stringify(data))
var item = {
id: data.id,
type: data.type
type: data.type,
attachments: []
};
switch (item['type']){
case "mention":
@ -156,6 +167,7 @@ function parseNotification(data){
item = parseAccounts(item, "reblog_", data["account"])
item['content'] = data['account']['note']
item['typeIcon'] = "image://theme/icon-s-installed"
item['attachments'] = []
break;
default:
@ -164,7 +176,7 @@ function parseNotification(data){
item['id'] = data.id
item['created_at'] = new Date(data.created_at)
item['section'] = new Date(data["created_at"]).toLocaleDateString()
item['section'] = getDate(data["created_at"])
return item;
}
@ -180,6 +192,10 @@ function collect() {
}
return ret;
}
function getDate(dateStr){
var ts = new Date(dateStr);
return new Date(ts.getFullYear(), ts.getMonth(), ts.getDate(), 0, 0, 0)
}
function parseToot (data){
//console.log(JSON.stringify(data))
var item = {};
@ -191,7 +207,7 @@ function parseToot (data){
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'] = new Date(data["created_at"]).toLocaleDateString()
item['section'] = getDate(data["created_at"]);
item['status_reblogs_count'] = data["reblogs_count"]
item['status_favourites_count'] = data["favourites_count"]
item['status_reblogged'] = data["reblogged"]
@ -212,13 +228,13 @@ function parseToot (data){
} else {
item = parseAccounts(item, "", data["account"])
}
item['content'] = data['content'].replaceAll('</span><span class="invisible">', '').replaceAll('<span class="invisible">', '').replaceAll('</span><span class="ellipsis">', '');
//item['application_name'] = data["application"]["name"]
//item['application_website'] = data["application"]["website"]
// account
item['content'] = data['content'].replace(/(<([^>]+)>)/ig,"");
//item['content'] = data['content'].replace(/(<([^>]+)>)/ig,"");
/*for(var i = 0; i < data['tags'].length ; i++){
var tag = data['tags'][i]['name'];
console.log(tag)
@ -227,7 +243,6 @@ function parseToot (data){
item['attachments'] = [];
for(var i = 0; i < data['media_attachments'].length ; i++){
var attachments = data['media_attachments'][i];
console.log(JSON.stringify(attachments))
item['content'] = item['content'].replaceAll(attachments['text_url'], '')
item['attachments'].push({
id: attachments['id'],
@ -237,8 +252,7 @@ function parseToot (data){
preview_url: attachments['preview_url']
})
}
console.log(JSON.stringify(item['attachments']))
item['content'] = item['content'].split(" ")
/*item['content'] = item['content'].split(" ")
for(var i = 0; i < item['content'].length ; i++){
if(item['content'][i][0] === "#"){
item['content'][i] = '<a href="'+item['content'][i]+'">'+item['content'][i]+'</a>';
@ -247,9 +261,8 @@ function parseToot (data){
item['content'][i] = '<a href="'+item['content'][i]+'">'+item['content'][i]+'</a>';
}
}
item['content'] = item['content'].join(" ").autoLink()
item['content'] = item['content'].join(" ").autoLink()*/
//console.log(JSON.stringify(item))
return item;
}

View file

@ -137,6 +137,8 @@ Page {
var msg = {
'action' : 'statuses',
'method' : 'POST',
'model' : mdl,
'mode' : "append",
'params' : {
"status": toot.text,
"visibility": visibility[privacy.currentIndex]

View file

@ -145,7 +145,7 @@ Page {
}
clip: true
model: ListModel {}
mdl: ListModel {}
type: "accounts/"+user_id+"/statuses"
vars: {}
conf: Logic.conf

View file

@ -0,0 +1,66 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtMultimedia 5.0
Page {
id: page
property string type: ""
property string previewURL: ""
property string mediaURL: ""
allowedOrientations: Orientation.All
Item {
anchors.fill: parent
clip: true
Image {
id: image
anchors.centerIn: parent
//fillMode: Image.PreserveAspectCrop
asynchronous: true
opacity: status === Image.Ready ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {} }
source: mediaURL
onStatusChanged: {
if (status === Image.Ready) {
console.log('Loaded')
width = sourceSize.width
height = sourceSize.height
if (width > height)
pinch.scale = page.width / width
else
pinch.scale = page.height / height
}
}
}
Video {
id: video
anchors.fill: parent
autoLoad: true
source: videoURL
onErrorStringChanged: {
console.log(errorString)
}
MouseArea {
anchors.fill: parent
onClicked: {
video.playbackState == MediaPlayer.PlayingState ? video.pause() : video.play()
}
}
focus: true
}
PinchArea {
id: pinch
visible: videoURL === ""
anchors.fill: parent
pinch.target: image
pinch.minimumScale: 0.1
pinch.maximumScale: 10
pinch.dragAxis: Pinch.XAndYAxis
}
}
}

View file

@ -0,0 +1,154 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtMultimedia 5.0
Item {
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){
model.remove(model.count-1)
}
//console.log(JSON.stringify(model.get(0)))
}
switch(model.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.width = (holder.width-Theme.paddingSmall)/2
placeholder1.height = placeholder1.width
placeholder2.width = placeholder1.width
placeholder2.height = placeholder1.width
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.width = holder.width - Theme.paddingSmall - Theme.itemSizeLarge;
placeholder1.height = Theme.itemSizeLarge*2+Theme.paddingSmall
placeholder2.width = Theme.itemSizeLarge;
placeholder2.height = placeholder2.width
placeholder2.x = placeholder1.x + placeholder1.width + Theme.paddingSmall;
break;
case 4:
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;
holder.height = placeholder1.height
break;
default:
holder.height = 0
}
}
MyImage {
id: placeholder1
width: 2
height: 1
opacity: pressed ? 0.6 : 1
visible: {
if (model && model.count){
type = model.get(0).type
previewURL = model.get(0).preview_url
mediaURL = model.get(0).url
height = 200
return true
} else {
height = 0
return false
}
}
Image {
visible: model.count && (model.get(0).type === "video" || model.get(0).type === "gifv")
anchors.centerIn: parent
source: "image://theme/icon-l-play"
}
}
MyImage {
id: placeholder2
width: 2
height: 1
opacity: pressed ? 0.6 : 1
visible: {
if (model && model.count && model.get(1)){
type = model.get(1).type
previewURL = model.get(1).preview_url
mediaURL = model.get(1).url
height = 200
return true
} else {
height = 0
return false
}
}
}
MyImage {
id: placeholder3
width: 2
height: 1
opacity: pressed ? 0.6 : 1
visible: {
if (model && model.count && model.get(2)){
type = model.get(2).type
previewURL = model.get(2).preview_url
mediaURL = model.get(2).url
height = 200
return true
} else {
height = 0
return false
}
}
}
MyImage {
id: placeholder4
width: 2
height: 1
opacity: pressed ? 0.6 : 1
visible: {
if (model && model.count && model.get(3)){
type = model.get(3).type
previewURL = model.get(3).preview_url
mediaURL = model.get(3).url
height = 200
return true
} else {
height = 0
return false
}
}
}
}

View file

@ -18,7 +18,7 @@ Item {
visible: type.length
width: Theme.iconSizeExtraSmall
height: width
source: typeIcon
source: typeof typeIcon !== "undefined" ? typeIcon : ""
}
Label {
@ -45,7 +45,7 @@ Item {
ministatus.visible = false
action = type;
}
return '@' + reblog_account_username + ' ' + action
return typeof reblog_account_username !== "undefined" ? '@' + reblog_account_username + ' ' + action : ''
}
font.pixelSize: Theme.fontSizeExtraSmall

View file

@ -0,0 +1,23 @@
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtMultimedia 5.0
Item {
property string type : ""
property string previewURL: ""
property string mediaURL: ""
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
asynchronous: true
opacity: status === Image.Ready ? 1.0 : 0.0
Behavior on opacity { FadeAnimator {} }
source: previewURL
MouseArea {
anchors.fill: parent
onClicked: {
pageStack.push(Qt.resolvedUrl("./ImageFullScreen.qml"), {"previewURL": previewURL, "mediaURL": mediaURL, "type": type})
}
}
}
}

View file

@ -2,20 +2,9 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import "../../lib/API.js" as Logic
import "."
import org.nemomobile.notifications 1.0
SilicaListView {
Notification {
id: notification
category: "x-nemo.example"
urgency: Notification.Normal
onClicked: console.log("Clicked")
}
id: myList
property string type;
property string title
@ -86,19 +75,20 @@ SilicaListView {
}
}
}
PushUpMenu {
/*PushUpMenu {
MenuItem {
text: qsTr("Load more")
onClicked: {
loadData("append")
}
}
}
}*/
clip: true
section {
property: 'section'
delegate: SectionHeader {
text: section
height: Theme.itemSizeExtraSmall
text: Format.formatDate(section, Formatter.DateMedium)
}
}
@ -114,22 +104,43 @@ SilicaListView {
}
onCountChanged: {
contentY = scrollOffset
console.log("CountChanged!")
//last_id_MN
loadStarted = false;
/*contentY = scrollOffset
console.log("CountChanged!")*/
}
footer: Item{
width: parent.width
height: Theme.itemSizeLarge
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: Theme.paddingSmall
anchors.bottomMargin: Theme.paddingLarge
visible: false
onClicked: {
loadData("append")
}
}
BusyIndicator {
size: BusyIndicatorSize.Small
running: loadStarted;
//anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
}
onContentYChanged: {
if (contentY > scrollOffset) {
openDrawer(false)
} else {
if (contentY < 100 && !loadStarted){
}
openDrawer(true)
}
if(contentY+height > footerItem.y && !loadStarted){
loadData("append")
loadStarted = true;
}
scrollOffset = contentY
}
VerticalScrollDecorator {}

View file

@ -6,7 +6,7 @@ BackgroundItem {
signal send (string notice)
signal navigateTo(string link)
width: parent.width
height: miniHeader.height + media.height + lblContent.height + Theme.paddingLarge + (ministatus.visible ? ministatus.height : 0) +Theme.paddingLarge
height: miniHeader.height + (attachments && attachments.count ? media.height + Theme.paddingLarge + Theme.paddingMedium: Theme.paddingLarge) + lblContent.height + Theme.paddingLarge + (ministatus.visible ? ministatus.height : 0)
MiniStatus {
id: ministatus
anchors {
@ -24,6 +24,8 @@ BackgroundItem {
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
@ -58,6 +60,8 @@ BackgroundItem {
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
}
@ -107,25 +111,37 @@ BackgroundItem {
}
text: content
textFormat: Text.StyledText
text: content.replace(new RegExp("<a ", 'g'), '<a style="text-decoration: none; color:'+Theme.highlightColor+'" ')
textFormat: Text.RichText
linkColor : Theme.highlightColor
wrapMode: Text.Wrap
font.pixelSize: Theme.fontSizeSmall
color: (pressed ? Theme.highlightColor : (highlight ? Theme.primaryColor : Theme.secondaryColor))
color: (pressed ? Theme.highlightColor : (!highlight ? Theme.primaryColor : Theme.secondaryColor))
}
Label {
MediaBlock {
id: media
anchors {
left: parent.left
leftMargin: Theme.paddingMedium
right: parent.right
rightMargin: Theme.horizontalPageMargin
left: lblContent.left
right: lblContent.right
top: lblContent.bottom
topMargin: Theme.paddingSmall
bottomMargin: Theme.paddingLarge
}
text: attachments.count + "Aaa"
model: typeof attachments !== "undefined" ? attachments : []
height: 100
Rectangle {
anchors.fill: parent
color: Theme.highlightDimmerColor
visible: status_sensitive
Image {
source: "image://theme/icon-l-attention?"+Theme.highlightColor
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: parent.visible = false;
}
}
}
@ -143,4 +159,7 @@ BackgroundItem {
type: "reply"
})
}
onPressAndHold: {
console.log(lblContent.text)
}
}

View file

@ -5,11 +5,11 @@
<name></name>
<message id="Logout">
<source></source>
<translation></translation>
<translation type="unfinished"></translation>
</message>
<message id="Login">
<source></source>
<translation></translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -122,7 +122,7 @@
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Charger davantage</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -5,11 +5,11 @@
<name></name>
<message id="Logout">
<source></source>
<translation>Uitloggen</translation>
<translation type="unfinished"></translation>
</message>
<message id="Login">
<source></source>
<translation>Inloggen</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -122,7 +122,7 @@
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Meer laden</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -5,11 +5,11 @@
<name></name>
<message id="Logout">
<source></source>
<translation></translation>
<translation type="unfinished"></translation>
</message>
<message id="Login">
<source></source>
<translation></translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>
@ -122,7 +122,7 @@
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Cargar mai</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>

View file

@ -122,7 +122,7 @@
<name>MyList</name>
<message>
<source>Load more</source>
<translation>Load more</translation>
<translation type="unfinished"></translation>
</message>
</context>
<context>