Changeset View
Changeset View
Standalone View
Standalone View
smsapp/qml/ConversationDisplay.qml
Show All 32 Lines | 32 | readonly property QtObject person: PersonData { | |||
---|---|---|---|---|---|
33 | id: person | 33 | id: person | ||
34 | } | 34 | } | ||
35 | property QtObject device | 35 | property QtObject device | ||
36 | property int conversationId | 36 | property int conversationId | ||
37 | 37 | | |||
38 | property string phoneNumber | 38 | property string phoneNumber | ||
39 | title: person.person && person.person.name ? person.person.name : phoneNumber | 39 | title: person.person && person.person.name ? person.person.name : phoneNumber | ||
40 | 40 | | |||
41 | /** | ||||
42 | * Build a chat message which is representative of all chat messages | ||||
43 | * | ||||
44 | * In other words, one which I can use to get a reasonable height guess | ||||
45 | */ | ||||
46 | ChatMessage { | ||||
47 | id: genericMessage | ||||
48 | messageBody: "Generic Message Body" | ||||
49 | dateTime: new Date('2000-0-0') | ||||
50 | visible: false | ||||
51 | enabled: false | ||||
52 | } | ||||
53 | | ||||
41 | function sendMessage() { | 54 | function sendMessage() { | ||
42 | console.log("sending sms", page.phoneNumber) | 55 | console.log("sending sms", page.phoneNumber) | ||
43 | model.sourceModel.sendReplyToConversation(message.text) | 56 | model.sourceModel.sendReplyToConversation(message.text) | ||
44 | message.text = "" | 57 | message.text = "" | ||
45 | } | 58 | } | ||
46 | 59 | | |||
47 | ListView { | 60 | ListView { | ||
61 | id: viewport | ||||
48 | model: QSortFilterProxyModel { | 62 | model: QSortFilterProxyModel { | ||
49 | id: model | 63 | id: model | ||
50 | sortOrder: Qt.AscendingOrder | 64 | sortOrder: Qt.AscendingOrder | ||
51 | sortRole: ConversationModel.DateRole | 65 | sortRole: ConversationModel.DateRole | ||
52 | sourceModel: ConversationModel { | 66 | sourceModel: ConversationModel { | ||
53 | deviceId: device.id() | 67 | deviceId: device.id() | ||
54 | threadId: page.conversationId | 68 | threadId: page.conversationId | ||
55 | } | 69 | } | ||
56 | } | 70 | } | ||
57 | 71 | | |||
58 | spacing: Kirigami.Units.largeSpacing | 72 | spacing: Kirigami.Units.largeSpacing | ||
59 | 73 | | |||
60 | delegate: ChatMessage { | 74 | delegate: ChatMessage { | ||
61 | messageBody: model.display | 75 | messageBody: model.display | ||
62 | sentByMe: model.fromMe | 76 | sentByMe: model.fromMe | ||
63 | dateTime: new Date(model.date) | 77 | dateTime: new Date(model.date) | ||
78 | | ||||
79 | ListView.onAdd: { | ||||
80 | if (index == viewport.count - 1) | ||||
81 | // This message is being inserted at the newest position | ||||
82 | // We want to scroll to show it if the user is "almost" looking at it | ||||
83 | | ||||
84 | // Define some fudge area. If the message is being drawn offscreen but within | ||||
85 | // this distance, we move to show it anyway. | ||||
86 | // Selected to be genericMessage.height because that value scales for different | ||||
87 | // font sizes / DPI / etc. -- Better ideas are welcome! | ||||
88 | // Double the value works nicely | ||||
89 | var offscreenFudge = 2 * genericMessage.height | ||||
90 | | ||||
91 | var viewportYBottom = viewport.contentY + viewport.height | ||||
92 | | ||||
93 | if (y < viewportYBottom + genericMessage.height) { | ||||
94 | viewport.currentIndex = index | ||||
95 | } | ||||
64 | } | 96 | } | ||
97 | } | ||||
98 | | ||||
99 | onMovementEnded: { | ||||
100 | // Unset the highlightRangeMode if it was set previously | ||||
101 | highlightRangeMode = ListView.ApplyRange | ||||
102 | highlightMoveDuration: -1 // "Re-enable" the highlight animation | ||||
65 | 103 | | |||
66 | // Set the view to start at the bottom of the page and track new elements if it was not manually scrolled up | 104 | if (atYBeginning) { | ||
67 | currentIndex: atYEnd ? | 105 | // "Lock" the view to the message currently at the beginning of the view | ||
68 | count - 1 : | 106 | // This prevents the view from snapping to the top of the messages we are about to request | ||
69 | currentIndex | 107 | currentIndex = 0 // Index 0 is the beginning of the view | ||
108 | preferredHighlightBegin = visibleArea.yPosition | ||||
109 | preferredHighlightEnd = preferredHighlightBegin + currentItem.height | ||||
110 | highlightRangeMode = ListView.StrictlyEnforceRange | ||||
111 | | ||||
112 | highlightMoveDuration = 1 // This is not ideal: I would like to disable the highlight animation altogether | ||||
113 | | ||||
114 | // Get more messages | ||||
115 | model.sourceModel.requestMoreMessages() | ||||
116 | } | ||||
117 | } | ||||
70 | } | 118 | } | ||
71 | 119 | | |||
72 | footer: RowLayout { | 120 | footer: RowLayout { | ||
73 | enabled: page.device | 121 | enabled: page.device | ||
74 | ScrollView { | 122 | ScrollView { | ||
75 | Layout.maximumHeight: page.height / 3 | 123 | Layout.maximumHeight: page.height / 3 | ||
76 | Layout.fillWidth: true | 124 | Layout.fillWidth: true | ||
77 | Layout.fillHeight: true | 125 | Layout.fillHeight: true | ||
Show All 23 Lines |