Merge lp:~mzanetti/telegram-app/stickers into lp:telegram-app

Proposed by Michael Zanetti
Status: Merged
Approved by: Michał Karnicki
Approved revision: 157
Merged at revision: 156
Proposed branch: lp:~mzanetti/telegram-app/stickers
Merge into: lp:telegram-app
Diff against target: 1135 lines (+804/-16)
14 files modified
telegram/app/app.pro (+4/-2)
telegram/app/asemantools/asemandevices.cpp (+1/-1)
telegram/app/emoticonsmodel.cpp (+32/-0)
telegram/app/emoticonsmodel.h (+3/-0)
telegram/app/qml/AccountMessageList.qml (+28/-0)
telegram/app/qml/AccountSendMessage.qml (+77/-2)
telegram/app/qml/Emoticons.qml (+227/-0)
telegram/app/qml/InstallStickerDialog.qml (+80/-0)
telegram/app/qml/components/MessagesListItem.qml (+1/-0)
telegram/app/qml/files/emojis.svg (+191/-0)
telegram/app/stickerfilemanager.cpp (+117/-0)
telegram/app/stickerfilemanager.h (+34/-0)
telegram/app/telegram.cpp (+2/-0)
telegram/app/telegram.qrc (+7/-11)
To merge this branch: bzr merge lp:~mzanetti/telegram-app/stickers
Reviewer Review Type Date Requested Status
Roberto Mier Escandon (community) Approve
Michał Karnicki (community) Needs Information
Review via email: mp+287426@code.launchpad.net

Commit message

add support for stickers

Description of the change

this adds complete support for stickers.

Browsing stickers with just this branch is very slow. In order to get the complete experience, this branch must be merged upstream:

https://github.com/Aseman-Land/TelegramQML/pull/48

To post a comment you must log in.
Revision history for this message
Roberto Mier Escandon (rmescandon) wrote :

Only overviewed, not tested yet. Left some comments below

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Only overviewed, not tested yet. Left some comments below

The commented code was a leftover (as I copied the upstream code, and then implemented the Ubuntu version accordingly) which I just forgot to drop. I've deleted it by now. Thanks for catching it.

About the po updates: This really depends on how you guys want to handle it. I've committed the changes because the build scripts do the updates automatically. I for one quite dislike that because it creates merge conflicts in translations all the time. On the other hand, it prevents us from forgetting to update the translations before a release. In any case, it's up to you guys really. Let me know if I should revert those changes or not.

Maybe Jin and Michał have an opinion on this too?

Revision history for this message
Roberto Mier Escandon (rmescandon) wrote :

