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.
 
 
 

209 lines
5.0 KiB

  1. define([
  2. 'html!ui/templates/messages/tplTab'
  3. ], function (
  4. tplTab
  5. ) {
  6. const extensionObj = {
  7. processChat: function (msgConfig) {
  8. const { message, event: keyboardEvent } = msgConfig;
  9. const { key } = keyboardEvent;
  10. const { el, currentChannel } = this;
  11. const optionContainer = this.find('.channelOptions');
  12. if (message.length) {
  13. if (el.hasClass('picking'))
  14. msgConfig.cancel = true;
  15. return;
  16. }
  17. if (key === 'Enter') {
  18. const selectedSubPick = optionContainer.find('.option.selected');
  19. if (selectedSubPick.length) {
  20. this.onPickSubChannel(selectedSubPick.html(), currentChannel);
  21. return;
  22. }
  23. }
  24. //If we're busy picking a sub channel, we can use keyboard nav
  25. const isPicking = el.hasClass('picking');
  26. const currentSelection = optionContainer.find('.option.selected');
  27. if (isPicking && currentSelection.length) {
  28. const delta = {
  29. ArrowUp: -1,
  30. ArrowDown: 1
  31. }[key];
  32. if (delta) {
  33. const options = optionContainer.find('.option');
  34. const currentIndex = currentSelection.eq(0).index();
  35. let nextIndex = (currentIndex + delta) % options.length;
  36. currentSelection.removeClass('selected');
  37. options.eq(nextIndex).addClass('selected');
  38. }
  39. }
  40. const pick = {
  41. '%': 'party',
  42. '!': 'global',
  43. $: 'custom',
  44. '@': 'direct'
  45. }[key];
  46. if (!pick) {
  47. if (isPicking)
  48. msgConfig.cancel = true;
  49. return;
  50. }
  51. if (currentChannel === pick) {
  52. if (pick === 'direct')
  53. this.lastPrivateChannel = null;
  54. else if (pick === 'custom')
  55. this.lastCustomChannel = null;
  56. }
  57. this.onPickChannel(pick, true);
  58. msgConfig.cancel = true;
  59. },
  60. onPickChannel: function (channel, autoPickSub) {
  61. this.currentChannel = channel;
  62. this.currentSubChannel = null;
  63. const showSubChannels = (
  64. ['direct', 'custom'].includes(channel) &&
  65. (
  66. !autoPickSub ||
  67. (
  68. channel === 'direct' &&
  69. !this.lastPrivateChannel
  70. ) ||
  71. (
  72. channel === 'custom' &&
  73. !this.lastCustomChannel
  74. )
  75. )
  76. );
  77. if (!showSubChannels) {
  78. this.find('.channelOptions').removeClass('active');
  79. let showValue = {
  80. direct: this.lastPrivateChannel,
  81. custom: this.lastCustomChannel
  82. }[channel];
  83. if (channel === 'direct' || channel === 'custom')
  84. this.currentSubChannel = showValue;
  85. showValue = showValue || channel;
  86. this.find('.channelPicker').html(showValue);
  87. this.find('input').focus();
  88. this.el.removeClass('picking');
  89. } else
  90. this.onShowChannelOptions(channel);
  91. },
  92. onPickSubChannel: function (subChannel, channel) {
  93. this.currentSubChannel = subChannel;
  94. this.find('.channelOptions').removeClass('active');
  95. this.find('.channelPicker').html(subChannel);
  96. const elInput = this.find('input');
  97. elInput.focus();
  98. if (channel === 'custom') {
  99. if (subChannel === 'join new') {
  100. elInput.val('/join channelName');
  101. elInput[0].setSelectionRange(6, 17);
  102. } else if (subChannel === 'leave') {
  103. elInput.val('/leave channelName');
  104. elInput[0].setSelectionRange(7, 18);
  105. }
  106. }
  107. this.el.removeClass('picking');
  108. },
  109. onShowChannelOptions: function (currentPick) {
  110. const optionContainer = this.find('.channelOptions')
  111. .addClass('active')
  112. .empty();
  113. const options = [];
  114. let handlerOnClick = this.onPickChannel;
  115. this.el.addClass('picking');
  116. if (!currentPick) {
  117. options.push('global', 'custom');
  118. if (this.privateChannels.length)
  119. options.push('direct');
  120. //Hack...surely we can find a more sane way to do this
  121. if ($('.uiParty .member').length)
  122. options.push('party');
  123. } else {
  124. handlerOnClick = this.onPickSubChannel;
  125. if (currentPick === 'direct')
  126. options.push(...this.privateChannels);
  127. else if (currentPick === 'custom')
  128. options.push(...this.customChannels, 'join new', 'leave');
  129. }
  130. if (!options.length) {
  131. this.onPickChannel('global');
  132. return;
  133. }
  134. let addSelectStyleTo = null;
  135. if (currentPick)
  136. addSelectStyleTo = this.currentSubChannel || options[0];
  137. options.forEach(o => {
  138. const shortcut = {
  139. global: ' (!)',
  140. direct: ' (@)',
  141. party: ' (%)',
  142. custom: ' ($)'
  143. }[o] || '';
  144. const html = `<div class='option' shortcut='${shortcut}'>${o}</div>`;
  145. const el = $(html)
  146. .appendTo(optionContainer)
  147. .on('click', handlerOnClick.bind(this, o, currentPick))
  148. .on('hover', this.stopKeyboardNavForOptions.bind(this));
  149. if (o === addSelectStyleTo)
  150. el.addClass('selected');
  151. });
  152. },
  153. stopKeyboardNavForOptions: function () {
  154. this.find('.channelOptions .option.selected').removeClass('selected');
  155. }
  156. };
  157. return {
  158. init: function () {
  159. $.extend(this, extensionObj);
  160. //This whole hoverFilter business is a filthy hack
  161. this.find('.channelPicker, .channelOptions, .filter:not(.channel)')
  162. .on('mouseover', this.onFilterHover.bind(this, true))
  163. .on('mouseleave', this.onFilterHover.bind(this, false));
  164. this.find('.channelPicker').on('click', this.onShowChannelOptions.bind(this, null));
  165. }
  166. };
  167. });