Version 0.003

This commit is contained in:
LubuWest 2017-03-25 23:36:14 +01:00
commit 10dccdcdbb
572 changed files with 3711 additions and 13631 deletions

View file

@ -0,0 +1,74 @@
import QtQuick 2.0
import Qt.labs.folderlistmodel 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle{
id:attachmentDialog
z:2
border.color: "grey"
width: parent.width-4*mm
height:parent.height-12*mm
x:2*mm
y:10*mm
property var parsedAttachments: JSON.parse(attachedobjects)
Text{
x:0.5*mm
y:0.5*mm
width: imageDialog-8*mm
elide:Text.ElideRight
text: "Attachments:"
}
BlueButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{attachmentDialog.destroy()}
}
ListView {
id: attachmentView
x:0.5*mm
y:5.5*mm
width: attachmentDialog.width-2*mm
height: attachmentDialog.height-14*mm
clip: true
spacing:0
model: attachmentModel
delegate: attachmentItem
}
ListModel{id: attachmentModel}
Component { id:attachmentItem
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 3*mm
x: mm
text:attachment.name
}
MouseArea{
anchors.fill: parent
onClicked:{
Qt.openUrlExternally(attachment.url)
}
}
}}
}
Component.onCompleted: {
for (var a in parsedAttachments){
attachmentModel.append({"attachment":parsedAttachments[a]})
}
}
}

View file

@ -0,0 +1,52 @@
// ConversationStack with buttons
import QtQuick 2.0
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle {
id:conversationStack
property var news
y:1
color: "white"
width:root.width-2*mm
height:root.height-8*mm
ListView {
id: conversationView
x:3*mm
y:8*mm
width: conversationStack.width-4*mm
height: conversationStack.height-10*mm
clip: true
spacing: 0
model: conversationModel
delegate: Newsitem{}
}
ListModel{id: conversationModel}
WorkerScript {
id: conversationWorker
source: "qrc:/js/newsworker.js"
}
BlueButton {
id: closeButton
width:10*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"// qsTr("Close")
onClicked: {
newstab.newstabstatus=login.newsViewType;
newsStack.pop()
}
}
Component.onCompleted: {
var currentTime= new Date();
var msg = {'currentTime': currentTime, 'model': conversationModel,'news':news};
conversationWorker.sendMessage(msg)
}
}

View file

@ -0,0 +1,81 @@
// List if people from Friendica Activities
import QtQuick 2.0
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle {
id:activitiesRectangle
property var activitymembers
color: "white"
border.color: "light grey"
radius:0.5*mm
width:root.width/2
height:Math.min(root.height/2,(10*mm+6*activitymembers.length*mm))
ListView {
id: contactView
x:mm
y:8*mm
width: activitiesRectangle.width-2*mm
height: activitiesRectangle.height-10*mm
clip: true
spacing: 0
model: activitiesModel
delegate: activitiesContact
}
ListModel{id: activitiesModel}
Component { id:activitiesContact
Rectangle{
border.color: "#EEEEEE"
border.width: 1
radius:0.5*mm
width:parent.width
height:6*mm
Image {
id: contactImage
x:1
y:1
width: 5*mm
height:5*mm
source:(contact.profile_image!="")? "file://"+contact.profile_image : contact.profile_image_url
onStatusChanged: if (contactImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
}
Text{
font.pixelSize: 3*mm
anchors.left: contactImage.right
anchors.margins: 1*mm
text:Qt.atob(contact.name)
}
MouseArea{
anchors.fill: parent
onClicked:{
try {root.currentIndex=1;
friendstab.active=true;
root.contactdetailsSignal(contact)
} catch(e) {Helperjs.showMessage("Error",e,root)}}
}
}}
BlueButton {
id: closeButton
//width:10*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
color:"white"
text: "\uf057"// qsTr("Close")
onClicked: {
activitiesRectangle.destroy()
}
}
Component.onCompleted: {
for (var user in activitymembers){
activitiesModel.append({"contact":activitymembers[user]})
}
}
}

View file

@ -0,0 +1,121 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
import Qt.labs.folderlistmodel 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle{
id:imageDialog
z:2
border.color: "grey"
width: parent.width-4*mm
height:parent.height-12*mm
x:2*mm
y:10*mm
property string directory: ""
Text{
id:directoryText
x:0.5*mm
y:0.5*mm
width: imageDialog.width-15*mm
height:contentHeight
wrapMode: Text.Wrap
text: directory
}
BlueButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{imageDialog.destroy()}
}
ListView {
id: imageView
x:0.5*mm
y:directoryText.height+mm
width: imageDialog.width-2*mm
height: imageDialog.height-directoryText.height-4*mm
clip: true
model: imageModel
delegate: imageItem
}
FolderListModel{
id: imageModel
nameFilters: ["*.png", "*.jpg",".jpeg","*.JPG"]
sortField: FolderListModel.Time
sortReversed:false
showDotAndDotDot: true
showDirs: true
showDirsFirst: true
folder:directory
}
BusyIndicator{
id: imageBusy
anchors.horizontalCenter: imageView.horizontalCenter
anchors.top:imageView.top
anchors.topMargin: 2*mm
width:10*mm
height: 10*mm
running:false
}
Component{
id:imageItem
Item{
width:imageView.width
height:folderImage.height+2*mm
Rectangle{
id:imagetextRectangle
color:"black"
x:mm
z:3
opacity: fileIsDir?0:0.5
width:imagetext.contentWidth
height: imagetext.contentHeight
anchors.bottom: folderImage.bottom
}
Text {
id:imagetext
x:fileIsDir?11*mm:mm
z:4
text: fileName
width: fileIsDir?parent.width - 12*mm :imageView.width-mm
anchors.bottom: folderImage.bottom
color: fileIsDir?"black":"white"
font.pixelSize: 3*mm
wrapMode:Text.Wrap
}
Image{id:folderImage
width: fileIsDir?10*mm: imageView.width-mm
fillMode:Image.PreserveAspectFit
source:fileIsDir?"qrc:/images/folder-blue.png":fileURL
}
MouseArea{
anchors.fill: parent
onClicked:{
if (fileName==".."){
imageModel.folder=imageModel.parentFolder;
directory=imageModel.parentFolder
}
else if (fileIsDir){
imageModel.folder=fileURL;
directory=fileURL
}
else{
attachImageURL=fileURL;
imageDialog.destroy()
}
}
}
}
}
}

View file

@ -0,0 +1,199 @@
// message.qml
// message with buttons
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/smiley.js" as Smileyjs
import "qrc:/qml/genericqml"
Flickable{
width:root.width-5*mm
height:root.height-12*mm
contentHeight: messageColumn.height
boundsBehavior: Flickable.StopAtBounds
id:messageSend
property string parentId: ""
property string reply_to_user:""
property string attachImageURL: "";
property int directmessage: 0;
property var contacts: []
property var groups: []
property var contact_allow:login.permissions[0]
property var contact_deny:login.permissions[1]
property var group_allow:login.permissions[2]
property var group_deny:login.permissions[3]
onAttachImageURLChanged: {if(attachImageURL!=""){
var imageAttachmentObject=Qt.createQmlObject('import QtQuick 2.0; Image {id:imageAttachment; source:"'+
attachImageURL.toString()+'"; width: 15*mm; height: 15*mm;fillMode: Image.PreserveAspectFit;MouseArea{anchors.fill:parent;onClicked:{attachImageURL="";imageAttachment.destroy()}}}',messageColumn,"attachedImage");
console.log("You chose: " + attachImageURL)
}}
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
xhr.url= login.server + "/api/statuses/update.json";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.clearParams();
xhr.setParam("source", "Friendiqa");
xhr.setParam("status", status);
if (parentId!="") {xhr.setParam("in_reply_to_status_id", parentId)};
if (title!=="") {xhr.setParam("title", title)};
if (group_allow.length>0) {xhr.setParam("group_allow", Helperjs.cleanArray(group_allow))};
if (group_deny.length>0) {xhr.setParam("group_deny", Helperjs.cleanArray(group_deny))};
if (contact_allow.length>0) {xhr.setParam("contact_allow", Helperjs.cleanArray(contact_allow))};
if (contact_deny.length>0) {xhr.setParam("contact_deny", Helperjs.cleanArray(contact_deny))};
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
xhr.post();
}
function dmUpdate(title,text,replyto,screen_name,attachImageURL) {
xhr.url= login.server + "/api/direct_messages/new.json";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.clearParams();
xhr.setParam("text", text);
xhr.setParam("screen_name", screen_name);
if (parentId!="") {xhr.setParam("replyto", replyto)};
if (title!=="") {xhr.setParam("title", title)};
xhr.post();
}
Column {
id:messageColumn
spacing: 2
width: parent.width
TextField {
id: titleField
width: parent.width
placeholderText: qsTr("Title (optional)")
visible: messageSend.parentId === ""
}
TextArea {
id: bodyField
width: parent.width
height: 30*mm
wrapMode: TextEdit.Wrap
textFormat: TextEdit.PlainText
}
Row{
spacing: 2
CheckBox{
id:dmCheckbox
text:"DM"
enabled: false
checked: (directmessage==1)?true:false
onClicked:{
if(dmCheckbox.checkedState==Qt.Checked){directmessage=1}
else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0}
}
}
BlueButton{
text:"\uf0c1"
onClicked: {
if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)}
else{urlTextEdit.text="";
urlRectangle.visible=true}}
}
Rectangle{
id:urlRectangle
height:parent.height
width:37*mm
visible:false
TextField{
id:urlTextEdit
width:30*mm
height:parent.height
}
BlueButton{
anchors.left:urlTextEdit.right
anchors.leftMargin:mm
text:"\u2713"
onClicked: {if(urlTextEdit.text!=""){
var start = bodyField.selectionStart;
var end = bodyField.selectionEnd;
var text = bodyField.getText(start,end);
text = "[url="+urlTextEdit.text+"]" + text + "[/url]";
bodyField.remove(start,end);
bodyField.insert(start,text);}
urlRectangle.visible=false}
}
}
}
Row{
spacing:2
BlueButton{id:permButton
visible: (directmessage==1)?false:true
text: ((contact_allow.length==0)&&(contact_deny.length==0)&&(group_allow.length==0)&&(group_deny.length==0))?"\uf09c":"\uf023"//qsTr("Permissions")
onClicked: {
var component = Qt.createComponent("qrc:/qml/newsqml/PermissionDialog.qml");
var permissions = component.createObject(messageColumn);
}}
BlueButton {
id: attachButton
text: "\uf0c6"
visible:(directmessage==0)
onClicked: {
if (attachImageURL!=""){
Helperjs.showMessage( qsTr("Error"),qsTr("Only one attachment. Remove other attachment first!"), messageColumn)}
else{print(filesystem.homePath);
var defaultDirectory="file://"+osSettings.attachImageDir;//"file:///storage/emif.open()
print(defaultDirectory);
var component = Qt.createComponent("qrc:/qml/newsqml/ImageDialog.qml");
var imagedialog = component.createObject(messageSend,{"directory": defaultDirectory});
}
}
}
BlueButton{
id:contactButton
text:"\uf234"
visible:(directmessage==0)
onClicked:{
var contactitems="";
for (var i=0;i<contacts.length;i++){
if(contacts[i].network=="dfrn"){
if(Helperjs.getCount(db,login,"contacts","screen_name",contacts[i].screen_name)>1){
contacts[i].screen_name=contacts[i].screen_name+"+"+contacts[i].cid
}
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"';iconSource:'"+contacts[i].profile_image+"'; onTriggered: bodyField.insert(0,' @"+contacts[i].screen_name+"+"+contacts[i].cid+" ')}"
}}
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput")
contactlistObject.popup() }
}
BlueButton{
id:smileyButton
text: "\uf118"
onClicked: {
var smileyarray=Smileyjs.smileys
//print(JSON.stringify(smileyarray[0]))
var component = Qt.createComponent("qrc:/qml/newsqml/SmileyDialog.qml");
var smileydialog = component.createObject(messageColumn)
}}
BlueButton {
id: cancelButton
text: "\uf057"
onClicked: {newstab.newstabstatus=login.newsViewType;
newsStack.pop()}
}
BlueButton {
id: sendButton
text: "\uf1d9"
onClicked: {
var title=titleField.text.replace("\"","\'");
var body=bodyField.getText(0,bodyField.length);
if (directmessage==0){
statusUpdate(title,body,messageSend.parentId,attachImageURL.toString())}
else {dmUpdate(title,body,"",messageSend.reply_to_user) }
newstab.newstabstatus=login.newsViewType; newsStack.pop()
}
}
}
}
}

View file

@ -0,0 +1,362 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
import "qrc:/qml/genericqml"
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/service.js" as Service
Item {
Connections{
target:newstab
onNewstabstatusChanged:{
newstabstatusButton.text= qsTr(newstab.newstabstatus)
}
}
Connections{
target:newstab
onConversationChanged:{
newsBusy.running=false;
newstab.newstabstatus="Conversation";
//newsStack.push({item:"qrc:/qml/newsqml/Conversation.qml",properties:{"news": conversation}})
showNews(conversation);
}
}
Connections{
target:root
onCurrentContactChanged:{
if (root.newContacts.length>0){
if(root.currentContact<root.newContacts.length){
downloadNotice.text= qsTr("Download profile image for ")+ root.newContacts[root.currentContact].name;
print(root.newContacts[root.currentContact].name)
}
}else{downloadNotice.text=""}
}
}
Connections{
target:xhr
onError:{if (data=="contact"){downloadNotice.text=root.newContacts[root.currentContact].name+"... Error!"}}
onSuccess:{replytimer.start() //wait 1 second to load new timeline
}
}
Timer {id:replytimer; interval: 1000; running: false; repeat: false
onTriggered: {if(newstab.newstabstatus=="Conversation"){
showConversation(newsStack.timelineIndex-1,newsModel.get(0).newsitemobject)} else{
var onlynew=true;
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(rns,rnc){
root.contactLoadType="news";
root.news=rns;root.newContacts=rnc;root.currentContact=0})
}}
}
function showNews(newsToShow){
try{if (newsStack.depth>1){newsStack.pop()}}catch(e){}
newsBusy.running=false;
var currentTime= new Date();
downloadNotice.text="";
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow};
newsWorker.sendMessage(msg);
}
function showConversation(timelineIndex,newsitemobject){
newsBusy.running=true;
root.contactLoadType="conversation";
newsStack.timelineIndex= timelineIndex;
if(newsitemobject.messagetype==0){
Newsjs.requestConversation(root.login,db,newsitemobject.status_id,root.contactlist,root,function(ns,nc){
root.news=ns;root.newContacts=nc;root.currentContact=0;
})}
else{Newsjs.conversationfromdb(root.db,root.login.username,newsitemobject.statusnet_conversation_id, function(newsarray){
root.news=newsarray;root.newContacts=[];root.currentContact=1;
})}
}
function onFriendsMessages(friend){
newstab.newstabstatus="Contact"
Newsjs.newsfromdb(db,root.login.username, function(dbnews){showNews(dbnews)},friend)
}
function onDirectMessage(friend){
newstab.newstabstatus="SendMessage"
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": friend,"directmessage":1,"login":root.login}});
}
StackView{
id: newsStack
anchors.fill:parent
property int timelineIndex: 0
onTimelineIndexChanged:print("timelineindex:"+ timelineIndex)
initialItem:Rectangle {
y:1
color: "white"
width:root.width-2*mm
height:root.height-8*mm
BlueButton{
id:newstabstatusButton
anchors.top: parent.top
anchors.topMargin: 0.5*mm
text: qsTr(newstab.newstabstatus)
onClicked: {newstabmenu.popup()}
}
Row{
spacing: mm
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right: parent.right
BlueButton {
id: newMessageButton
width:10*mm
text: "\uf040"
onClicked: {
var groups=[];
Helperjs.readData(root.db,"groups",root.login.username,function(groupobject){
groups=groupobject});
newstab.newstabstatus="SendMessage";
Helperjs.readData(root.db,"contacts",root.login.username,function(friends){
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"contacts": friends,"login":root.login}})
},"isFriend",1);
}
}
BlueButton {
id: quitButton
width:10*mm
text: "\uf08b"
onClicked: {Service.cleanNews(root.db,function(){Qt.quit() })}
}
BlueButton {
id: update
text: "\uf021"
onClicked: {
newsBusy.running=true;
newstab.newstabstatus=login.newsViewType;
root.contactLoadType="news";
var onlynew=true;
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(ns,nc){
root.news=ns;root.newContacts=nc;root.currentContact=0;
if (ns.length==0){// update last 20 existing news for changes and likes
onlynew=false;
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(rns,rnc){
root.contactLoadType="news";
root.news=rns;root.newContacts=rnc;root.currentContact=0})
}
})
}
}
}
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:newsView.width
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var currentTime= new Date();
if(newstab.newstabstatus=="Timeline"){
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},false,lastnews_id)}
if(newstab.newstabstatus=="Tree"){
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
Newsjs.chatsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},lastnews_id)}
else if(newstab.newstabstatus=="Contact"){
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
newsWorker.sendMessage(msg);
},newsModel.get(newsModel.count-1).newsitemobject.uid,newsModel.get(newsModel.count-1).newsitemobject.created_at)}
}}
}
}
Component { id:footerReply
Rectangle{
border.color: "#EEEEEE"
border.width: 1
color:"lightgrey"
width:newsView.width
height:Math.max(replyText.contentHeight+2*mm,6*mm)
Rectangle{
color: "white"
radius:0.5*mm
anchors.left: parent.left
anchors.leftMargin:mm
anchors.top:parent.top
anchors.topMargin: 0.5*mm
width:parent.width-12*mm
height:Math.max( replyText.contentHeight,5*mm)
TextInput {
id: replyText
font.pixelSize: 3*mm
wrapMode: Text.Wrap
//width: parent.width
anchors.fill: parent
selectByMouse: true
}
}
BlueButton {
id: sendButton
text: "\uf1d9"
anchors.right: parent.right
anchors.rightMargin:mm
anchors.top:parent.top
anchors.topMargin: 0.5*mm
color:"white"
onClicked: { try{
var body=replyText.getText(0,replyText.length);
newsBusy.running=true;
replyText.text=""
xhr.clearParams();
xhr.setLogin(login.username+":"+Qt.atob(login.password));
if (newsModel.get(0).newsitemobject.messagetype==0){
xhr.setParam("source", "Friendiqa");
xhr.url= login.server + "/api/statuses/update.json";
xhr.setParam("status", body);
xhr.setParam("in_reply_to_status_id", newsModel.get(newsModel.count-1).newsitemobject.status_id)}
else {xhr.url= login.server + "/api/direct_messages/new.json";
xhr.setParam("text", body);
xhr.setParam("screen_name",newsModel.get(newsModel.count-1).newsitemobject.screen_name);
xhr.setParam("replyto", newsModel.get(newsModel.count-1).newsitemobject.status_id)
}
xhr.post();
//replyText.text=""
} catch(e){Helperjs.showMessage("Error",e.toString(),root)}
}
}
}
}
ListView {
id: newsView
anchors.fill: parent
anchors.topMargin: 8*root.mm
anchors.leftMargin: 3*root.mm; anchors.rightMargin: root.mm
anchors.bottomMargin: 1*root.mm
clip: true
spacing: 0
footer: (newstab.newstabstatus=="Conversation")?footerReply:footerComponent
model: newsModel
delegate: Newsitem{}
Component.onCompleted: {//print(newstab.newstabstatus);
if(newstab.newstabstatus!="Conversation"){
positionViewAtIndex(newsStack.timelineIndex-1, ListView.Beginning)}
else {positionViewAtBeginning();
newsStack.timelineIndex=0
}}
}
ListModel{id: newsModel}
WorkerScript {
id: newsWorker
source: "qrc:/js/newsworker.js"
}
BusyIndicator{
id: newsBusy
anchors.horizontalCenter: newsView.horizontalCenter
anchors.top:newsView.top
anchors.topMargin: 2*mm
width:10*mm
height: 10*mm
}
Rectangle{
id:downloadNotice
property alias text: noticeText.text
color:"white"
border.color:"grey"
z:1
anchors.horizontalCenter: newsView.horizontalCenter
anchors.bottom:newsView.bottom
anchors.bottomMargin: 2*mm
width: noticeText.width+2*mm
height: noticeText.height+2*mm
visible: (downloadNotice.text!="")
Text{
id:noticeText
color: "grey"
anchors.centerIn: parent
width: contentWidth
height: contentHeight
font.pixelSize: 2*mm
text:""
}
}
Menu {
id:newstabmenu
MenuItem {
text: qsTr("Timeline")
onTriggered: {
newstab.newstabstatus="Timeline";
newsModel.clear();
try{ Newsjs.newsfromdb(root.db,root.login.username, function(dbnews){
showNews(dbnews)
})}catch(e){Helperjs.showMessage("Error",e,root)}}
}
MenuItem {
text: qsTr("Favorites")
onTriggered:{
newstab.newstabstatus="Favorites";
root.contactLoadType="favorites";
newsBusy.running=true;
Newsjs.requestFavorites(root.login,db,root.contactlist,root,function(ns,nc){
root.news=ns; root.newContacts=nc;root.currentContact=0;
})
}
}
MenuItem {
text: qsTr("Tree")
onTriggered:{
newsModel.clear();
newstab.newstabstatus="Tree";
Newsjs.chatsfromdb(db,root.login.username,function(news){showNews(news)})
}
}
MenuItem {
text: qsTr("Notifications")
onTriggered:{
newstab.newstabstatus="Notifications";
newsBusy.running=true;
Newsjs.getNotifications(root.login,db,root,function(news){
showNews(news)}
)}
}
}
Component.onCompleted: {
root.messageSignal.connect(onFriendsMessages);
root.directmessageSignal.connect(onDirectMessage);
root.newsSignal.connect(showNews);
try{newsModel.clear()} catch(e){}
newstab.newstabstatus=login.newsViewType;
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
else{Newsjs.chatsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
}
}
}
}

