'use strict'; (function() { var weechat = angular.module('weechat'); weechat.factory('neoContextMenu', ['$rootScope', 'connection', 'models', function($rootScope, connection, models) { var menu = {visible: false, actions: [], position: {}, label: ''}; var send = function(buffer, command) { connection.sendMessageToBuffer(buffer.id, command); }; var action = function(id, label, run, destructive) { return {id: id, label: label, run: run, destructive: Boolean(destructive)}; }; var safeNick = function(value) { return /^[A-Za-z0-9[\]\\`_^{|}-]+$/.test(value || ''); }; function bufferActions(buffer) { var actions = []; var core = buffer.fullName === 'core.weechat'; if (buffer.type === 'server' && buffer.plugin === 'irc') { actions.push(action('edit-server', 'Edit server settings', function() { $rootScope.$broadcast('neoServerManagerOpen', buffer.server || buffer.shortName); })); actions.push(action('connect', 'Connect', function() { send(buffer, '/connect ' + buffer.server); })); actions.push(action('disconnect', 'Disconnect', function() { send(buffer, '/disconnect ' + buffer.server); }, true)); } if (buffer.type === 'channel' && buffer.plugin === 'irc') { actions.push(action('mute', 'Mute activity', function() { send(buffer, '/buffer notify none'); })); actions.push(action('unmute', 'Unmute activity', function() { send(buffer, '/buffer notify all'); })); actions.push(action('part', 'Part channel', function() { send(buffer, '/part'); }, true)); actions.push(action('rejoin', 'Rejoin channel', function() { send(buffer, '/join'); })); actions.push(action('autojoin-add', 'Add to auto-join', function() { send(buffer, '/autojoin add'); })); actions.push(action('autojoin-del', 'Remove from auto-join', function() { send(buffer, '/autojoin del'); })); } if (/neodrop_manager/.test(buffer.fullName)) { actions.push(action('drops-list', 'Refresh drops', function() { send(buffer, '/drops list'); })); actions.push(action('drops-help', 'NeoDrop help', function() { send(buffer, '/drops help'); })); } if (/neoguard/.test(buffer.fullName)) { actions.push(action('guard-status', 'Refresh NeoGuard', function() { send(buffer, '/neoguard status'); })); actions.push(action('guard-help', 'NeoGuard help', function() { send(buffer, '/neoguard'); })); } actions.push(action('clear', 'Clear buffer', function() { send(buffer, '/buffer clear'); })); if (!core) actions.push(action('close', 'Close buffer', function() { if (window.confirm('Close ' + (buffer.shortName || buffer.fullName) + '?')) send(buffer, '/buffer close'); }, true)); return actions; } function nickActions(target) { var nick = target.nick.name; var buffer = target.buffer; if (!safeNick(nick) || !buffer || buffer.plugin !== 'irc') return []; var actions = [ action('dm', 'Direct message', function() { var prefix = buffer.fullName.substring(0, buffer.fullName.lastIndexOf('.') + 1); if (!models.setActiveBuffer(prefix + nick, 'fullName')) { models.outgoingQueries.push(nick); send(buffer, '/query -noswitch ' + nick); } }), action('whois', 'Whois', function() { send(buffer, '/whois ' + nick); }) ]; if (buffer.type === 'channel') { actions.push(action('op', 'Give operator', function() { send(buffer, '/mode +o ' + nick); })); actions.push(action('halfop', 'Give half-operator', function() { send(buffer, '/mode +h ' + nick); })); actions.push(action('voice', 'Give voice', function() { send(buffer, '/mode +v ' + nick); })); actions.push(action('kick', 'Kick', function() { if (window.confirm('Kick ' + nick + '?')) send(buffer, '/kick ' + nick); }, true)); actions.push(action('ban', 'Ban', function() { if (window.confirm('Ban ' + nick + '?')) send(buffer, '/ban ' + nick); }, true)); } return actions; } return { menu: menu, open: function(event, target) { var actions = target.kind === 'nick' ? nickActions(target) : bufferActions(target.buffer); if (!actions.length) return; menu.actions = actions; menu.label = target.kind === 'nick' ? 'Actions for ' + target.nick.name : 'Buffer actions'; menu.position = {left: Math.min(event.clientX, window.innerWidth - 230) + 'px', top: Math.min(event.clientY, window.innerHeight - 360) + 'px'}; menu.visible = true; }, close: function() { menu.visible = false; }, run: function(item) { menu.visible = false; item.run(); } }; }]); weechat.directive('neoContext', ['neoContextMenu', function(neoContextMenu) { return {restrict: 'A', link: function(scope, element, attrs) { var open = function(event) { event.preventDefault(); event.stopPropagation(); scope.$apply(function() { neoContextMenu.open(event, scope.$eval(attrs.neoContext)); }); }; element.on('contextmenu', open); scope.$on('$destroy', function() { element.off('contextmenu', open); }); }}; }]); weechat.directive('neoContextMenuView', ['neoContextMenu', '$document', function(neoContextMenu, $document) { return {restrict: 'E', templateUrl: 'directives/context-menu.html', link: function(scope) { scope.menu = neoContextMenu.menu; scope.runContextAction = neoContextMenu.run; var close = function(event) { if (scope.menu.visible && !event.target.closest('.neo-context-menu')) scope.$apply(neoContextMenu.close); }; $document.on('mousedown', close); scope.$on('$destroy', function() { $document.off('mousedown', close); }); }}; }]); }());