mirror of
https://gitlab.com/eql/lqml.git
synced 2025-12-06 02:30:38 -08:00
example 'meshtastic': add deletion of messages; revisions
This commit is contained in:
parent
8f42003e36
commit
e6b25c8d60
8 changed files with 128 additions and 85 deletions
|
|
@ -31,3 +31,7 @@
|
|||
(let ((val (first (query "select max(mid) from messages"))))
|
||||
(if (numberp val) val 0)))
|
||||
|
||||
(defun delete-message (mid)
|
||||
(query "delete from messages where mid = ?"
|
||||
mid))
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
(msg:show-messages)
|
||||
(q> |currentIndex| ui:*main-view* 0)) ; 'Group'
|
||||
(q> |playing| ui:*loading* nil)
|
||||
(q> |interactive| ui:*main-view* t)
|
||||
#+android
|
||||
(progn
|
||||
(ensure-permissions :access-fine-location) ; for sharing location
|
||||
|
|
@ -30,6 +29,7 @@
|
|||
(q> |currentIndex| ui:*main-view* 0))
|
||||
(q> |visible| ui:*location* (= 0 index))
|
||||
(q> |visible| ui:*find* (= 1 index))
|
||||
(q> |interactive| ui:*main-view* (/= 1 index)) ; swipe single message, not view
|
||||
(values))
|
||||
|
||||
(defun icon-press-and-hold (name) ; see QML
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
(defpackage :db
|
||||
(:use :cl)
|
||||
(:export
|
||||
#:delete-message
|
||||
#:ini
|
||||
#:load-message
|
||||
#:load-messages
|
||||
|
|
|
|||
|
|
@ -12,69 +12,21 @@ Rectangle {
|
|||
anchors.fill: parent
|
||||
anchors.bottomMargin: rectEdit.height + 3
|
||||
anchors.margins: 5
|
||||
delegate: messageDelegate
|
||||
model: messages
|
||||
clip: true
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: messages
|
||||
objectName: "messages"
|
||||
delegate: SwipeDelegate {
|
||||
id: swipeDelegate
|
||||
width: view.width
|
||||
height: delegate.height
|
||||
clip: true
|
||||
|
||||
// hack to define all model key _types_
|
||||
ListElement {
|
||||
receiver: ""; sender: ""; senderName: ""; timestamp: ""; hour: "";
|
||||
text: ""; text2: ""; mid: ""; ackState: 0; me: true; hidden: false
|
||||
}
|
||||
onPressAndHold: Lisp.call("msg:message-press-and-hold", model.text)
|
||||
|
||||
function addMessage(message) { append(message) }
|
||||
|
||||
function changeState(state, mid) {
|
||||
for (var i = count - 1; i >= 0; i--) {
|
||||
if (get(i).mid === mid) {
|
||||
setProperty(i, "ackState", state)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function find(term) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
var text = get(i).text
|
||||
var highlighted = Lisp.call("msg:highlight-term", text, term)
|
||||
if (highlighted) {
|
||||
if (!get(i).text2) {
|
||||
setProperty(i, "text2", text)
|
||||
}
|
||||
setProperty(i, "text", highlighted)
|
||||
}
|
||||
setProperty(i, "hidden", !highlighted)
|
||||
}
|
||||
view.positionViewAtBeginning()
|
||||
}
|
||||
|
||||
function clearFind() {
|
||||
for (var i = 0; i < count; i++) {
|
||||
var text2 = get(i).text2
|
||||
if (text2) {
|
||||
setProperty(i, "text", text2)
|
||||
setProperty(i, "text2", "")
|
||||
}
|
||||
setProperty(i, "hidden", false)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: remove(0) // see hack above
|
||||
}
|
||||
|
||||
Component {
|
||||
id: messageDelegate
|
||||
|
||||
Item {
|
||||
background: Item {
|
||||
id: delegate
|
||||
width: Math.max(text.paintedWidth, rowSender.width + 4 * text.padding) + 2 * text.padding + 4
|
||||
height: model.hidden ? 0 : (text.contentHeight + 2 * text.padding + sender.contentHeight + 8)
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
|
|
@ -83,11 +35,6 @@ Rectangle {
|
|||
color: model.me ? "#f2f2f2" : "#ffffcc"
|
||||
radius: 12
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressAndHold: Lisp.call("msg:message-press-and-hold", model.text)
|
||||
}
|
||||
|
||||
Row {
|
||||
id: rowSender
|
||||
padding: text.padding
|
||||
|
|
@ -142,6 +89,97 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView.onRemove: SequentialAnimation {
|
||||
PropertyAction {
|
||||
target: swipeDelegate
|
||||
property: "ListView.delayRemove"
|
||||
value: true
|
||||
}
|
||||
NumberAnimation {
|
||||
target: swipeDelegate
|
||||
property: "height"
|
||||
to: 0
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
PropertyAction {
|
||||
target: swipeDelegate
|
||||
property: "ListView.delayRemove"
|
||||
value: false
|
||||
}
|
||||
}
|
||||
|
||||
swipe.left: Rectangle {
|
||||
y: 2
|
||||
width: 35
|
||||
height: parent.height - 2 * y
|
||||
color: "#ff4141"
|
||||
radius: 12
|
||||
|
||||
Image {
|
||||
anchors.centerIn: parent
|
||||
width: 12
|
||||
height: width
|
||||
source: "../img/delete.png"
|
||||
}
|
||||
|
||||
SwipeDelegate.onClicked: {
|
||||
var mid = model.mid
|
||||
view.model.remove(index)
|
||||
Lisp.call("db:delete-message", mid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: messages
|
||||
objectName: "messages"
|
||||
|
||||
// hack to define all model key _types_
|
||||
ListElement {
|
||||
receiver: ""; sender: ""; senderName: ""; timestamp: ""; hour: "";
|
||||
text: ""; text2: ""; mid: ""; ackState: 0; me: true; hidden: false
|
||||
}
|
||||
|
||||
function addMessage(message) { append(message) }
|
||||
|
||||
function changeState(state, mid) {
|
||||
for (var i = count - 1; i >= 0; i--) {
|
||||
if (get(i).mid === mid) {
|
||||
setProperty(i, "ackState", state)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function find(term) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
var text = get(i).text
|
||||
var highlighted = Lisp.call("msg:highlight-term", text, term)
|
||||
if (highlighted) {
|
||||
if (!get(i).text2) {
|
||||
setProperty(i, "text2", text)
|
||||
}
|
||||
setProperty(i, "text", highlighted)
|
||||
}
|
||||
setProperty(i, "hidden", !highlighted)
|
||||
}
|
||||
view.positionViewAtBeginning()
|
||||
}
|
||||
|
||||
function clearFind() {
|
||||
for (var i = 0; i < count; i++) {
|
||||
var text2 = get(i).text2
|
||||
if (text2) {
|
||||
setProperty(i, "text", text2)
|
||||
setProperty(i, "text2", "")
|
||||
}
|
||||
setProperty(i, "hidden", false)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: remove(0) // see hack above
|
||||
}
|
||||
|
||||
// find text
|
||||
|
|
|
|||
BIN
examples/meshtastic/qml/img/delete.png
Normal file
BIN
examples/meshtastic/qml/img/delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
|
|
@ -40,7 +40,6 @@ Item {
|
|||
width: headerHeight
|
||||
height: width
|
||||
anchors.right: parent.right
|
||||
visible: false
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
|
|
|||
|
|
@ -37,12 +37,14 @@ Messages
|
|||
--------
|
||||
|
||||
The initial view shows the messages between you and a chosen person. You choose
|
||||
the desired person in the **Group** view (swipe to the left).
|
||||
the desired person in the **Group** view (tap on group icon).
|
||||
|
||||
To copy a message to the clipboard, press-and-hold it.
|
||||
|
||||
To see the exact date of a message, tap on its hour.
|
||||
|
||||
To delete a message, swipe it to the right and tap on the delete button.
|
||||
|
||||
The search function (icon on the right) should be intuitive. The search term
|
||||
(case insensitive) is highlighted in red. Tap again on the search icon to leave
|
||||
search mode.
|
||||
|
|
@ -51,7 +53,7 @@ search mode.
|
|||
Group
|
||||
-----
|
||||
|
||||
Swiping to the left (from **Messages**), you see the list of all persons. Every
|
||||
Tapping on group (in **Messages**), you'll see the list of all persons. Every
|
||||
person is associated to a specific radio. This view is populated automatically.
|
||||
|
||||
You can set a name to every person associated to a radio, which defaults to
|
||||
|
|
@ -66,7 +68,7 @@ without internet connection.
|
|||
Radios
|
||||
------
|
||||
|
||||
Swiping to the right (from **Messages**), you see the list of all radios
|
||||
Tapping on radio (in **Messages**), you'll see the list of all radios
|
||||
visible to your phone's bluetooth. You generally just choose 1 device, which
|
||||
will be remembered.
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,7 @@ The macOS version must be compiled first and started from Finder (not the
|
|||
console), otherwise BLE permissions will not work (if run from console, the app
|
||||
will show a BLE exception and consume 100% CPU).
|
||||
|
||||
It should also work on Windows 10 and later, but the bluetooth part is not
|
||||
tested yet.
|
||||
Windows 10+ will follow soon.
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue