legacyMessaging.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-FileCopyrightText: GSConnect Developers https://github.com/GSConnect
  2. //
  3. // SPDX-License-Identifier: GPL-2.0-or-later
  4. 'use strict';
  5. const Gio = imports.gi.Gio;
  6. const GObject = imports.gi.GObject;
  7. const Gtk = imports.gi.Gtk;
  8. const Contacts = imports.service.ui.contacts;
  9. const Messaging = imports.service.ui.messaging;
  10. const URI = imports.service.utils.uri;
  11. const _ui = imports.service.utils.ui;
  12. var Dialog = GObject.registerClass({
  13. GTypeName: 'GSConnectLegacyMessagingDialog',
  14. Properties: {
  15. 'device': GObject.ParamSpec.object(
  16. 'device',
  17. 'Device',
  18. 'The device associated with this window',
  19. GObject.ParamFlags.READWRITE,
  20. GObject.Object
  21. ),
  22. 'plugin': GObject.ParamSpec.object(
  23. 'plugin',
  24. 'Plugin',
  25. 'The plugin providing messages',
  26. GObject.ParamFlags.READWRITE,
  27. GObject.Object
  28. ),
  29. },
  30. Template: 'resource:///org/gnome/Shell/Extensions/GSConnect/ui/legacy-messaging-dialog.ui',
  31. Children: [
  32. 'infobar', 'stack',
  33. 'message-box', 'message-avatar', 'message-label', 'entry',
  34. ],
  35. }, class Dialog extends Gtk.Dialog {
  36. _init(params) {
  37. super._init({
  38. application: Gio.Application.get_default(),
  39. device: params.device,
  40. plugin: params.plugin,
  41. use_header_bar: true,
  42. });
  43. this.set_response_sensitive(Gtk.ResponseType.OK, false);
  44. // Dup some functions
  45. this.headerbar = this.get_titlebar();
  46. this._setHeaderBar = Messaging.Window.prototype._setHeaderBar;
  47. // Info bar
  48. this.device.bind_property(
  49. 'connected',
  50. this.infobar,
  51. 'reveal-child',
  52. GObject.BindingFlags.INVERT_BOOLEAN
  53. );
  54. // Message Entry/Send Button
  55. this.device.bind_property(
  56. 'connected',
  57. this.entry,
  58. 'sensitive',
  59. GObject.BindingFlags.DEFAULT
  60. );
  61. this._connectedId = this.device.connect(
  62. 'notify::connected',
  63. this._onStateChanged.bind(this)
  64. );
  65. this._entryChangedId = this.entry.buffer.connect(
  66. 'changed',
  67. this._onStateChanged.bind(this)
  68. );
  69. // Set the message if given
  70. if (params.message) {
  71. this.message = params.message;
  72. this.addresses = params.message.addresses;
  73. this.message_avatar.contact = this.device.contacts.query({
  74. number: this.addresses[0].address,
  75. });
  76. this.message_label.label = URI.linkify(this.message.body);
  77. this.message_box.visible = true;
  78. // Otherwise set the address(es) if we were passed those
  79. } else if (params.addresses) {
  80. this.addresses = params.addresses;
  81. }
  82. // Load the contact list if we weren't supplied with an address
  83. if (this.addresses.length === 0) {
  84. this.contact_chooser = new Contacts.ContactChooser({
  85. device: this.device,
  86. });
  87. this.stack.add_named(this.contact_chooser, 'contact-chooser');
  88. this.stack.child_set_property(this.contact_chooser, 'position', 0);
  89. this._numberSelectedId = this.contact_chooser.connect(
  90. 'number-selected',
  91. this._onNumberSelected.bind(this)
  92. );
  93. this.stack.visible_child_name = 'contact-chooser';
  94. }
  95. this.restoreGeometry('legacy-messaging-dialog');
  96. this.connect('destroy', this._onDestroy);
  97. }
  98. _onDestroy(dialog) {
  99. if (dialog._numberSelectedId !== undefined) {
  100. dialog.contact_chooser.disconnect(dialog._numberSelectedId);
  101. dialog.contact_chooser.destroy();
  102. }
  103. dialog.entry.buffer.disconnect(dialog._entryChangedId);
  104. dialog.device.disconnect(dialog._connectedId);
  105. }
  106. vfunc_delete_event() {
  107. this.saveGeometry();
  108. return false;
  109. }
  110. vfunc_response(response_id) {
  111. if (response_id === Gtk.ResponseType.OK) {
  112. // Refuse to send empty or whitespace only texts
  113. if (!this.entry.buffer.text.trim())
  114. return;
  115. this.plugin.sendMessage(
  116. this.addresses,
  117. this.entry.buffer.text,
  118. 1,
  119. true
  120. );
  121. }
  122. this.destroy();
  123. }
  124. get addresses() {
  125. if (this._addresses === undefined)
  126. this._addresses = [];
  127. return this._addresses;
  128. }
  129. set addresses(addresses = []) {
  130. this._addresses = addresses;
  131. // Set the headerbar
  132. this._setHeaderBar(this._addresses);
  133. // Show the message editor
  134. this.stack.visible_child_name = 'message-editor';
  135. this._onStateChanged();
  136. }
  137. get device() {
  138. if (this._device === undefined)
  139. this._device = null;
  140. return this._device;
  141. }
  142. set device(device) {
  143. this._device = device;
  144. }
  145. get plugin() {
  146. if (this._plugin === undefined)
  147. this._plugin = null;
  148. return this._plugin;
  149. }
  150. set plugin(plugin) {
  151. this._plugin = plugin;
  152. }
  153. _onActivateLink(label, uri) {
  154. Gtk.show_uri_on_window(
  155. this.get_toplevel(),
  156. uri.includes('://') ? uri : `https://${uri}`,
  157. Gtk.get_current_event_time()
  158. );
  159. return true;
  160. }
  161. _onNumberSelected(chooser, number) {
  162. const contacts = chooser.getSelected();
  163. this.addresses = Object.keys(contacts).map(address => {
  164. return {address: address};
  165. });
  166. }
  167. _onStateChanged() {
  168. if (this.device.connected &&
  169. this.entry.buffer.text.trim() &&
  170. this.stack.visible_child_name === 'message-editor')
  171. this.set_response_sensitive(Gtk.ResponseType.OK, true);
  172. else
  173. this.set_response_sensitive(Gtk.ResponseType.OK, false);
  174. }
  175. /**
  176. * Set the contents of the message entry
  177. *
  178. * @param {string} text - The message to place in the entry
  179. */
  180. setMessage(text) {
  181. this.entry.buffer.text = text;
  182. }
  183. });