harbour-tooter/qml/pages/Conversation.qml

578 lines
24 KiB
QML
Raw Normal View History

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