Tested the behaviour of the app... absolutely awesome!!
Though I've seen a thing which I don't know if it is related with this change (I don't think so). Sometimes, when sending a sticker in a conversation, that sticker is put in the conversation and then resized. After resizing, sometimes it get taller and that amount of image that has grown remains out of the screen in the lower part and there is no way to see it unless you get out to dialogs list and enter back in conversation. (see last sticker in attached image)

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

> Tested the behaviour of the app... absolutely awesome!!
> Though I've seen a thing which I don't know if it is related with this change
> (I don't think so). Sometimes, when sending a sticker in a conversation, that
> sticker is put in the conversation and then resized. After resizing, sometimes
> it get taller and that amount of image that has grown remains out of the
> screen in the lower part and there is no way to see it unless you get out to
> dialogs list and enter back in conversation. (see last sticker in attached
> image)

yes, I've seen this too... I really believe this is a bug that's already been in there forever (I occasionally saw this with regular images before) but is now triggered much more often. However, I think this is only happening with the default sticker pack. It doesn't seem to happen with the others. Reason for that is that the default sticker pack is actually images that are sent over the net, while the others are just IDs that are replaced by the sticker on the view only.

I will have a look at this and try to fix it.

Revision history for this message
Michał Karnicki (karni) wrote :

Needs info around line 984.

Few minor comments in-line.

You will make many users happy about this :)

review: Needs Information
lp:~mzanetti/telegram-app/stickers updated
156. By Michael Zanetti

add support for stickers

157. By Michael Zanetti

fix issues from review

Revision history for this message
Roberto Mier Escandon (rmescandon) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'telegram/app/app.pro'
2--- telegram/app/app.pro 2015-11-18 13:45:48 +0000
3+++ telegram/app/app.pro 2016-02-29 10:35:34 +0000
4@@ -25,7 +25,8 @@
5 upgradev2.cpp \
6 cutegramenums.cpp \
7 textemojiwrapper.cpp \
8- emoticonsmodel.cpp
9+ emoticonsmodel.cpp \
10+ stickerfilemanager.cpp
11
12 include(qmake/qtcAddDeployment.pri)
13 include(asemantools/asemantools.pri)
14@@ -41,7 +42,8 @@
15 cutegramenums.h \
16 themeitem.h \
17 textemojiwrapper.h \
18- emoticonsmodel.h
19+ emoticonsmodel.h \
20+ stickerfilemanager.h
21
22 RESOURCES += telegram.qrc
23
24
25=== modified file 'telegram/app/asemantools/asemandevices.cpp'
26--- telegram/app/asemantools/asemandevices.cpp 2015-09-22 09:57:07 +0000
27+++ telegram/app/asemantools/asemandevices.cpp 2016-02-29 10:35:34 +0000
28@@ -483,7 +483,7 @@
29 if(file.exists() && file.isDir())
30 return file.filePath();
31 else
32- return QCoreApplication::applicationDirPath() + "/";
33+ return QCoreApplication::applicationDirPath() + "/../../../";
34 #else
35 return QCoreApplication::applicationDirPath() + "/../Resources/";
36 #endif
37
38=== modified file 'telegram/app/emoticonsmodel.cpp'
39--- telegram/app/emoticonsmodel.cpp 2015-09-22 09:57:07 +0000
40+++ telegram/app/emoticonsmodel.cpp 2016-02-29 10:35:34 +0000
41@@ -10,11 +10,21 @@
42 #include <QSettings>
43 #include <QDebug>
44
45+// The Emoji Model also holds standard stickers. In Ubuntu we don't really
46+// want emojis, because emojis are handled by the on screen keyboard but
47+// we do want to have the stickers from this model.
48+// We might want to enable standard emojis here for the desktop use case
49+// where we don't have an on screen keyboard. Also for compatibility with
50+// upstream, the emoji code has been kept but disabled by the following
51+// define.
52+#define ONLY_STICKERS
53+
54 class EmoticonsModelPrivate
55 {
56 public:
57 QStringList list;
58 QStringList keys;
59+ QList<QUrl> keysIcons;
60 QHash<QString,QString> keysPath;
61
62 QString currentKey;
63@@ -75,6 +85,11 @@
64 return AsemanApplication::settings()->value("General/recentEmojis", QVariant::fromValue<QStringList>(p->emojis->keys().mid(0,20))).toStringList();
65 }
66
67+QList<QUrl> EmoticonsModel::keysIcons() const
68+{
69+ return p->keysIcons;
70+}
71+
72 void EmoticonsModel::setCurrentKey(const QString &key)
73 {
74 if(p->currentKey == key)
75@@ -165,6 +180,7 @@
76 void EmoticonsModel::refresh()
77 {
78 QStringList newList;
79+#ifndef ONLY_STICKERS
80 const int index = currentKeyIndex();
81 if(index == 0) // is recent
82 {
83@@ -183,6 +199,7 @@
84 p->type = EmoticonEmoji;
85 }
86 else // is sticker
87+#endif
88 {
89 const QString key = currentKey();
90 const QString &path = p->keysPath.value(key);
91@@ -209,10 +226,16 @@
92 {
93 p->keys.clear();
94 p->keysPath.clear();
95+ p->keysIcons.clear();
96
97+#ifndef ONLY_STICKERS
98 p->keys.append("Recent");
99 p->keys.append("Emojis");
100
101+ p->keysIcons << QUrl("qrc:/qml/files/emoticons-recent.png");
102+ p->keysIcons << QUrl("qrc:/qml/files/emoticons-emoji.png");
103+#endif
104+
105 foreach(const QUrl &subPathUrl, p->stickerSubPaths)
106 {
107 const QString &subPath = subPathUrl.toLocalFile();
108@@ -222,13 +245,22 @@
109 if(p->keys.contains(sticker))
110 continue;
111
112+#ifdef ONLY_STICKERS
113+ if (sticker.toLower() == "personal") continue;
114+#endif
115+
116 const QString stickerPath = subPath + "/" + sticker;
117 p->keys << sticker;
118 p->keysPath[sticker] = stickerPath;
119+ if(sticker.toLower() == "personal")
120+ p->keysIcons << QUrl("qrc:/qml/files/emoticons-personal.png");
121+ else
122+ p->keysIcons << QUrl("qrc:/qml/files/emoticons-telegram.png");
123 }
124 }
125
126 emit keysChanged();
127+ emit keysIconsChanged();
128 }
129
130 void EmoticonsModel::changed(const QStringList &list)
131
132=== modified file 'telegram/app/emoticonsmodel.h'
133--- telegram/app/emoticonsmodel.h 2015-09-22 09:57:07 +0000
134+++ telegram/app/emoticonsmodel.h 2016-02-29 10:35:34 +0000
135@@ -15,6 +15,7 @@
136 Q_PROPERTY(int count READ count NOTIFY countChanged)
137 Q_PROPERTY(Emojis* emojis READ emojis WRITE setEmojis NOTIFY emojisChanged)
138 Q_PROPERTY(QList<QUrl> stickerSubPaths READ stickerSubPaths WRITE setStickerSubPaths NOTIFY stickerSubPathsChanged)
139+ Q_PROPERTY(QList<QUrl> keysIcons READ keysIcons NOTIFY keysIconsChanged)
140 Q_PROPERTY(QStringList keys READ keys NOTIFY keysChanged)
141 Q_PROPERTY(QString currentKey READ currentKey WRITE setCurrentKey NOTIFY currentKeyChanged)
142 Q_PROPERTY(int currentKeyIndex READ currentKeyIndex NOTIFY currentKeyIndexChanged)
143@@ -43,6 +44,7 @@
144
145 QStringList keys() const;
146 QStringList recentKeys() const;
147+ QList<QUrl> keysIcons() const;
148
149 void setCurrentKey(const QString &key);
150 QString currentKey() const;
151@@ -69,6 +71,7 @@
152 void currentKeyChanged();
153 void currentKeyIndexChanged();
154 void recentKeysChanged();
155+ void keysIconsChanged();
156
157 private:
158 void refreshKeys();
159
160=== modified file 'telegram/app/qml/AccountMessageList.qml'
161--- telegram/app/qml/AccountMessageList.qml 2015-11-02 11:31:04 +0000
162+++ telegram/app/qml/AccountMessageList.qml 2016-02-29 10:35:34 +0000
163@@ -1,5 +1,6 @@
164 import QtQuick 2.0
165 import Ubuntu.Components 1.3
166+import Ubuntu.Components.Popups 1.3
167 import Ubuntu.Components 1.3 as UC
168 import Ubuntu.Content 0.1
169 import AsemanTools.Controls 1.0 as Controls
170@@ -88,6 +89,18 @@
171 }
172 }
173
174+ Connections {
175+ id: sticker_installer
176+ target: telegramObject
177+ onDocumentStickerRecieved: {
178+ if(document != doc)
179+ return
180+
181+ PopupUtils.open(Qt.resolvedUrl("InstallStickerDialog.qml"), acc_msg_list, {telegram: telegramObject, stickerSet: set.shortName})
182+ }
183+ property Document doc
184+ }
185+
186 // Timer {
187 // id: refresh_timer
188 // repeat: true
189@@ -149,6 +162,11 @@
190 interval: 500
191 }
192
193+ StickersModel {
194+ id: stickers_model
195+ telegram: telegramObject
196+ }
197+
198 MultipleSelectionListView {
199 id: mlist
200 anchors.fill: parent
201@@ -227,11 +245,21 @@
202 onTriggered: Clipboard.push(item.message)
203 },
204 Action {
205+ iconName: "info"
206+ text: i18n.tr("Sticker Pack info")
207+ visible: message_item.isSticker && telegramObject.documentStickerId(message_item.media.document) !== 0
208+ onTriggered: {
209+ sticker_installer.doc = message_item.media.document
210+ telegramObject.getStickerSet(sticker_installer.doc)
211+ }
212+ },
213+ Action {
214 iconName: "next"
215 text: i18n.tr("Forward")
216 visible: enchat == telegramObject.nullEncryptedChat
217 onTriggered: forwardMessages([message.id])
218 }
219+
220 ]
221
222 selected: mlist.isSelected(message_item)
223
224=== modified file 'telegram/app/qml/AccountSendMessage.qml'
225--- telegram/app/qml/AccountSendMessage.qml 2016-02-20 23:21:10 +0000
226+++ telegram/app/qml/AccountSendMessage.qml 2016-02-29 10:35:34 +0000
227@@ -9,6 +9,7 @@
228 import Ubuntu.Content 1.1
229 import AsemanTools 1.0
230 import TelegramQML 1.0
231+import Cutegram 1.0
232
233 import "components"
234
235@@ -24,7 +25,6 @@
236 property bool isChat: currentDialog != telegramObject.nullDialog ? currentDialog.peer.chatId != 0 : false
237
238 signal accepted( string text, int inReplyTo )
239- signal emojiRequest(real x, real y)
240 signal copyRequest()
241
242 function checkForSharedContent() {
243@@ -83,6 +83,7 @@
244 property Dialog lastDialog: telegramObject.nullDialog
245 property variant suggestionItem
246 property variant attachmentItem
247+ property variant emojiItem
248 }
249
250 Timer {
251@@ -144,7 +145,7 @@
252
253 anchors {
254 left: parent.left
255- right: send_button_box.left
256+ right: sticker_button_box.left
257 bottom: parent.bottom
258 margins: units.gu(1)
259 rightMargin: 0
260@@ -227,6 +228,11 @@
261 check_suggestion.restart();
262 }
263 }
264+ onFocusChanged: {
265+ if (focus && privates.emojiItem) {
266+ privates.emojiItem.destroy();
267+ }
268+ }
269 }
270
271 MediaImport {
272@@ -244,6 +250,42 @@
273 }
274
275 Item {
276+ id: sticker_button_box
277+ anchors {
278+ top: parent.top
279+ bottom: parent.bottom
280+ right: send_button_box.left
281+ }
282+ width: units.gu(6)
283+
284+ AbstractButton {
285+ anchors.fill: parent
286+ activeFocusOnPress: false
287+ onClicked: {
288+ if (!telegramObject.connected || !NetworkingStatus.online) return
289+
290+ if (!privates.emojiItem) {
291+ txt.focus = false;
292+ privates.emojiItem = emoticons_component.createObject(send_msg)
293+ privates.emojiItem.y = -privates.emojiItem.height
294+ } else {
295+ privates.emojiItem.destroy()
296+ }
297+ }
298+ }
299+
300+ Image {
301+ id: sticker_image
302+ anchors.centerIn: parent
303+ height: units.dp(22)
304+ width: height
305+ sourceSize: Qt.size(width, height)
306+ fillMode: Image.PreserveAspectFit
307+ source: Qt.resolvedUrl("qrc:/qml/files/emojis.svg")
308+ }
309+ }
310+
311+ Item {
312 id: send_button_box
313 anchors {
314 top: parent.top
315@@ -451,4 +493,37 @@
316 onFileRequested: requestMedia(ContentType.All)
317 }
318 }
319+
320+ StickerFileManager {
321+ id: sticker_file_manager
322+ telegram: telegramObject
323+ }
324+
325+ Component {
326+ id: emoticons_component
327+ Emoticons {
328+ id: emoticons
329+ telegram: telegramObject
330+ onEmojiSelected: {
331+ send_msg.insertText(code)
332+ emoticons.destroy();
333+ }
334+ onStickerSelected: {
335+ var dId = currentDialog.peer.userId
336+ if(!dId)
337+ dId = currentDialog.peer.chatId
338+
339+ sticker_file_manager.sendSticker(dId, path)
340+ emoticons.destroy();
341+ }
342+ onStickerDocumentSelected: {
343+ var dId = currentDialog.peer.userId
344+ if(!dId)
345+ dId = currentDialog.peer.chatId
346+
347+ telegramObject.forwardDocument(dId, document)
348+ emoticons.destroy();
349+ }
350+ }
351+ }
352 }
353
354=== added file 'telegram/app/qml/Emoticons.qml'
355--- telegram/app/qml/Emoticons.qml 1970-01-01 00:00:00 +0000
356+++ telegram/app/qml/Emoticons.qml 2016-02-29 10:35:34 +0000
357@@ -0,0 +1,227 @@
358+import QtQuick 2.4
359+import Ubuntu.Components 1.3
360+import AsemanTools 1.0
361+import TelegramQML 1.0
362+import Cutegram 1.0
363+
364+Item {
365+ id: root
366+ width: parent.width
367+ height: units.gu(40)
368+
369+ property variant accountEmojis: emojis
370+ property alias telegram: stickers_model.telegram
371+
372+ signal emojiSelected( string code )
373+ signal stickerSelected( string path )
374+ signal stickerDocumentSelected(variant document)
375+
376+ StickersModel {
377+ id: stickers_model
378+ }
379+
380+ EmoticonsModel {
381+ id: emodel
382+ emojis: accountEmojis
383+ stickerSubPaths: [Devices.localFilesPrePath + AsemanApp.homePath + "/stickers", Devices.resourcePath + "/stickers"]
384+ currentKey: emodel.keys[0]
385+ }
386+
387+ Rectangle {
388+ anchors.fill: parent
389+ color: "white"
390+ }
391+
392+ ListView {
393+ id: selectionView
394+ anchors {
395+ left: parent.left
396+ right: parent.right
397+ top: parent.top
398+ }
399+ orientation: ListView.Horizontal
400+ height: units.gu(6)
401+
402+ model: {
403+ var result = new Array
404+ for(var i=0 ;i<emodel.keys.length; i++) {
405+ result[result.length] = emodel.keys[i]
406+ }
407+ for(var i=0 ;i<stickers_model.installedStickerSets.length; i++) {
408+ result[result.length] = stickers_model.installedStickerSets[i]
409+ }
410+ return result
411+ }
412+
413+ delegate: Item {
414+ id: titem
415+ height: parent.height
416+ width: height
417+
418+ property var itemObject
419+
420+ Component.onCompleted: {
421+ if(index < emodel.keys.length)
422+ itemObject = tab_emoji_icon.createObject(titem, {"index": index})
423+ else {
424+ var idx = index - emodel.keys.length
425+ var sid = stickers_model.installedStickerSets[idx]
426+ var doc = stickers_model.stickerSetThumbnailDocument(sid)
427+ var set = stickers_model.stickerSetItem(sid)
428+
429+ itemObject = tab_sticker_icon.createObject(titem, {"index": index, "document": doc, "stickerSet": set, "currentStickerSet": sid})
430+ }
431+ }
432+ }
433+ }
434+
435+ Rectangle {
436+ id: separator
437+ anchors { left: parent.left; right: parent.right; top: selectionView.bottom }
438+ height: units.dp(1)
439+ color: "black"
440+ }
441+
442+ GridView {
443+ id: elist
444+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom; top: separator.bottom }
445+ clip: true
446+ model: emodel
447+ visible: !slist.visible
448+ cellWidth: emodel.keys.length === 1 || emodel.currentKeyIndex > 1 ? root.width / 4 : root.width / 6
449+ cellHeight: cellWidth
450+ delegate: AbstractButton {
451+ id: item
452+ width: elist.cellWidth
453+ height: elist.cellHeight
454+
455+ Image {
456+ anchors.centerIn: parent
457+ height: model.type === EmoticonsModel.EmoticonSticker ? parent.width - units.gu(1) : units.gu(3)
458+ width: height
459+ sourceSize: Qt.size(width, height)
460+ source: model.path
461+ smooth: true
462+ fillMode: Image.PreserveAspectFit
463+ asynchronous: true
464+ }
465+
466+ onClicked: {
467+ switch(model.type) {
468+ case EmoticonsModel.EmoticonEmoji:
469+ root.emojiSelected(model.key)
470+ emodel.pushToRecent(model.key)
471+ break;
472+
473+ case EmoticonsModel.EmoticonSticker:
474+ root.stickerSelected(model.path)
475+ break;
476+ }
477+ }
478+ }
479+ }
480+
481+ GridView {
482+ id: slist
483+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom; top: separator.bottom }
484+ model: stickers_model
485+ cellWidth: root.width / 4
486+ cellHeight: cellWidth
487+ clip: true
488+ visible: count != 0
489+
490+ delegate: AbstractButton {
491+ width: root.width / 4
492+ height: width
493+
494+ Image {
495+ anchors.fill: parent
496+ anchors.margins: units.gu(0.5)
497+ sourceSize: Qt.size(width, height)
498+ source: sticker_handler.thumbPath
499+ smooth: false
500+ fillMode: Image.PreserveAspectFit
501+ asynchronous: true
502+ }
503+
504+ FileHandler {
505+ id: sticker_handler
506+ target: model.document
507+ telegram: root.telegram
508+ Component.onCompleted: download()
509+ }
510+
511+ onClicked: {
512+ root.stickerDocumentSelected(model.document)
513+ }
514+ }
515+ }
516+
517+ Component {
518+ id: tab_emoji_icon
519+ Rectangle {
520+ id: sitem
521+ anchors.fill: parent
522+ border.width: units.dp(1)
523+ border.color: selected ? UbuntuColors.lightGrey : "transparent"
524+ color: selected ? "#33929292" : "transparent"
525+ property bool selected: stickers_model.currentStickerSet === "" && emodel.currentKey === emodel.keys[index]
526+
527+ property int index
528+
529+ Image {
530+ anchors.fill: parent
531+ anchors.margins: units.gu(.5)
532+ source: emodel.keysIcons[index]
533+ asynchronous: true
534+
535+ AbstractButton {
536+ anchors.fill: parent
537+ onClicked: {
538+ emodel.currentKey = emodel.keys[index]
539+ stickers_model.currentStickerSet = ""
540+ }
541+ }
542+ }
543+ }
544+ }
545+
546+ Component {
547+ id: tab_sticker_icon
548+ Rectangle {
549+ id: sitem
550+ anchors.fill: parent
551+ border.width: units.dp(1)
552+ border.color: selected ? UbuntuColors.lightGrey : "transparent"
553+ color: selected ? "#33929292" : "transparent"
554+ property bool selected: stickers_model.currentStickerSet === currentStickerSet
555+
556+ property Document document
557+ property StickerSet stickerSet
558+ property int index
559+ property string currentStickerSet
560+
561+ Image {
562+ anchors.fill: parent
563+ anchors.margins: units.gu(.5)
564+ source: handler.thumbPath
565+ fillMode: Image.PreserveAspectFit
566+ asynchronous: true
567+
568+ AbstractButton {
569+ anchors.fill: parent
570+ onClicked: {
571+ stickers_model.currentStickerSet = currentStickerSet
572+ }
573+ }
574+ FileHandler {
575+ id: handler
576+ target: sitem.document
577+ telegram: root.telegram
578+ Component.onCompleted: download()
579+ }
580+ }
581+ }
582+ }
583+}
584+
585
586=== added file 'telegram/app/qml/InstallStickerDialog.qml'
587--- telegram/app/qml/InstallStickerDialog.qml 1970-01-01 00:00:00 +0000
588+++ telegram/app/qml/InstallStickerDialog.qml 2016-02-29 10:35:34 +0000
589@@ -0,0 +1,80 @@
590+import QtQuick 2.4
591+import Ubuntu.Components 1.3 as UC
592+import Ubuntu.Components.Popups 1.3 as UCP
593+import AsemanTools 1.0
594+import TelegramQML 1.0
595+import Cutegram 1.0
596+
597+UCP.Dialog {
598+ id: root
599+ title: stickerSet
600+
601+ property alias telegram: smodel.telegram
602+ property alias stickerSet: smodel.currentStickerSet
603+
604+ StickersModel {
605+ id: smodel
606+ }
607+
608+ Connections {
609+ target: telegram
610+ onStickerInstalled: {
611+ if(shortName != stickerSet)
612+ return
613+ if(ok)
614+ close()
615+ }
616+ }
617+
618+ GridView {
619+ id: gridView
620+ width: parent.width
621+ height: units.gu(40)
622+ clip: true
623+
624+ model: smodel
625+
626+ cellWidth: width / 4
627+ cellHeight: cellWidth
628+
629+ delegate: Item {
630+ id: item
631+ width: gridView.cellWidth
632+ height: gridView.cellHeight
633+
634+ property Document document: model.document
635+
636+ FileHandler {
637+ id: handler
638+ target: item.document
639+ telegram: smodel.telegram
640+ Component.onCompleted: download()
641+ }
642+
643+ Image {
644+ anchors.fill: parent
645+ anchors.margins: units.gu(.5)
646+ height: parent.height
647+ width: height
648+ fillMode: Image.PreserveAspectFit
649+ sourceSize: Qt.size(width, height)
650+ source: handler.thumbPath
651+ }
652+ }
653+ }
654+
655+ UC.Button {
656+ text: i18n.tr("Install")
657+ color: UT.UbuntuColors.blue
658+ onClicked: {
659+ telegram.installStickerSet(root.stickerSet)
660+ PopupUtils.close(root)
661+ }
662+ }
663+ UC.Button {
664+ text: i18n.tr("Close")
665+ color: UT.UbuntuColors.orange
666+ onClicked: PopupUtils.close(root)
667+ }
668+}
669+
670
671=== modified file 'telegram/app/qml/components/MessagesListItem.qml'
672--- telegram/app/qml/components/MessagesListItem.qml 2016-02-24 14:17:22 +0000
673+++ telegram/app/qml/components/MessagesListItem.qml 2016-02-29 10:35:34 +0000
674@@ -56,6 +56,7 @@
675 // A link may cause website image preview to show,
676 // but this should not disable showing of message text.
677 property bool hasMedia: message_media.hasMedia && !hasLink
678+ property alias media: message_media.media
679 property alias mediaLocation: message_media.location
680
681 signal dialogRequest(variant dialog);
682
683=== added file 'telegram/app/qml/files/emojis.svg'
684--- telegram/app/qml/files/emojis.svg 1970-01-01 00:00:00 +0000
685+++ telegram/app/qml/files/emojis.svg 2016-02-29 10:35:34 +0000
686@@ -0,0 +1,191 @@
687+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
688+<!-- Created with Inkscape (http://www.inkscape.org/) -->
689+
690+<svg
691+ xmlns:dc="http://purl.org/dc/elements/1.1/"
692+ xmlns:cc="http://creativecommons.org/ns#"
693+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
694+ xmlns:svg="http://www.w3.org/2000/svg"
695+ xmlns="http://www.w3.org/2000/svg"
696+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
697+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
698+ width="96"
699+ height="96"
700+ id="svg4874"
701+ version="1.1"
702+ inkscape:version="0.91 r13725"
703+ viewBox="0 0 96 96.000001"
704+ sodipodi:docname="emojis.svg">
705+ <defs
706+ id="defs4876" />
707+ <sodipodi:namedview
708+ id="base"
709+ pagecolor="#ffffff"
710+ bordercolor="#666666"
711+ borderopacity="1.0"
712+ inkscape:pageopacity="0.0"
713+ inkscape:pageshadow="2"
714+ inkscape:zoom="8.7812488"
715+ inkscape:cx="-26.2662"
716+ inkscape:cy="44.122411"
717+ inkscape:document-units="px"
718+ inkscape:current-layer="g4780"
719+ showgrid="true"
720+ showborder="true"
721+ fit-margin-top="0"
722+ fit-margin-left="0"
723+ fit-margin-right="0"
724+ fit-margin-bottom="0"
725+ inkscape:snap-bbox="true"
726+ inkscape:bbox-paths="true"
727+ inkscape:bbox-nodes="true"
728+ inkscape:snap-bbox-edge-midpoints="true"
729+ inkscape:snap-bbox-midpoints="true"
730+ inkscape:object-paths="true"
731+ inkscape:snap-intersection-paths="true"
732+ inkscape:object-nodes="true"
733+ inkscape:snap-smooth-nodes="true"
734+ inkscape:snap-midpoints="true"
735+ inkscape:snap-object-midpoints="true"
736+ inkscape:snap-center="true"
737+ showguides="true"
738+ inkscape:guide-bbox="true"
739+ inkscape:window-width="2880"
740+ inkscape:window-height="1752"
741+ inkscape:window-x="0"
742+ inkscape:window-y="48"
743+ inkscape:window-maximized="1">
744+ <inkscape:grid
745+ type="xygrid"
746+ id="grid5451"
747+ empspacing="8" />
748+ <sodipodi:guide
749+ orientation="1,0"
750+ position="8,-8.0000001"
751+ id="guide4063" />
752+ <sodipodi:guide
753+ orientation="1,0"
754+ position="4,-8.0000001"
755+ id="guide4065" />
756+ <sodipodi:guide
757+ orientation="0,1"
758+ position="-8,88.000001"
759+ id="guide4067" />
760+ <sodipodi:guide
761+ orientation="0,1"
762+ position="-8,92.000001"
763+ id="guide4069" />
764+ <sodipodi:guide
765+ orientation="0,1"
766+ position="104,4"
767+ id="guide4071" />
768+ <sodipodi:guide
769+ orientation="0,1"
770+ position="-5,8.0000001"
771+ id="guide4073" />
772+ <sodipodi:guide
773+ orientation="1,0"
774+ position="92,-8.0000001"
775+ id="guide4075" />
776+ <sodipodi:guide
777+ orientation="1,0"
778+ position="88,-8.0000001"
779+ id="guide4077" />
780+ <sodipodi:guide
781+ orientation="0,1"
782+ position="-8,84.000001"
783+ id="guide4074" />
784+ <sodipodi:guide
785+ orientation="1,0"
786+ position="12,-8.0000001"
787+ id="guide4076" />
788+ <sodipodi:guide
789+ orientation="0,1"
790+ position="-5,12"
791+ id="guide4078" />
792+ <sodipodi:guide
793+ orientation="1,0"
794+ position="84,-9.0000001"
795+ id="guide4080" />
796+ <sodipodi:guide
797+ position="48,-8.0000001"
798+ orientation="1,0"
799+ id="guide4170" />
800+ <sodipodi:guide
801+ position="-8,48"
802+ orientation="0,1"
803+ id="guide4172" />
804+ </sodipodi:namedview>
805+ <metadata
806+ id="metadata4879">
807+ <rdf:RDF>
808+ <cc:Work
809+ rdf:about="">
810+ <dc:format>image/svg+xml</dc:format>
811+ <dc:type
812+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
813+ <dc:title></dc:title>
814+ </cc:Work>
815+ </rdf:RDF>
816+ </metadata>
817+ <g
818+ inkscape:label="Layer 1"
819+ inkscape:groupmode="layer"
820+ id="layer1"
821+ transform="translate(67.857146,-78.50504)">
822+ <g
823+ transform="matrix(0,-1,-1,0,373.50506,516.50504)"
824+ id="g4845"
825+ style="display:inline">
826+ <g
827+ inkscape:export-ydpi="90"
828+ inkscape:export-xdpi="90"
829+ inkscape:export-filename="next01.png"
830+ transform="matrix(-0.9996045,0,0,1,575.94296,-611.00001)"
831+ id="g4778"
832+ inkscape:label="Layer 1">
833+ <g
834+ transform="matrix(-1,0,0,1,575.99999,611)"
835+ id="g4780"
836+ style="display:inline">
837+ <rect
838+ style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:4;marker:none;enable-background:accumulate"
839+ id="rect4782"
840+ width="96.037987"
841+ height="96"
842+ x="-438.00244"
843+ y="345.36221"
844+ transform="scale(-1,1)" />
845+ <path
846+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:none;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.00079107;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
847+ d="m 432,393.36133 c 0,23.17268 -18.83506,42 -42.01562,42 -23.18057,0 -42.01758,-18.82732 -42.01758,-42 0,-23.17268 18.83701,-42 42.01758,-42 23.18056,0 42.01562,18.82732 42.01562,42 z m -4.00195,0 c 0,-21.00964 -16.99444,-37.99805 -38.01367,-37.99805 -21.01924,0 -38.01563,16.98841 -38.01563,37.99805 0,21.00963 16.99639,38 38.01563,38 21.01923,0 38.01367,-16.99037 38.01367,-38 z"
848+ id="path4116"
849+ inkscape:connector-curvature="0" />
850+ <ellipse
851+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
852+ id="path4175"
853+ cx="-379.36221"
854+ cy="-402.98859"
855+ transform="matrix(0,-1,-1,0,0,0)"
856+ rx="5.0000143"
857+ ry="5.0019927" />
858+ <ellipse
859+ ry="5.0019927"
860+ rx="5.0000143"
861+ transform="matrix(0,-1,-1,0,0,0)"
862+ cy="-402.98859"
863+ cx="-407.36221"
864+ id="ellipse4155"
865+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
866+ <path
867+ transform="matrix(0,-1,-1,0,0,0)"
868+ style="opacity:0.581;fill:none;fill-opacity:1;stroke:#000000;stroke-width:4.00079123;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linecap:round"
869+ d="m -377.2452,-372.85966 c -4.25266,4.25434 -10.12766,6.88571 -16.61701,6.88571 -6.48935,0 -12.36435,-2.63137 -16.61701,-6.88571"
870+ id="path4184"
871+ inkscape:connector-curvature="0"
872+ sodipodi:nodetypes="csc" />
873+ </g>
874+ </g>
875+ </g>
876+ </g>
877+</svg>
878
879=== added file 'telegram/app/qml/files/emoticons-emoji.png'
880Binary files telegram/app/qml/files/emoticons-emoji.png 1970-01-01 00:00:00 +0000 and telegram/app/qml/files/emoticons-emoji.png 2016-02-29 10:35:34 +0000 differ
881=== added file 'telegram/app/qml/files/emoticons-personal.png'
882Binary files telegram/app/qml/files/emoticons-personal.png 1970-01-01 00:00:00 +0000 and telegram/app/qml/files/emoticons-personal.png 2016-02-29 10:35:34 +0000 differ
883=== added file 'telegram/app/qml/files/emoticons-recent.png'
884Binary files telegram/app/qml/files/emoticons-recent.png 1970-01-01 00:00:00 +0000 and telegram/app/qml/files/emoticons-recent.png 2016-02-29 10:35:34 +0000 differ
885=== added file 'telegram/app/qml/files/emoticons-telegram.png'
886Binary files telegram/app/qml/files/emoticons-telegram.png 1970-01-01 00:00:00 +0000 and telegram/app/qml/files/emoticons-telegram.png 2016-02-29 10:35:34 +0000 differ
887=== added file 'telegram/app/stickerfilemanager.cpp'
888--- telegram/app/stickerfilemanager.cpp 1970-01-01 00:00:00 +0000
889+++ telegram/app/stickerfilemanager.cpp 2016-02-29 10:35:34 +0000
890@@ -0,0 +1,117 @@
891+#include "stickerfilemanager.h"
892+#include "asemantools/asemandevices.h"
893+
894+#include <telegramqml.h>
895+#include "../../deps/libqtelegram-ae/telegram.h"
896+
897+#include <QList>
898+#include <QHash>
899+#include <QPointer>
900+#include <QDebug>
901+#include <QDir>
902+#include <QFileInfo>
903+
904+class StickerFileManagerPrivate
905+{
906+public:
907+ QPointer<TelegramQml> telegram;
908+ QHash<qint64, QString> pendind_sticker_upload;
909+};
910+
911+StickerFileManager::StickerFileManager(QObject *parent) :
912+ QObject(parent)
913+{
914+ p = new StickerFileManagerPrivate;
915+}
916+
917+void StickerFileManager::setTelegram(TelegramQml *tg)
918+{
919+ if(p->telegram == tg)
920+ return;
921+ if( !tg && p->telegram )
922+
923+ if(p->telegram)
924+ disconnect(p->telegram , SIGNAL(authLoggedInChanged()), this, SLOT(recheck()));
925+
926+ p->telegram = tg;
927+ if(p->telegram)
928+ connect(p->telegram , SIGNAL(authLoggedInChanged()), this, SLOT(recheck()), Qt::QueuedConnection);
929+
930+ recheck();
931+ emit telegramChanged();
932+}
933+
934+TelegramQml *StickerFileManager::telegram() const
935+{
936+ return p->telegram;
937+}
938+
939+void StickerFileManager::sendSticker(qint64 peerId, const QString &file)
940+{
941+ if(!p->telegram || !p->telegram->authLoggedIn())
942+ return;
943+
944+ QString path = file;
945+ if(path.left(AsemanDevices::localFilesPrePath().size()) == AsemanDevices::localFilesPrePath())
946+ path = path.mid(AsemanDevices::localFilesPrePath().size());
947+
948+ QStringList parts = QFileInfo(file).baseName().split("_", QString::SkipEmptyParts);
949+ if(parts.length() != 2)
950+ {
951+ qint64 id = p->telegram->sendFile(peerId, path);
952+ p->pendind_sticker_upload[id] = path;
953+ }
954+ else
955+ {
956+ InputPeer peer = p->telegram->getInputPeer(peerId);
957+ p->telegram->telegram()->messagesForwardDocument(peer, p->telegram->generateRandomId(),
958+ parts.first().toLongLong(),
959+ parts.last().toLongLong());
960+ }
961+}
962+
963+void StickerFileManager::recheck()
964+{
965+ if(!p->telegram || !p->telegram->authLoggedIn())
966+ return;
967+
968+ connect(p->telegram->telegram(), SIGNAL(messagesSendMediaAnswer(qint64,UpdatesType)),
969+ this, SLOT(messagesSendDocumentAnswer(qint64,UpdatesType)));
970+ connect(p->telegram->telegram(), SIGNAL(messagesSendDocumentAnswer(qint64,UpdatesType)),
971+ this, SLOT(messagesSendDocumentAnswer(qint64,UpdatesType)));
972+}
973+
974+void StickerFileManager::messagesSendDocumentAnswer(qint64 id, const UpdatesType &updates)
975+{
976+ if(!p->pendind_sticker_upload.contains(id))
977+ return;
978+
979+ const QString file = p->pendind_sticker_upload.take(id);
980+
981+
982+ QList<Update> updatesList = updates.updates();
983+ updatesList << updates.update();
984+
985+ Document document;
986+ foreach(const Update &upd, updatesList)
987+ {
988+ const MessageMedia &media = upd.message().media();
989+ if(media.classType() != MessageMedia::typeMessageMediaDocument)
990+ continue;
991+
992+ document = media.document();
993+ }
994+ if(document.classType() == Document::typeDocumentEmpty)
995+ return;
996+
997+ const QString newName = QString("%1_%2.webp").arg(document.id()).arg(document.accessHash());
998+ const QString newPath = QString("%1/%2").arg(QFileInfo(file).dir().path(), newName);
999+
1000+ QFile::rename(file, newPath);
1001+}
1002+
1003+StickerFileManager::~StickerFileManager()
1004+{
1005+ delete p;
1006+}
1007+
1008
1009=== added file 'telegram/app/stickerfilemanager.h'
1010--- telegram/app/stickerfilemanager.h 1970-01-01 00:00:00 +0000
1011+++ telegram/app/stickerfilemanager.h 2016-02-29 10:35:34 +0000
1012@@ -0,0 +1,34 @@
1013+#ifndef STICKERFILEMANAGER_H
1014+#define STICKERFILEMANAGER_H
1015+
1016+#include <QObject>
1017+
1018+class TelegramQml;
1019+class StickerFileManagerPrivate;
1020+class StickerFileManager : public QObject
1021+{
1022+ Q_OBJECT
1023+ Q_PROPERTY(TelegramQml* telegram READ telegram WRITE setTelegram NOTIFY telegramChanged)
1024+
1025+public:
1026+ StickerFileManager(QObject *parent = 0);
1027+ ~StickerFileManager();
1028+
1029+ void setTelegram(TelegramQml *tg);
1030+ TelegramQml *telegram() const;
1031+
1032+public slots:
1033+ void sendSticker(qint64 peerId, const QString &file);
1034+
1035+signals:
1036+ void telegramChanged();
1037+
1038+private slots:
1039+ void recheck();
1040+ void messagesSendDocumentAnswer(qint64 id, const class UpdatesType &updates);
1041+
1042+private:
1043+ StickerFileManagerPrivate *p;
1044+};
1045+
1046+#endif // STICKERFILEMANAGER_H
1047
1048=== modified file 'telegram/app/telegram.cpp'
1049--- telegram/app/telegram.cpp 2015-09-22 09:57:07 +0000
1050+++ telegram/app/telegram.cpp 2016-02-29 10:35:34 +0000
1051@@ -27,6 +27,7 @@
1052 #include "asemantools/asemandevices.h"
1053 #include "asemantools/asemanapplication.h"
1054 #include "emoticonsmodel.h"
1055+#include "stickerfilemanager.h"
1056 #include "themeitem.h"
1057 #include "textemojiwrapper.h"
1058 #include "emojis.h"
1059@@ -187,6 +188,7 @@
1060 qmlRegisterType<TextEmojiWrapper>("Cutegram", 1, 0, "TextEmojiWrapper");
1061 qmlRegisterType<Emojis>("Cutegram", 1, 0, "Emojis");
1062 qmlRegisterType<EmoticonsModel>("Cutegram", 1, 0, "EmoticonsModel");
1063+ qmlRegisterType<StickerFileManager>("Cutegram", 1, 0, "StickerFileManager");
1064
1065 init_languages();
1066 }
1067
1068=== modified file 'telegram/app/telegram.qrc'
1069--- telegram/app/telegram.qrc 2015-11-03 11:06:37 +0000
1070+++ telegram/app/telegram.qrc 2016-02-29 10:35:34 +0000
1071@@ -3,12 +3,9 @@
1072 <file>database/database.sqlite</file>
1073 <file>database/profiles.sqlite</file>
1074 <file>database/userdata.sqlite</file>
1075-
1076 <file>images/telegram.png</file>
1077 <file>images/telegram.svg</file>
1078-
1079 <file>qml/telegram.qml</file>
1080-
1081 <file>qml/AccountAddContactHeader.qml</file>
1082 <file>qml/AccountContactsPage.qml</file>
1083 <file>qml/AccountDialogList.qml</file>
1084@@ -40,7 +37,6 @@
1085 <file>qml/MessageReplyItem.qml</file>
1086 <file>qml/ProfilePage.qml</file>
1087 <file>qml/TagSuggestionMenu.qml</file>
1088-
1089 <file>qml/components/AccountPanel.qml</file>
1090 <file>qml/components/AccountPanelItem.qml</file>
1091 <file>qml/components/AttachPanel.qml</file>
1092@@ -66,17 +62,13 @@
1093 <file>qml/components/TelegramContactsListItem.qml</file>
1094 <file>qml/components/TelegramHeader.qml</file>
1095 <file>qml/components/TelegramPage.qml</file>
1096-
1097 <file>qml/components/listitems/ListItemWithActions.qml</file>
1098 <file>qml/components/listitems/ListItemWithActionsCheckBox.qml</file>
1099-
1100 <file>qml/js/avatar.js</file>
1101 <file>qml/js/ba-linkify.js</file>
1102 <file>qml/js/colors.js</file>
1103 <file>qml/js/time.js</file>
1104 <file>qml/js/version.js</file>
1105-
1106-
1107 <file>qml/files/attach_document.png</file>
1108 <file>qml/files/attach_gallery.png</file>
1109 <file>qml/files/attach_location.png</file>
1110@@ -140,18 +132,22 @@
1111 <file>qml/files/user_red.png</file>
1112 <file>qml/files/user_violet.png</file>
1113 <file>qml/files/user_yellow.png</file>
1114-
1115 <file>qml/files/android/attach_camera.png</file>
1116 <file>qml/files/android/attach_gallery.png</file>
1117 <file>qml/files/android/attach_video.png</file>
1118 <file>qml/files/android/attach_file.png</file>
1119 <file>qml/files/android/attach_hide1.png</file>
1120 <file>qml/files/android/attach_hide2.png</file>
1121-
1122 <file>qml/ui/dialogs/ConfirmationDialog.qml</file>
1123 <file>qml/PickerPage.qml</file>
1124 <file>qml/PreviewPage.qml</file>
1125 <file>qml/UserNameSuggestionMenu.qml</file>
1126+ <file>qml/Emoticons.qml</file>
1127+ <file>qml/files/emoticons-emoji.png</file>
1128+ <file>qml/files/emoticons-personal.png</file>
1129+ <file>qml/files/emoticons-recent.png</file>
1130+ <file>qml/files/emoticons-telegram.png</file>
1131+ <file>qml/files/emojis.svg</file>
1132+ <file>qml/InstallStickerDialog.qml</file>
1133 </qresource>
1134 </RCC>
1135-

Subscribers

People subscribed via source and target branches

to status/vote changes: