~nicohman/signal-rs

65a31f5a1c4562d1f216e9fef2048f50bddb4fe3 — nicohman 6 months ago 21d519d
More Krigami conversion and image overlay
M qml/ChatHistory.qml => qml/ChatHistory.qml +15 -24
@@ 2,14 2,13 @@ import QtQuick 2.0
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15
import QtQuick.Dialogs 1.3
import org.kde.kirigami 2.13 as Kirigami

Page {
Kirigami.ScrollablePage {
    //anchors.fill: stackView
    id: chatHistory
    property var msgImgComponent: Qt.createComponent(Qt.resolvedUrl("MessageImage.qml"))
    objectName: "chatHistory"
    background:Rectangle {
        color: theme.background
    }
    title: signalState.currentName
    function sendMessage() {
        console.log("Sending "+ msgTextInput.text +" to "+signalState.current);


@@ 38,9 37,8 @@ Page {
        }
        }
    }
    ColumnLayout {
        anchors.fill: parent
        ListView {
            ListView {
                anchors.fill: parent
            Layout.topMargin: 10
            highlight: Rectangle {
                color: "transparent"


@@ 51,9 49,8 @@ Page {
            id: chatView
            x: 0
            y: 0
            //anchors.left: parent.left
            Layout.fillWidth: true
            Layout.maximumHeight:window.height - window.header.height - sendButton.height - msgTextInput.height
            //Layout.maximumHeight:window.height - window.header.height - sendButton.height - msgTextInput.height
            Layout.fillHeight: true
            Layout.rightMargin: 5
            delegate:


@@ 63,11 60,13 @@ Page {
                }
            model: signal.messages
        }
        Row {

    footer:         Row {
            Layout.fillWidth: true
            TextField {
                placeholderText: "Write a message"
                id: msgTextInput
                width: parent.width - addAttachmentButton.width
                width: parent.width - addAttachmentButton.width - sendButton.width
                onAccepted: {
                    chatHistory.sendMessage();
                }


@@ 80,23 79,15 @@ Page {
                    fd.visible = true;
                }
            }
        }
        Row {
            Layout.fillWidth: true
            Button {
                background: Rectangle {
                    color:theme.button
                }
                width: parent.width
                id: sendButton
                contentItem: Text {
                    color: theme.text
                }
                text: "Send Message"
                onClicked: {
                icon.name: "document-send"
                display:AbstractButton.IconOnly
               action: Kirigami.Action {
                onTriggered: {
                    chatHistory.sendMessage();
                }
               }
            }
        }
    }
}

M qml/ChatList.qml => qml/ChatList.qml +8 -5
@@ 2,16 2,19 @@ import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Controls.Material 2.12
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami

Page {
    anchors.fill: stackView
Kirigami.ScrollablePage {
    title: qsTr("Chats")
    objectName: "chats"
    property string avatar: ""
    background:Rectangle {
        color: theme.background
    actions.main: Kirigami.Action {
        id: addChatAction
        icon.name: "list-add"
        text: "Create Chat"
        onTriggered: signalState.openView("createChat");
    }

    
    ListView {
        id: chatView
        anchors.fill: parent

M qml/CreateChat.qml => qml/CreateChat.qml +3 -5
@@ 1,12 1,10 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15
Page {
	background: Rectangle {
		color: theme.background
	}
import org.kde.kirigami 2.13 as Kirigami

Kirigami.Page {
	title: "Create Chat"
	anchors.fill: stackView
	ColumnLayout {
		anchors.leftMargin: 10
		anchors.fill: parent

M qml/CreateContact.qml => qml/CreateContact.qml +2 -6
@@ 1,14 1,10 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami

Page {
    anchors.fill: stackView
    background: Rectangle {
        color: theme.background
    }
Kirigami.Page {
    title: "Create a New Contact"

    ColumnLayout {
        x: 20
        y: 10

M qml/EditContact.qml => qml/EditContact.qml +2 -5
@@ 1,17 1,14 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami

Page {
Kirigami.Page {
	id: editContact
	anchors.fill: stackView
	title: qsTr("Edit Contact")
	property string contactName: ""
	property string contactTel: ""
	property string currentTel: ""
	background: Rectangle {
		color: theme.background
	}
	Component.onCompleted: {
		editContact.contactTel = signalState.current;
        editContact.currentTel = signalState.current;

A qml/MessageImage.qml => qml/MessageImage.qml +25 -0
@@ 0,0 1,25 @@
import QtQuick 2.15;
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami

Image { 
	id: messageImage
	width: 350
	fillMode: Image.PreserveAspectFit
	property string filePath: ""
	Component.onCompleted: {
		messageImage.source = `file://${messageImage.filePath}`;
	}
	source: ""
	MouseArea {
		anchors.fill: parent
		onClicked: {
			msgImgOver.open();
		}
	}
	PictureOverlay {
		id: msgImgOver
		filePath: messageImage.filePath
	}
}
\ No newline at end of file

M qml/MessageUI.qml => qml/MessageUI.qml +22 -14
@@ 1,7 1,7 @@
import QtQuick 2.15
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15

import org.kde.kirigami 2.13 as Kirigami
ItemDelegate {
    id: message
    x: 5


@@ 12,8 12,9 @@ ItemDelegate {
    property bool group: false
    property int oneLineWidth: textLabel.implicitWidth
    property bool oneLine: oneLineWidth <= maxDelegateWidth
    readonly property int maxDelegateWidth: 27 * 8
    readonly property int maxDelegateWidth: Math.min(27 * Kirigami.Units.gridUnit, chatHistory.width - (Kirigami.Units.gridUnit ) * 2)
    width: parent ? parent.width : 0
    //Layout.fillWidth: true
    property ListModel attachmentModel: ListModel {
    }
    property ListModel reactionModel : ListModel {


@@ 42,6 43,7 @@ ItemDelegate {
        layoutDirection: message.message.outgoing ? Qt.RightToLeft : Qt.LeftToRight
        Layout.rightMargin: 5
        Rectangle {
            Kirigami.Theme.colorSet:  message.message.outgoing ? Kirigami.Theme.Complementary : Kirigami.Theme.View  
            MouseArea {
                anchors.fill: parent
                acceptedButtons: Qt.RightButton


@@ 61,13 63,12 @@ ItemDelegate {
                }
            }
            id: rectangle
            width: Math.min(
                       message.maxDelegateWidth, Math.max(
                           message.oneLine ? message.oneLineWidth : textLabel.implicitWidth,
                           dateLabel.implicitWidth, attachmentList.implicitWidth, dynName.implicitWidth)) + 10
            width: Math.max(
                           textLabel.width,
                           dateLabel.implicitWidth, attachmentList.implicitWidth, dynName.implicitWidth) + 10
            height: textLabel.implicitHeight + textLabel.anchors.topMargin + 15
                    + dateLabel.implicitHeight + atRow.implicitHeight + dynName.implicitHeight + dynName.anchors.topMargin + attachmentList.anchors.topMargin + dateLabel.anchors.topMargin
            color: message.message.outgoing ? theme.outgoing : theme.message
            color:  Kirigami.Theme.alternateBackgroundColor
            radius: 10
            anchors.top: parent.top
            anchors.topMargin: 10


@@ 76,14 77,17 @@ ItemDelegate {
            ColumnLayout {
                Row {
                    leftPadding: 5
                    Label {
                    TextEdit {
                        Kirigami.Theme.inherit: true
                        selectByMouse: !Kirigami.Settings.isMobile
                        readOnly: true
                        MouseArea {
                            anchors.fill: parent
                            cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
                            cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor
                            acceptedButtons: Qt.NoButton
                        }
                        onLinkActivated: Qt.openUrlExternally(link)
                    	color: theme.highlightedText
                    	color:  Kirigami.Theme.textColor
                        font.pixelSize: Qt.application.font.pixelSize
                        font.bold: false
                        id: textLabel


@@ 111,7 115,7 @@ ItemDelegate {
                            Component.onCompleted: {
                                switch (CType) {
                                    case 2:
                                        var obj = Qt.createQmlObject(`import QtQuick 2.15; Image { width: 350\nfillMode: Image.PreserveAspectFit\nsource: "file://${File}"}`,atRow,  "imageDel");
                                        var obj = msgimgover.createObject(atRow, {filePath: File});//Qt.createQmlObject(`import QtQuick 2.15; Image { width: 350\nfillMode: Image.PreserveAspectFit\nsource: "file://${File}"}`,atRow,  "imageDel");
                                        if (obj.width > rectangle.width) {
                                            rectangle.width = obj.width + 10;
                                        }


@@ 160,9 164,13 @@ ItemDelegate {
                    ListView {
                        orientation: ListView.Horizontal
                        model: message.reactionModel
                        delegate: Label {
                            text: emoji
                        }
                        delegate: Rectangle {
                            radius: 50

                            Label {
                                text: emoji
                            }
                    }
                    }
                }
            }

A qml/PictureOverlay.qml => qml/PictureOverlay.qml +22 -0
@@ 0,0 1,22 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami

Kirigami.OverlaySheet {
	topPadding: 0
	id: photoOverlay
	property string filePath: ""
	Image {
		MouseArea {
			anchors.fill: parent
			onClicked: {
				photoOverlay.close();
			}
		}
		fillMode: Image.PreserveAspectFit
		source: {
			return "file://"+photoOverlay.filePath;
		}
	}
}
\ No newline at end of file

M qml/SignalState.qml => qml/SignalState.qml +6 -6
@@ 15,24 15,24 @@ Item {
        signal.show_view(viewName);
        switch (viewName) {
            case "chats":
                stackView.push(chatViewStack);
                window.pageStack.push(chatViewStack);
                break;
            case "createContact":
                stackView.push("CreateContact.qml");
                window.pageStack.push(Qt.resolvedUrl("CreateContact.qml"));
                break;
            case "settings":
                stackView.push("Settings.qml");
                window.pageStack.push(Qt.resolvedUrl("Settings.qml"));
                break;
            case "chatHistory":
                if (!signalState.desktopView) {
                    stackView.push(messagesViewStack);
                    window.pageStack.push(messagesViewStack);
                }
                break;
            case "editContact":
                stackView.push("EditContact.qml");
                window.pageStack.push(Qt.resolvedUrl("EditContact.qml"));
                break;
            case "createChat":
                stackView.push("CreateChat.qml");
                window.pageStack.push(Qt.resolvedUrl("CreateChat.qml"));
                break;
        }
    }

M qml/loading.qml => qml/loading.qml +2 -1
@@ 1,7 1,8 @@
import QtQuick 2.12
import QtQuick.Controls 2.5
import org.kde.kirigami 2.13 as Kirigami

Page {
Kirigami.Page {
    anchors.fill: stackView
    objectName: "loadingpage"
    title: ""

M qml/main.qml => qml/main.qml +42 -7
@@ 4,7 4,7 @@ import SignalUI 0.1
import QtQuick.Layouts 1.15
import QtQuick.Controls.Material 2.12
import org.kde.kirigami 2.13 as Kirigami
ApplicationWindow {
Kirigami.ApplicationWindow {
    id: window
    width: 640
    height: 470


@@ 31,11 31,42 @@ ApplicationWindow {
        name: "signal"
        onReady: {
            signalState.currentView = "chats";
            stackView.replace(null, chatViewStack);
            toolButton.enabled = true;
            window.pageStack.replace(chatViewStack);
            //toolButton.enabled = true;
        }
    }
    header: ToolBar {
    pageStack.initialPage: Kirigami.Page {
    //anchors.fill: stackView
    objectName: "loadingpage"
    title: ""
    background:Rectangle {
        color: theme.background
    }
    BusyIndicator {
        running: true
        anchors.centerIn: parent
    }
}

    globalDrawer: Kirigami.GlobalDrawer {
        isMenu: true
        actions: [
            Kirigami.Action {
                text: "Create Contact"
                icon.name: "gtk-add"
                onTriggered: {
                    signalState.openView("createContact")
                }
            },
            Kirigami.Action {
                text: i18n("Quit")
                icon.name: "gtk-quit"
                shortcut: StandardKey.Quit
                onTriggered: Qt.quit()
            }
        ]
    }
    /*header: ToolBar {
        id: headerToolBar
        background: Rectangle {
            color: theme.background


@@ 103,7 134,7 @@ ApplicationWindow {
        }
        Column {
            anchors.fill: parent
            /*ItemDelegate {
            ItemDelegate {
                width: parent.width
                onClicked: {
                    signalState.openView("chats");


@@ 113,7 144,7 @@ ApplicationWindow {
                    text: "Chats"
                    color: theme.text
                }
            }*/
            }
            ItemDelegate {
                width: parent.width
                onClicked: {


@@ 157,7 188,7 @@ ApplicationWindow {
            enabled: signalState.desktopView
            active: signalState.desktopView
        }
    }
    }*/
    Component {
        id: chatViewStack
        ChatList {}


@@ 166,6 197,10 @@ ApplicationWindow {
        id: messagesViewStack
        ChatHistory {}
    }
    Component {
        id: msgimgover
        MessageImage {}
    }

}


M src/main.rs => src/main.rs +41 -24
@@ 153,18 153,43 @@ impl SignalUI {
            .unwrap_or_default();
        serde_json::to_string(&fetched).unwrap()
    }
    fn update_chat(&mut self, chat_id: String) {
        let mut i = 0;
        let name = self.resolve_name(chat_id.clone());
        if let Some(msgs) = self
            .state
            .as_ref()
            .unwrap()
            .sbackend
            .messages_id(&chat_id)
            .ok()
        {
            if msgs.len() > 0 {
                let latest = msgs.values().max_by_key(|x| x.sent_at).unwrap();
                let mut chats = self.chats.borrow_mut();
                loop {
                    let mut chat = chats[i].clone();
                    if chat.tel == chat_id {
                        chat.name = name.clone();
                        chat.last = latest.message.clone();
                        chat.timestamp = latest.sent_at;
                        chat.messages = vec![latest.clone()];
                        //chats.change_line(i, chat);
                        chats.remove(i);
                        chats.insert(0, chat);
                        break;
                    }
                    i += 1;
                }
            }
        }
    }
    fn edit_contact(&self, name: String, tel: String, id: String) {
        self.send_req(SignalRequest::EditContact {
            name,
            phone: tel,
            id,
        });
        /*self.state
        .as_ref()
        .unwrap()
        .req_sender
        .send()
        .expect("Couldn't send EditContact");*/
    }
    fn send_message(&self, to: String, message: String, attachment: String) {
        let attachment = match attachment.len() {


@@ 176,12 201,6 @@ impl SignalUI {
            message,
            attachment,
        });
        /*        self.state
        .as_ref()
        .unwrap()
        .req_sender
        .send()
        .expect("Couldn't send SendMessage");*/
    }
    fn resolve_name(&mut self, source: String) -> String {
        self.state.as_mut().unwrap().resolve_name(source)


@@ 196,21 215,9 @@ impl SignalUI {
            message,
            attachment,
        });
        /*self.state
        .as_ref()
        .unwrap()
        .req_sender
        .send()
        .expect("Couldn't send SendGroupMessage");*/
    }
    fn add_contact(&self, name: String, tel: String) {
        self.send_req(SignalRequest::AddContact { name, phone: tel });
        /*self.state
        .as_ref()
        .unwrap()
        .req_sender
        .send()
        .expect("Couldn't send AddContact");*/
    }
    fn show_view(&mut self, view: String) {
        self.state.as_mut().unwrap().show_view(view);


@@ 274,6 281,7 @@ impl SignalUI {
                                    .show()
                                    .unwrap();
                            }
                            slf.update_chat(msg.chat_id.clone());
                        }
                    }
                    SignalResponse::RmMessage {


@@ 343,6 351,7 @@ impl SignalUI {
            conn.clone(),
        );
        state.user_tel = config.number.clone();

        self.state = Some(state);
        res_receiver.attach(None, move |value| {
            process_res(value);


@@ 533,6 542,14 @@ mod qrc;

#[tokio::main]
async fn main() -> Result<(), std::boxed::Box<dyn std::error::Error>> {
    std::process::Command::new("pkill")
        .arg("-f")
        .arg("-SIGKILL")
        .arg("signal-cli")
        .spawn()
        .unwrap()
        .wait()
        .unwrap();
    init_gettext();
    unsafe {
        cpp! { {

M src/qrc.rs => src/qrc.rs +3 -1
@@ 11,7 11,9 @@ qrc!(qml_resources,
        "qml/EditContact.qml",
        "qml/Theme.qml",
        "qml/Avatar.qml",
        "qml/CreateChat.qml"
        "qml/CreateChat.qml",
        "qml/PictureOverlay.qml",
        "qml/MessageImage.qml"
    },
);