View file

@ -0,0 +1,355 @@
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
Item {
id: newsitem
width: newsView.width
height:Math.max((itemMessage.height+topFlow.height+friendicaActivities.height+4*mm),profileImage.height+user_name.height+mm)
property string attending: ""
onAttendingChanged: {attendLabel.visible=true;
attendLabel.text= qsTr("attending: ")+ qsTr(attending)}
signal replyto(string parent_id)
function showActivityContacts(contacts){
var component = Qt.createComponent("qrc:/qml/newsqml/FriendicaActivities.qml");
var imagedialog = component.createObject(friendicaActivities,{"activitymembers": contacts});
}
Rectangle{width:newsitem.width; height: 1; anchors.bottom: newsitem.bottom; color:"light grey"}
Rectangle{
width:newsitem.width
height:newsitem.height-1
color: (newsitemobject.messagetype==1)?"#ffe6e6" : "white"
Column {
id: authorcolumn
width: 8*mm
Image {
id:profileImage
source: (newsitemobject.user.profile_image!="")? "file://"+newsitemobject.user.profile_image : newsitemobject.user.profile_image_url
x:1
width: 7*mm
height: 7*mm
MouseArea{
anchors.fill: parent
onClicked:{print(root.currentIndex);
try{root.currentIndex=1;
friendstab.active=true;
root.contactdetailsSignal(newsitemobject.user)} catch (e){Helperjs.showMessage("Error",e,root)}
}
}
onStatusChanged: if (profileImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
}
Label {
id:user_name
color: "grey"
width:parent.width
font.pixelSize: 1.5*mm
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: Qt.atob(newsitemobject.user.name)//+forumname
}
}
Column {
id:newscolumn
width: newsitem.width-8*mm
anchors.left: authorcolumn.right
Flow{
id:topFlow
spacing: mm
width:parent.width
Label {
id:messageTypeLabel
color: "grey"
text: if (newsitemobject.messagetype==0){qsTr("Source: ")+newsitemobject.source
} else if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else {" Notification"}
font.pixelSize: 1.5*mm
}
Label {
id:createdAtLabel
color: "grey"
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: dateDiff
}
Label {
id:replytoLabel
color: "grey"
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: try {qsTr("In reply to ")+newsitemobject.reply_user.screen_name
}catch(e){" "}
}
Label {
id:newscountLabel
visible:((newstabstatus=="Tree")&&(newsitemobject.newscount>1))?true:false
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
font.bold: true
horizontalAlignment: Label.AlignRight
text: try {(newsitemobject.newscount-1)+qsTr(" comments") }catch(e){" "}
MouseArea{
anchors.fill:parent
onClicked: {conversationsymbol.color="black";showConversation(index,newsitemobject)}
}
}
}
Text {
color: "#404040"
linkColor: "light green"
id: itemMessage
textFormat: Text.RichText
text:Qt.atob(newsitemobject.statusnet_html)
width: newsitem.width-8*mm-2
height: implicitHeight
wrapMode: Text.Wrap
onLinkActivated:{
Qt.openUrlExternally(link)}
}
Flow{
id:friendicaActivities
width:parent.width
spacing:mm
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.likeText
MouseArea{
anchors.fill: parent
onClicked: { showActivityContacts(newsitemobject.like)}
}
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.dislikeText
MouseArea{
anchors.fill: parent
onClicked: { showActivityContacts(newsitemobject.dislike)}
}
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendyesText
MouseArea{
anchors.fill: parent
onClicked: { showActivityContacts(newsitemobject.attendyes)}
}}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendnoText
MouseArea{
anchors.fill: parent
onClicked: { showActivityContacts(newsitemobject.attendno)}
}
}
Label{color: "grey"
font.pixelSize: 1.5*mm
text: friendica_activities.attendmaybeText
MouseArea{
anchors.fill: parent
onClicked: { showActivityContacts(newsitemobject.attendmaybe)}
}
}
}
Row{
CheckBox{
id:likeCheckbox
height:3*mm
width:8*mm
visible: (newsitemobject.messagetype==0)? true:false
checked:(friendica_activities.self.liked==1)?true:false
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 6*mm
implicitHeight: 3*mm
color:"white"
}
indicator: Rectangle{
implicitWidth: 3*mm
implicitHeight:3*mm
color:control.checked?"yellow":"white"
x: 4*mm
Text{
anchors.centerIn: parent
font.pixelSize: 2.5*mm
font.family:fontAwesome.name
color:control.checked?"black": "grey"
text:"\uf118"
}}
}
onClicked: {
if(likeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"like",newsitemobject.status_id,root);dislikeCheckbox.checked=false; model.friendica_activities.self.liked=0 }
else{Newsjs.like(root.login,root.db,0,"like",newsitemobject.status_id,root); model.friendica_activities.self.liked=1}}
}
CheckBox{
id: dislikeCheckbox
height:3*mm
width:8*mm
visible: (newsitemobject.messagetype==0)? true:false
checked: (friendica_activities.self.disliked==1)?true:false
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 6*mm
implicitHeight:3*mm
color:"white"
}
indicator: Rectangle{
implicitWidth: 3*mm
implicitHeight:3*mm
color:control.checked?"yellow":"white"
x:4*mm
Text{
anchors.centerIn: parent
font.pixelSize: 2.5*mm
font.family:fontAwesome.name
color:control.checked?"black": "grey"
text: "\uf119"
}}
}
onClicked: {
if (dislikeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"dislike",newsitemobject.status_id,root);likeCheckbox.checked=false; model.friendica_activities.self.disliked=0}
else {Newsjs.like(root.login,root.db,0,"dislike",newsitemobject.status_id,root); model.friendica_activities.self.disliked=1}}
}
CheckBox {
id:favoritedCheckbox
visible:(newsitemobject.messagetype==0)
width: 7*mm
style: CheckBoxStyle {
background: Rectangle {
implicitWidth: 6*mm
implicitHeight:3*mm
color:"transparent"
}
indicator:Rectangle{
x:3*mm
width: 3*mm
implicitHeight:3*mm
Text{
color: control.checked?"black":"grey"
font.pixelSize: 2.5*mm
text:"\uf005"
}}
}
checked:(newsitemobject.favorited>0)
onClicked:{
if(favoritedCheckbox.checkedState==Qt.Checked){
Newsjs.favorite(login,true,newsitemobject.status_id,root); model.newsitemobject.favorited=1}
else if(favoritedCheckbox.checkedState==Qt.Unchecked){
Newsjs.favorite(login,false,newsitemobject.status_id,root);model.newsitemobject.favorited=0}
}
}
Rectangle{
width: 7*mm
height: 3*mm
color:"transparent"
Text{
id:newsmenusymbol
color: "grey"
anchors.centerIn: parent
font.pixelSize: 2*mm
font.bold: true
text: "\u22EE"
}
MouseArea{
anchors.fill:parent
onClicked: {newsmenu.popup()}}
}
Rectangle{
width: 7*mm
height: 3*mm
visible:newstab.newstabstatus!="Conversation"
color:"transparent"
Text{
id:conversationsymbol
color: "grey"
anchors.centerIn: parent
font.pixelSize: 2.5*mm
font.family: fontAwesome.name
text: "\uf086"
}
MouseArea{
anchors.fill:parent
onClicked: { conversationsymbol.color="black";showConversation(index,newsitemobject)}
}
}
Label{
id:attendLabel
//visible: false
color: "grey"
height:3.5*mm
font.pixelSize: 1.5*mm
horizontalAlignment: Label.AlignRight
text: (friendica_activities.self.attending)?(qsTr("Attending: ")+ qsTr(friendica_activities.self.attending)):""
}
}
}
Menu {
id:newsmenu
MenuItem {
text: qsTr("Reply")
onTriggered: {
var directmessage=0;
if (newsitemobject.messagetype==1){ directmessage=1}
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.status_id,"login":root.login,"directmessage":directmessage}});
}
}
MenuItem {
text: qsTr("DM")
onTriggered: {
root.directmessageSignal(newsitemobject.user.screen_name);
}
}
MenuItem {
text: qsTr("Repost")
onTriggered: {
Newsjs.retweetNews(root.login,db,newsitemobject.status_id,root,function(reply){
print(reply)})
}
}
MenuItem {
text: qsTr("Conversation")
onTriggered: showConversation(index,newsitemobject)
}
Menu{
title: qsTr("Attending")
MenuItem{
text:qsTr("yes")
onTriggered: {Newsjs.attend(root.login,db,"yes",newsitemobject.status_id,root,function(){
model.friendica_activities.self.attending="yes";attending="yes"})
}
}
MenuItem{text:qsTr("maybe")
onTriggered: {Newsjs.attend(root.login,db,"maybe",newsitemobject.status_id,root,function(){
model.friendica_activities.self.attending="maybe";attending="maybe"})
}
}
MenuItem{text:qsTr("no")
onTriggered: {Newsjs.attend(root.login,db,"no",newsitemobject.status_id,root,function(){
model.friendica_activities.self.attending="no";attending="no"})}
}
}
MenuItem {
text: qsTr("Delete")
onTriggered: {
Newsjs.deleteNews(root.login,root.db,newsitemobject.status_id,newsitemobject.messagetype,root,function(reply){
newsModel.remove(index)})
}
}
}
}
}

View file

@ -0,0 +1,189 @@
import QtQuick 2.0
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle{
id:permissionDialog
x: mm
width: messageColumn.width-5*mm
height:root.height/3
function updatePerms(){
for (var i=0;i<groupModel.count;i++)
{if (groupModel.get(i).groupstatus=="positive"){
group_allow.push(groupModel.get(i).group.gid)
}
if (groupModel.get(i).groupstatus=="negative"){
group_deny.push(groupModel.get(i).group.gid)
}
}
for (var j=0;j<contactModel.count;j++){
if (contactModel.get(j).contactstatus=="positive"){
contact_allow.push(contactModel.get(j).contact.cid)
}
if (contactModel.get(j).contactstatus=="negative"){
contact_deny.push(contactModel.get(j).contact.cid)
}
if ((contact_allow.length==0)&&(contact_deny.length==0)&&(group_allow.length==0)&&(group_deny.length==0))
{permButton.text="\uf09c"}
else{permButton.text="\uf023"}
}}
Text{
x:0.5*mm
y:0.5*mm
text: "Contacts"
}
ListView {
id: contactView
x:0.5*mm
y:5.5*mm
width: permissionDialog.width/2-2*mm
height: permissionDialog.height-14*mm
clip: true
spacing: 1
model: contactModel
delegate: contactItem
}
ListModel{id: contactModel}
Component{
id:contactItem
Rectangle{
id:contactitemRect
width:contactView.width
height: 5*mm
radius: 0.5*mm
property string contactstatus
onContactstatusChanged:{
if(contactstatus=="positive"){contactitemRect.color="light green"}
else if (contactstatus=="negative"){contactitemRect.color= "ffe6e6"}
else{contactitemRect.color= "white"}}
color: "white"
border.color:"grey"
Text{
color:"grey"
text:contact.screen_name
}
MouseArea{
anchors.fill: parent
onClicked:{
if(contactModel.get(index).contactstatus=="neutral"){
contactModel.set(index,{"contactstatus":"positive"});
contactstatus="positive"
}
else if (contactModel.get(index).contactstatus=="positive"){
contactModel.set(index,{"contactstatus":"negative"})
contactstatus="negative"
}
else{contactModel.set(index,{"contactstatus":"neutral"});
contactstatus="neutral";
}
}}
Component.onCompleted:{
if (contactModel.get(index).contactstatus=="positive"){
contactstatus="positive"
}
else if (contactModel.get(index).contactstatus=="negative"){
contactstatus="negative"
}
else {contactstatus="neutral"} }
}
}
Text{
x:contactView.width+2*mm
y:0.5*mm
text: "Groups"
}
ListView {
id: groupView
x:contactView.width+2*mm
y:5.5*mm
width: permissionDialog.width/2-2*mm
height: permissionDialog.height-14*mm
clip: true
spacing: 1
model: groupModel
delegate: groupItem
}
ListModel{id: groupModel}
Component{
id:groupItem
Rectangle{
id:groupitemRect
width:groupView.width
radius: 0.5*mm
height: 5*mm
property string groupstatus:"neutral"
onGroupstatusChanged:
{if(groupstatus=="positive"){groupitemRect.color="light green"}
else if (groupstatus=="negative"){groupitemRect.color= "#ffe6e6"}
else{groupitemRect.color= "white"}}
color: "white"
border.color:"grey"
Text{
color:"grey"
text:group.groupname
}
MouseArea{
anchors.fill: parent
onClicked:{
if(groupModel.get(index).groupstatus=="neutral"){
groupModel.set(index,{"groupstatus":"positive"});
groupstatus="positive"}
else if (groupModel.get(index).groupstatus=="positive"){
groupModel.set(index,{"groupstatus":"negative"});
groupstatus="negative"}
else{groupModel.set(index,{"groupstatus":"neutral"})
groupstatus="neutral"}
}}
Component.onCompleted:{ if (groupModel.get(index).groupstatus=="positive"){
groupstatus="positive"
}
else if (groupModel.get(index).groupstatus=="negative"){
groupstatus="negative"
}
else {groupstatus="neutral"} }
}
}
BlueButton{
x:0.5*mm
anchors.bottom: parent.bottom
anchors.bottomMargin:1
text:"\uf0c7"
onClicked:{
updatePerms();
var perms=[];
perms.push(contact_allow,contact_deny,group_allow,group_deny);
Service.savePermissions(db,perms)
}
}
BlueButton{
x:contactView.width+2*mm
anchors.bottom: parent.bottom
anchors.bottomMargin:1
text:"\u2713"
onClicked:{updatePerms();
permissionDialog.destroy();
}
}
Component.onCompleted:{
Helperjs.readData(db,"contacts",login.username,function(contacts){
for (var name in contacts){
var contactstatus="neutral";
if (contact_allow.indexOf(contacts[name].cid)>-1){contactstatus="positive";print(contacts[name].cid+" pos")}
else if (contact_deny.indexOf(contacts[name].cid)>-1){contactstatus="negative"}
contactModel.append({"contact":contacts[name],"contactstatus":contactstatus})
}},"isFriend",1);
Helperjs.readData(db,"groups",login.username,function(owngroups){
for (var number in owngroups){
var groupstatus= "neutral";
if (group_allow.indexOf(owngroups[number].gid)>-1){groupstatus="positive"}
else if (group_deny.indexOf(owngroups[number].gid)>-1){groupstatus="negative"}
groupModel.append({"group":owngroups[number],"groupstatus":groupstatus})
}});
}
}

View file

@ -0,0 +1,142 @@
import QtQuick 2.7
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import "qrc:/js/smiley.js" as Smileyjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle{
id:smileyDialog
x: mm
width: messageColumn.width-5*mm
height:root.height/3
BlueButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{smileyDialog.destroy()}
}
TabView{
id:smileyTabView
tabPosition: Qt.BottomEdge
anchors.top: closeButton.bottom
anchors.topMargin: 1*mm
width: smileyDialog.width-2*mm
height: smileyDialog.height-7*mm
currentIndex: 0
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: "white"
implicitWidth: smileyTabView.width/3-2*mm
implicitHeight: 4*mm
Text { id: text
anchors.centerIn: parent
text: styleData.title
color: "dark grey"
font.pixelSize:2.5*mm
font.bold: styleData.selected
}
}
frame: Rectangle { color: "light grey" }
tabsAlignment:Qt.AlignHCenter
}
Tab{
title: qsTr("Standard")
Rectangle{
id: coreGridTab
GridView {
id: coreSmileyView
anchors.fill: parent
cellWidth: 5*mm
cellHeight: 5*mm
clip: true
model: coreSmileyModel
delegate: smileyItem
}
ListModel{
id: coreSmileyModel
}
Component.onCompleted:{
var smileyarray=Smileyjs.core
for (var icon in smileyarray){
coreSmileyModel.append({"emoji":smileyarray[icon]})
}
}
}
}
Tab{
title: qsTr("Addon")
Rectangle{
id: addonGridTab
GridView {
id: addonView
anchors.fill: parent
cellWidth: 5*mm
cellHeight: 5*mm
clip: true
model: addonModel
delegate: smileyItem
}
ListModel{
id: addonModel
}
Component.onCompleted:{
for (var icon in Smileyjs.addon){
addonModel.append({"emoji":Smileyjs.addon[icon]})
}
}
}
}
Tab{
title: qsTr("Adult")
Rectangle{
id: adultGridTab
GridView {
id: adultView
anchors.fill: parent
cellWidth: 5*mm
cellHeight: 5*mm
clip: true
model: adultModel
delegate: smileyItem
}
ListModel{
id: adultModel
}
Component.onCompleted:{
for (var icon in Smileyjs.adult){
adultModel.append({"emoji":Smileyjs.adult[icon]})
}
}
}
}
}
Component{
id:smileyItem
AnimatedImage{id:smileyImage
width:4.5*mm
height: 4.5*mm
fillMode:Image.PreserveAspectFit
source:emoji.url
MouseArea{
anchors.fill: parent
onClicked:{
bodyField.append(emoji.name+" ")
smileyDialog.destroy()
}
}
}
}
}