example 'meshtastic': add deletion of messages; revisions

This commit is contained in:
pls.153 2023-08-09 18:32:58 +02:00
parent 8f42003e36
commit e6b25c8d60
8 changed files with 128 additions and 85 deletions

View file

@ -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))

View file

@ -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

View file

@ -61,6 +61,7 @@
(defpackage :db
(:use :cl)
(:export
#:delete-message
#:ini
#:load-message
#:load-messages

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -40,7 +40,6 @@ Item {
width: headerHeight
height: width
anchors.right: parent.right
visible: false
MouseArea {
anchors.fill: parent

View file

@ -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.

View file

@ -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.