mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Multiple Qml app improvements
LibresapiLocalClient::request(...) return a meaningful value ChatView.qml uses a TextField for message input TrustedNodesView.qml improve aestetic main.qml use stack based navigation and tool/menubar
This commit is contained in:
parent
5a219b4d10
commit
17a41dc96a
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2016 Manu Pineda <manu@cooperativa.cat>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -38,9 +38,7 @@ int LibresapiLocalClient::request( const QString& path, const QString& jsonData,
|
||||
data.append(path); data.append('\n');
|
||||
data.append(jsonData); data.append('\n');
|
||||
callbackQueue.enqueue(callback);
|
||||
mLocalSocket.write(data);
|
||||
|
||||
return 1;
|
||||
return mLocalSocket.write(data);
|
||||
}
|
||||
|
||||
void LibresapiLocalClient::socketError(QLocalSocket::LocalSocketError)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@ -39,7 +39,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
/// @deprecated
|
||||
/** When possible it is better to use +rsApi+ object directly instead of
|
||||
* multiple instances of +LibresapiLocalClient+ in Qml */
|
||||
qmlRegisterType<LibresapiLocalClient>(
|
||||
"org.retroshare.qml_components.LibresapiLocalClient", 1, 0,
|
||||
"LibresapiLocalClient");
|
||||
@ -55,7 +56,8 @@ int main(int argc, char *argv[])
|
||||
engine.load(QUrl(QLatin1String("qrc:/qml/main.qml")));
|
||||
|
||||
QFileInfo fileInfo(sockPath);
|
||||
qDebug() << "QML APP:" << sockPath << fileInfo.exists() << fileInfo.lastModified().toString();
|
||||
qDebug() << "QML APP:" << sockPath << fileInfo.exists()
|
||||
<< fileInfo.lastModified().toString();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>qml/main.qml</file>
|
||||
<file>qml/icons/star-2-128.png</file>
|
||||
<file>qml/icons/settings-4-128.png</file>
|
||||
<file>qml/icons/email-128.png</file>
|
||||
<file>qml/icons/contacts-128.png</file>
|
||||
<file>qml/Locations.qml</file>
|
||||
<file>qml/jsonpath.js</file>
|
||||
<file>qml/JSONListModel.qml</file>
|
||||
@ -13,5 +9,9 @@
|
||||
<file>qml/RsLoginPassView.qml</file>
|
||||
<file>qml/TrustedNodesView.qml</file>
|
||||
<file>qml/ChatView.qml</file>
|
||||
<file>qml/icons/retroshare06.png</file>
|
||||
<file>qml/icons/remove-link.png</file>
|
||||
<file>qml/icons/state-offline.png</file>
|
||||
<file>qml/icons/state-ok.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import org.retroshare.qml_components.LibresapiLocalClient 1.0
|
||||
@ -43,16 +61,7 @@ Item
|
||||
delegate: chatMessageDelegate
|
||||
}
|
||||
|
||||
Rectangle
|
||||
{
|
||||
color: "green"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
width: chatView.width - sendButton.width
|
||||
height: Math.max(20, msgComposer.height)
|
||||
}
|
||||
|
||||
TextEdit
|
||||
TextField
|
||||
{
|
||||
id: msgComposer
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@ -29,7 +29,15 @@ Item
|
||||
|
||||
Component.onCompleted: refreshOwn()
|
||||
|
||||
function refreshData() { rsApi.request("/identity/*/", "", function(par) { locationsModel.json = par.response; if(contactsView.own_gxs_id == "") refreshOwn() }) }
|
||||
function refreshData()
|
||||
{
|
||||
function refreshCallback(par)
|
||||
{
|
||||
locationsModel.json = par.response
|
||||
if(contactsView.own_gxs_id == "") refreshOwn()
|
||||
}
|
||||
rsApi.request("/identity/*/", "", refreshCallback)
|
||||
}
|
||||
function refreshOwn()
|
||||
{
|
||||
rsApi.request("/identity/own", "", function(par)
|
||||
@ -43,6 +51,14 @@ Item
|
||||
else createIdentityDialog.visible = true
|
||||
})
|
||||
}
|
||||
function startChatCallback(par)
|
||||
{
|
||||
var chId = JSON.parse(par.response).data.chat_id
|
||||
stackView.push({
|
||||
item:"qrc:/qml/ChatView.qml",
|
||||
properties: {chatId: chId}
|
||||
})
|
||||
}
|
||||
|
||||
onFocusChanged: focus && refreshData()
|
||||
|
||||
@ -68,12 +84,16 @@ Item
|
||||
anchors.fill: parent
|
||||
onClicked:
|
||||
{
|
||||
console.log("Contacts view onclicked:", model.name, model.gxs_id)
|
||||
console.log("Contacts view onclicked:", model.name,
|
||||
model.gxs_id)
|
||||
if(model.own) contactsView.own_gxs_id = model.gxs_id
|
||||
else
|
||||
{
|
||||
var jsonData = { "own_gxs_hex": contactsView.own_gxs_id, "remote_gxs_hex": model.gxs_id }
|
||||
rsApi.request("/chat/initiate_distant_chat", JSON.stringify(jsonData), function (par) { mainWindow.activeChatId = JSON.parse(par.response).data.chat_id })
|
||||
var jsonData = { "own_gxs_hex": contactsView.own_gxs_id,
|
||||
"remote_gxs_hex": model.gxs_id }
|
||||
rsApi.request("/chat/initiate_distant_chat",
|
||||
JSON.stringify(jsonData),
|
||||
contactsView.startChatCallback)
|
||||
}
|
||||
}
|
||||
Text
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@ -18,17 +18,31 @@
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2
|
||||
import "jsonpath.js" as JSONPath
|
||||
|
||||
Item
|
||||
{
|
||||
function refreshData() { rsApi.request("/peers/*", "", function(par) { jsonModel.json = par.response }) }
|
||||
id: trustedNodesView
|
||||
|
||||
function refreshData()
|
||||
{
|
||||
rsApi.request("/peers/*", "",
|
||||
function(par) { jsonModel.json = par.response })
|
||||
}
|
||||
onFocusChanged: focus && refreshData()
|
||||
|
||||
JSONListModel
|
||||
{
|
||||
id: jsonModel
|
||||
query: "$.data[*]"
|
||||
|
||||
function isOnline(pgpId)
|
||||
{
|
||||
var qr = "$.data[?(@.pgp_id=='"+pgpId+"')].locations[*].is_online"
|
||||
var locArr = JSONPath.jsonPath(JSON.parse(jsonModel.json), qr)
|
||||
return locArr.reduce(function(cur,acc){return cur || acc}, false)
|
||||
}
|
||||
}
|
||||
|
||||
ListView
|
||||
@ -39,38 +53,92 @@ Item
|
||||
model: jsonModel.model
|
||||
delegate: Item
|
||||
{
|
||||
height: 50
|
||||
Row
|
||||
{
|
||||
height: 30
|
||||
Text
|
||||
{
|
||||
text: model.name
|
||||
onTextChanged: color = JSONPath.jsonPath(JSON.parse(jsonModel.json), "$.data[?(@.pgp_id=='"+model.pgp_id+"')].locations[*].is_online").reduce(function(cur,acc){return cur || acc}, false) ? "lime" : "darkslategray"
|
||||
}
|
||||
height: 30
|
||||
width: parent.width
|
||||
|
||||
Rectangle
|
||||
Image
|
||||
{
|
||||
id: statusImage
|
||||
source: jsonModel.isOnline(model.pgp_id) ?
|
||||
"icons/state-ok.png" :
|
||||
"icons/state-offline.png"
|
||||
|
||||
height: parent.height - 4
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.leftMargin: 6
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text
|
||||
{
|
||||
text: model.name
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: statusImage.right
|
||||
anchors.leftMargin: 10
|
||||
}
|
||||
Image
|
||||
{
|
||||
source: "icons/remove-link.png"
|
||||
|
||||
height: parent.height - 6
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
MouseArea
|
||||
{
|
||||
height: parent.height
|
||||
width: parent.height
|
||||
color: "red"
|
||||
|
||||
MouseArea
|
||||
width: parent.width
|
||||
onClicked:
|
||||
{
|
||||
height: parent.height
|
||||
width: parent.height
|
||||
onClicked: rsApi.request("/peers/"+model.pgp_id+"/delete")
|
||||
deleteDialog.nodeName = model.name
|
||||
deleteDialog.nodeId = model.pgp_id
|
||||
deleteDialog.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dialog
|
||||
{
|
||||
id: deleteDialog
|
||||
property string nodeName
|
||||
property string nodeId
|
||||
standardButtons: StandardButton.Yes | StandardButton.No
|
||||
visible: false
|
||||
onYes:
|
||||
{
|
||||
rsApi.request("/peers/"+nodeId+"/delete")
|
||||
trustedNodesView.refreshData()
|
||||
trustedNodesView.forceActiveFocus()
|
||||
}
|
||||
onNo: trustedNodesView.forceActiveFocus()
|
||||
Text
|
||||
{
|
||||
text: "Are you sure to delete " + deleteDialog.nodeName + " ("+
|
||||
deleteDialog.nodeId +") ?"
|
||||
|
||||
width: parent.width - 2
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
Button
|
||||
{
|
||||
id: bottomButton
|
||||
text: "Add Trusted Node"
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: swipeView.currentIndex = 3
|
||||
onClicked: stackView.push({item:"qrc:/qml/AddTrustedNode.qml"})
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Timer
|
||||
{
|
||||
interval: 800
|
||||
repeat: true
|
||||
onTriggered: if(trustedNodesView.visible) trustedNodesView.refreshData()
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
}
|
||||
|
BIN
retroshare-qml-app/src/qml/icons/remove-link.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/remove-link.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
1
retroshare-qml-app/src/qml/icons/retroshare06.png
Symbolic link
1
retroshare-qml-app/src/qml/icons/retroshare06.png
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../data/128x128/apps/retroshare06.png
|
BIN
retroshare-qml-app/src/qml/icons/state-offline.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/state-offline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
BIN
retroshare-qml-app/src/qml/icons/state-ok.png
Normal file
BIN
retroshare-qml-app/src/qml/icons/state-ok.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@ -24,94 +24,137 @@ ApplicationWindow
|
||||
{
|
||||
id: mainWindow
|
||||
visible: true
|
||||
title: qsTr("RSChat")
|
||||
title: "RetroShare"
|
||||
width: 400
|
||||
height: 400
|
||||
|
||||
property string activeChatId;
|
||||
|
||||
Rectangle
|
||||
toolBar: ToolBar
|
||||
{
|
||||
id: mainView
|
||||
anchors.fill: parent
|
||||
states:
|
||||
[
|
||||
State
|
||||
{
|
||||
name: "waiting_account_select"
|
||||
PropertyChanges { target: swipeView; currentIndex: 0 }
|
||||
PropertyChanges { target: locationsTab; enabled: true }
|
||||
},
|
||||
State
|
||||
{
|
||||
name: "running_ok"
|
||||
PropertyChanges { target: swipeView; currentIndex: 1 }
|
||||
PropertyChanges { target: locationsTab; enabled: false }
|
||||
},
|
||||
State
|
||||
{
|
||||
name: "running_ok_no_full_control"
|
||||
PropertyChanges { target: swipeView; currentIndex: 1 }
|
||||
PropertyChanges { target: locationsTab; enabled: false }
|
||||
}
|
||||
]
|
||||
|
||||
LibresapiLocalClient
|
||||
Image
|
||||
{
|
||||
onGoodResponseReceived:
|
||||
{
|
||||
var jsonReponse = JSON.parse(msg)
|
||||
mainView.state = jsonReponse.data.runstate
|
||||
}
|
||||
Component.onCompleted:
|
||||
{
|
||||
openConnection(apiSocketPath)
|
||||
request("/control/runstate/", "")
|
||||
}
|
||||
id: rsIcon
|
||||
fillMode: Image.PreserveAspectFit
|
||||
height: Math.max(30, parent.height - 4)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: "icons/retroshare06.png"
|
||||
}
|
||||
|
||||
TabView
|
||||
Label
|
||||
{
|
||||
id: swipeView
|
||||
anchors.fill: parent
|
||||
visible: true
|
||||
currentIndex: 0
|
||||
text: "RetroShare"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: rsIcon.right
|
||||
anchors.leftMargin: 20
|
||||
}
|
||||
}
|
||||
|
||||
Tab
|
||||
menuBar: MenuBar
|
||||
{
|
||||
Menu
|
||||
{
|
||||
MenuItem
|
||||
{
|
||||
title:"Locations"
|
||||
id: locationsTab
|
||||
Locations { onVisibleChanged: focus = visible }
|
||||
text: "Trusted Nodes"
|
||||
onTriggered:
|
||||
stackView.push({item:"qrc:/qml/TrustedNodesView.qml"})
|
||||
}
|
||||
|
||||
Tab
|
||||
MenuItem
|
||||
{
|
||||
title: "Trusted Nodes"
|
||||
TrustedNodesView { onVisibleChanged: focus = visible }
|
||||
}
|
||||
|
||||
Tab
|
||||
{
|
||||
title: "Contacts"
|
||||
Contacts { onVisibleChanged: focus = visible }
|
||||
}
|
||||
|
||||
Tab
|
||||
{
|
||||
title: "Add Node"
|
||||
AddTrustedNode { onVisibleChanged: focus = visible }
|
||||
}
|
||||
|
||||
Tab
|
||||
{
|
||||
title: "Chat"
|
||||
ChatView
|
||||
{
|
||||
id: chatView
|
||||
chatId: mainWindow.activeChatId
|
||||
onVisibleChanged: focus = visible
|
||||
}
|
||||
text: "StackView State"
|
||||
onTriggered: console.log(stackView.state, stackView.enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackView
|
||||
{
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
Keys.onReleased:
|
||||
if (event.key === Qt.Key_Back && stackView.depth > 1)
|
||||
{
|
||||
stackView.pop();
|
||||
event.accepted = true;
|
||||
}
|
||||
|
||||
function checkCoreStatus()
|
||||
{
|
||||
function runStateCallback(par)
|
||||
{
|
||||
var jsonReponse = JSON.parse(par.response)
|
||||
var runState = jsonReponse.data.runstate
|
||||
if(typeof(runState) === 'string') stackView.state = runState
|
||||
else
|
||||
{
|
||||
stackView.state = "core_down"
|
||||
console.log("runStateCallback(...) core is down")
|
||||
}
|
||||
}
|
||||
var ret = rsApi.request("/control/runstate/", "", runStateCallback)
|
||||
if ( ret < 1 )
|
||||
{
|
||||
console.log("checkCoreStatus() core is down")
|
||||
stackView.state = "core_down"
|
||||
}
|
||||
}
|
||||
|
||||
Timer
|
||||
{
|
||||
id: refreshTimer
|
||||
interval: 800
|
||||
repeat: true
|
||||
onTriggered: if(stackView.visible) stackView.checkCoreStatus()
|
||||
Component.onCompleted: start()
|
||||
}
|
||||
|
||||
state: "core_down"
|
||||
states: [
|
||||
State
|
||||
{
|
||||
name: "core_down"
|
||||
PropertyChanges { target: stackView; enabled: false }
|
||||
},
|
||||
State
|
||||
{
|
||||
name: "waiting_account_select"
|
||||
PropertyChanges { target: stackView; enabled: true }
|
||||
StateChangeScript
|
||||
{
|
||||
script:
|
||||
{
|
||||
console.log("StateChangeScript waiting_account_select")
|
||||
stackView.clear()
|
||||
stackView.push({item:"qrc:/qml/Locations.qml"})
|
||||
}
|
||||
}
|
||||
},
|
||||
State
|
||||
{
|
||||
name: "running_ok"
|
||||
PropertyChanges { target: stackView; enabled: true }
|
||||
StateChangeScript
|
||||
{
|
||||
script:
|
||||
{
|
||||
console.log("StateChangeScript waiting_account_select")
|
||||
stackView.clear()
|
||||
stackView.push({item: "qrc:/qml/Contacts.qml"})
|
||||
}
|
||||
}
|
||||
},
|
||||
State
|
||||
{
|
||||
name: "running_ok_no_full_control"
|
||||
PropertyChanges { target: stackView; state: "running_ok" }
|
||||
}
|
||||
]
|
||||
|
||||
initialItem: Rectangle
|
||||
{
|
||||
anchors.fill: parent
|
||||
color: "green"
|
||||
border.color: "black"
|
||||
|
||||
Text { text: "Connecting to core..." }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,8 @@ DISTFILES += \
|
||||
android/res/values/libs.xml \
|
||||
android/build.gradle \
|
||||
android/gradle/wrapper/gradle-wrapper.properties \
|
||||
android/gradlew.bat
|
||||
android/gradlew.bat \
|
||||
qml/icons/retroshare06.png
|
||||
|
||||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user