Forked mumble-django project from https://bitbucket.org/Svedrin/mumble-django
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
9.1 KiB

  1. // kate: space-indent on; indent-width 4; replace-tabs on;
  2. Ext.namespace('Ext.ux');
  3. Ext.ux.MumbleChannelNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
  4. renderElements : function(n, a, targetNode, bulkRender){
  5. Ext.ux.MumbleUserNodeUI.superclass.renderElements.call( this, n, a, targetNode, bulkRender );
  6. Ext.DomHelper.applyStyles( this.elNode, 'position: relative' );
  7. var tpl = new Ext.DomHelper.createTemplate(
  8. '<img style="position: absolute; top: 0px; right: {pos}px;" src="{imageurl}/{icon}.png"/>'
  9. );
  10. var icons = []
  11. if( a.chandata.description != "" ) icons.push( "comment_seen" );
  12. var pos = 8;
  13. for( var i = 0; i < icons.length; i++ ){
  14. tpl.append( this.elNode, {'imageurl': a.imageurl, 'icon': icons[i], 'pos': pos} );
  15. pos += 18
  16. }
  17. }
  18. });
  19. Ext.ux.MumbleUserNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
  20. renderElements : function(n, a, targetNode, bulkRender){
  21. Ext.ux.MumbleUserNodeUI.superclass.renderElements.call( this, n, a, targetNode, bulkRender );
  22. Ext.DomHelper.applyStyles( this.elNode, 'position: relative' );
  23. var tpl = new Ext.DomHelper.createTemplate(
  24. '<img style="position: absolute; top: 0px; right: {pos}px;" src="{imageurl}/{icon}.png"/>'
  25. );
  26. var icons = []
  27. if( a.userdata.userid != -1 ) icons.push( "authenticated" );
  28. if( a.userdata.selfDeaf ) icons.push( "deafened_self" );
  29. if( a.userdata.deaf ) icons.push( "deafened_server" );
  30. if( a.userdata.selfMute ) icons.push( "muted_self" );
  31. if( a.userdata.suppress ) icons.push( "muted_suppressed" );
  32. if( a.userdata.mute ) icons.push( "muted_server" );
  33. if( a.userdata.comment != "" ) icons.push( "comment_seen" );
  34. if( a.userdata.prioritySpeaker ) icons.push( "priority_speaker" );
  35. var pos = 8;
  36. for( var i = 0; i < icons.length; i++ ){
  37. tpl.append( this.elNode, {'imageurl': a.imageurl, 'icon': icons[i], 'pos': pos} );
  38. pos += 18
  39. }
  40. }
  41. });
  42. function cmp_channels( left, rite ){
  43. // Compare two channels, first by position, and if that equals, by name.
  44. if( typeof left.position != "undefined" && typeof rite.position != "undefined" ){
  45. byorder = left.position - rite.position;
  46. if( byorder != 0 )
  47. return byorder;
  48. }
  49. return left.name.localeCompare(rite.name);
  50. }
  51. function cmp_names( left, rite ){
  52. return left.name.localeCompare(rite.name);
  53. }
  54. Ext.ux.MumbleChannelViewer = function( config ){
  55. Ext.apply( this, config );
  56. Ext.applyIf( this, {
  57. title: gettext("Channel Viewer"),
  58. refreshInterval: 10000,
  59. idleInterval: 2,
  60. autoScroll: true,
  61. enableDD: false, // Users need to enable this explicitly
  62. root: {
  63. text: gettext("Loading..."),
  64. leaf: true
  65. },
  66. listeners: {}
  67. });
  68. Ext.applyIf( this.listeners, {
  69. dragdrop: function( tree, node, targetdd, ev ){
  70. if( typeof node.attributes.userdata != "undefined" )
  71. tree.fireEvent("moveUser", tree, node.attributes.userdata, targetdd.dragOverData.target.attributes.chandata);
  72. else if( typeof node.attributes.chandata != "undefined" )
  73. tree.fireEvent("moveChannel", tree, node.attributes.chandata, targetdd.dragOverData.target.attributes.chandata);
  74. }
  75. });
  76. Ext.applyIf( this, {
  77. // This stuff needs the above applied already
  78. bbar: [ gettext("Auto-Refresh")+':', {
  79. xtype: "checkbox",
  80. ref: "../cbAutoRefresh",
  81. scope: this,
  82. handler: this.setAutoRefresh,
  83. checked: (this.refreshInterval > 0),
  84. }, {
  85. xtype: "numberfield",
  86. width: 30,
  87. value: this.refreshInterval / 1000,
  88. ref: "../nfAutoRefreshInterval",
  89. scope: this,
  90. selectOnFocus: true,
  91. listeners: {
  92. render: function(c) {
  93. Ext.QuickTips.register({
  94. target: c.getEl(),
  95. text: gettext('Enter the interval in seconds in which the channel viewer should refresh and hit Enter.')
  96. });
  97. },
  98. specialkey: function( field, ev ){
  99. if( ev.getKey() == ev.ENTER ){
  100. this.scope.setAutoRefresh(); // lawl
  101. this.blur();
  102. }
  103. }
  104. },
  105. }, gettext("Seconds"), '->', {
  106. xtype: "button",
  107. text: gettext("Refresh"),
  108. handler: this.refresh,
  109. scope: this
  110. }]
  111. } );
  112. Ext.ux.MumbleChannelViewer.superclass.constructor.call( this );
  113. this.addEvents({
  114. 'moveUser': true,
  115. 'moveChannel': true
  116. });
  117. this.autoRefreshId = 0;
  118. this.setAutoRefresh();
  119. }
  120. Ext.extend( Ext.ux.MumbleChannelViewer, Ext.tree.TreePanel, {
  121. setAutoRefresh: function(){
  122. if( this.autoRefreshId != 0 ){
  123. clearTimeout( this.autoRefreshId );
  124. }
  125. if( this.cbAutoRefresh.getValue() ){
  126. this.refreshInterval = this.nfAutoRefreshInterval.getValue() * 1000;
  127. this.autoRefresh();
  128. }
  129. else{
  130. this.refreshInterval = 0;
  131. }
  132. },
  133. autoRefresh: function(){
  134. this.refresh();
  135. if( this.refreshInterval > 0 ){
  136. this.autoRefreshId = this.autoRefresh.defer( this.refreshInterval, this );
  137. }
  138. },
  139. refresh: function(){
  140. var conn = new Ext.data.Connection();
  141. conn.request({
  142. url: this.source_url,
  143. scope: this,
  144. success: function( resp, opt ){
  145. var respdata = Ext.decode( resp.responseText );
  146. var root = {
  147. text: respdata.name,
  148. nodeType: 'async',
  149. id: "mumbroot",
  150. leaf: false,
  151. icon: this.imageurl+'/mumble.16x16.png',
  152. children: [],
  153. imageurl: this.imageurl
  154. };
  155. tree = this;
  156. function populateNode( node, json ){
  157. var subchan_users = 0;
  158. json.channels.sort(cmp_channels);
  159. for( var i = 0; i < json.channels.length; i++ ){
  160. var child = {
  161. text: json.channels[i].name,
  162. id: ("channel_" + json.channels[i].id),
  163. nodeType: 'async',
  164. allowDrag: true,
  165. allowDrop: true,
  166. draggable: true,
  167. icon: tree.imageurl+'/channel.png',
  168. children: [],
  169. uiProvider: Ext.ux.MumbleChannelNodeUI,
  170. chandata: json.channels[i],
  171. imageurl: tree.imageurl
  172. };
  173. node.children.push( child );
  174. subchan_users += populateNode( child, json.channels[i] );
  175. }
  176. json.users.sort(cmp_names);
  177. for( var i = 0; i < json.users.length; i++ ){
  178. var child = {
  179. text: json.users[i].name,
  180. id: ("user_" + json.users[i].session),
  181. nodeType: 'async',
  182. leaf: true,
  183. allowDrag: true,
  184. draggable: true,
  185. uiProvider: Ext.ux.MumbleUserNodeUI,
  186. userdata: json.users[i],
  187. imageurl: tree.imageurl
  188. };
  189. if( json.users[i].idlesecs <= this.idleInterval )
  190. child.icon = tree.imageurl+'/talking_on.png';
  191. else
  192. child.icon = tree.imageurl+'/talking_off.png';
  193. node.leaf = false;
  194. node.children.push( child );
  195. }
  196. if( json.id == 0 || json.users.length > 0 || subchan_users )
  197. node.expanded = true;
  198. return subchan_users + json.users.length;
  199. }
  200. populateNode( root, respdata.root );
  201. this.setRootNode( root );
  202. },
  203. failure: function( resp, opt ){
  204. if( this.refreshInterval > 0 )
  205. this.cbAutoRefresh.setValue(false);
  206. Ext.Msg.show({
  207. title: gettext("Update error"),
  208. msg: gettext("Querying the server failed, so the channel viewer has not been updated."),
  209. icon: Ext.MessageBox.ERROR,
  210. buttons: Ext.MessageBox.OK
  211. });
  212. },
  213. });
  214. },
  215. } );
  216. Ext.reg( 'mumblechannelviewer', Ext.ux.MumbleChannelViewer );