Added an option for mass channel subscription and unsubscription
parent
3ec0f32634
commit
6f460ae111
|
@ -2,6 +2,7 @@
|
||||||
* **04.12.20**
|
* **04.12.20**
|
||||||
- Properly logging channel creations, deletions, shows and hides
|
- Properly logging channel creations, deletions, shows and hides
|
||||||
- Fixed missing collapsed arrow update after channel move
|
- Fixed missing collapsed arrow update after channel move
|
||||||
|
- Added an option for mass channel subscription and unsubscription
|
||||||
|
|
||||||
* **03.12.20**
|
* **03.12.20**
|
||||||
- Fixed server connection tab move handler
|
- Fixed server connection tab move handler
|
||||||
|
|
|
@ -753,14 +753,16 @@ export class ChannelEntry extends ChannelTreeEntry<ChannelEvents> {
|
||||||
return this.subscriptionMode;
|
return this.subscriptionMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubscriptionMode(mode: ChannelSubscribeMode) {
|
setSubscriptionMode(mode: ChannelSubscribeMode, dontSyncSubscribeMode?: boolean) {
|
||||||
if(this.subscriptionMode === mode) {
|
if(this.subscriptionMode === mode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.subscriptionMode = mode;
|
this.subscriptionMode = mode;
|
||||||
this.channelTree.client.settings.changeServer(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId), mode);
|
this.channelTree.client.settings.changeServer(Settings.FN_SERVER_CHANNEL_SUBSCRIBE_MODE(this.channelId), mode);
|
||||||
this.updateSubscribeMode().then(undefined);
|
if(!dontSyncSubscribeMode) {
|
||||||
|
this.updateSubscribeMode().then(undefined);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_data() : EventChannelData {
|
log_data() : EventChannelData {
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {MenuEntryType} from "tc-shared/ui/elements/ContextMenu";
|
||||||
import * as log from "tc-shared/log";
|
import * as log from "tc-shared/log";
|
||||||
import {LogCategory, logError, logWarn} from "tc-shared/log";
|
import {LogCategory, logError, logWarn} from "tc-shared/log";
|
||||||
import {PermissionType} from "tc-shared/permission/PermissionType";
|
import {PermissionType} from "tc-shared/permission/PermissionType";
|
||||||
import {SpecialKey} from "tc-shared/PPTListener";
|
|
||||||
import {Sound} from "tc-shared/sound/Sounds";
|
import {Sound} from "tc-shared/sound/Sounds";
|
||||||
import {Group} from "tc-shared/permission/GroupManager";
|
import {Group} from "tc-shared/permission/GroupManager";
|
||||||
import {ServerAddress, ServerEntry} from "./Server";
|
import {ServerAddress, ServerEntry} from "./Server";
|
||||||
|
@ -15,7 +14,6 @@ import {createChannelModal} from "tc-shared/ui/modal/ModalCreateChannel";
|
||||||
import {Registry} from "tc-shared/events";
|
import {Registry} from "tc-shared/events";
|
||||||
import * as ReactDOM from "react-dom";
|
import * as ReactDOM from "react-dom";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as ppt from "tc-backend/ppt";
|
|
||||||
|
|
||||||
import {batch_updates, BatchUpdateType, flush_batched_updates} from "tc-shared/ui/react-elements/ReactComponentBase";
|
import {batch_updates, BatchUpdateType, flush_batched_updates} from "tc-shared/ui/react-elements/ReactComponentBase";
|
||||||
import {createInputModal} from "tc-shared/ui/elements/Modal";
|
import {createInputModal} from "tc-shared/ui/elements/Modal";
|
||||||
|
@ -23,11 +21,10 @@ import {spawnBanClient} from "tc-shared/ui/modal/ModalBanClient";
|
||||||
import {formatMessage} from "tc-shared/ui/frames/chat";
|
import {formatMessage} from "tc-shared/ui/frames/chat";
|
||||||
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo";
|
||||||
import {tra} from "tc-shared/i18n/localize";
|
import {tra} from "tc-shared/i18n/localize";
|
||||||
import {EventType} from "tc-shared/ui/frames/log/Definitions";
|
|
||||||
import {renderChannelTree} from "tc-shared/ui/tree/Controller";
|
import {renderChannelTree} from "tc-shared/ui/tree/Controller";
|
||||||
import {ChannelTreePopoutController} from "tc-shared/ui/tree/popout/Controller";
|
import {ChannelTreePopoutController} from "tc-shared/ui/tree/popout/Controller";
|
||||||
import {Settings, settings} from "tc-shared/settings";
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
import {ServerConnection} from "tc-backend/web/connection/ServerConnection";
|
import {ClientIcon} from "svg-sprites/client-icons";
|
||||||
|
|
||||||
export interface ChannelTreeEvents {
|
export interface ChannelTreeEvents {
|
||||||
/* general tree notified */
|
/* general tree notified */
|
||||||
|
@ -536,7 +533,7 @@ export class ChannelTree {
|
||||||
const server = entries.find(e => e instanceof ServerEntry) as ServerEntry;
|
const server = entries.find(e => e instanceof ServerEntry) as ServerEntry;
|
||||||
|
|
||||||
let client_menu: contextmenu.MenuEntry[];
|
let client_menu: contextmenu.MenuEntry[];
|
||||||
let channel_menu: contextmenu.MenuEntry[];
|
let channelMenu: contextmenu.MenuEntry[];
|
||||||
let server_menu: contextmenu.MenuEntry[];
|
let server_menu: contextmenu.MenuEntry[];
|
||||||
|
|
||||||
if(clients.length > 0) {
|
if(clients.length > 0) {
|
||||||
|
@ -681,11 +678,87 @@ export class ChannelTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(channels.length > 0) {
|
if(channels.length > 0) {
|
||||||
channel_menu = [];
|
channelMenu = [];
|
||||||
|
|
||||||
|
channelMenu.push({
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Subscribe to channels"),
|
||||||
|
icon_class: ClientIcon.SubscribeToAllChannels,
|
||||||
|
callback: () => {
|
||||||
|
const bulks = channels.filter(channel => {
|
||||||
|
channel.setSubscriptionMode(ChannelSubscribeMode.SUBSCRIBED, false);
|
||||||
|
return !channel.isSubscribed();
|
||||||
|
}).map(channel => {
|
||||||
|
return {
|
||||||
|
cid: channel.channelId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if(bulks.length === 0) {
|
||||||
|
/* shall not happen */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client.serverConnection.send_command("channelsubscribe", bulks);
|
||||||
|
},
|
||||||
|
visible: channels.findIndex(channel => channel.getSubscriptionMode() !== ChannelSubscribeMode.SUBSCRIBED) !== -1
|
||||||
|
});
|
||||||
|
|
||||||
|
channelMenu.push({
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Unsubscribe from channels"),
|
||||||
|
icon_class: ClientIcon.UnsubscribeFromAllChannels,
|
||||||
|
callback: () => {
|
||||||
|
const bulks = channels.filter(channel => {
|
||||||
|
channel.setSubscriptionMode(ChannelSubscribeMode.UNSUBSCRIBED, false);
|
||||||
|
return channel.isSubscribed();
|
||||||
|
}).map(channel => {
|
||||||
|
return {
|
||||||
|
cid: channel.channelId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if(bulks.length === 0) {
|
||||||
|
/* shall not happen */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client.serverConnection.send_command("channelunsubscribe", bulks);
|
||||||
|
},
|
||||||
|
visible: channels.findIndex(channel => channel.getSubscriptionMode() !== ChannelSubscribeMode.UNSUBSCRIBED) !== -1
|
||||||
|
});
|
||||||
|
|
||||||
|
channelMenu.push({
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
name: tr("Use inherited subscribe mode"),
|
||||||
|
icon_class: ClientIcon.SubscribeToAllChannels,
|
||||||
|
callback: () => {
|
||||||
|
const inheritedSubscribe = this.client.isSubscribeToAllChannels();
|
||||||
|
const bulks = channels.filter(channel => {
|
||||||
|
channel.setSubscriptionMode(ChannelSubscribeMode.INHERITED, false);
|
||||||
|
return channel.isSubscribed() != inheritedSubscribe;
|
||||||
|
}).map(channel => {
|
||||||
|
return {
|
||||||
|
cid: channel.channelId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if(bulks.length === 0) {
|
||||||
|
/* might happen */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client.serverConnection.send_command(inheritedSubscribe ? "channelsubscribe" : "channelunsubscribe", bulks);
|
||||||
|
},
|
||||||
|
visible: channels.findIndex(channel => channel.getSubscriptionMode() !== ChannelSubscribeMode.INHERITED) !== -1
|
||||||
|
});
|
||||||
|
|
||||||
|
channelMenu.push(contextmenu.Entry.HR());
|
||||||
|
|
||||||
//TODO: Subscribe mode settings
|
//TODO: Subscribe mode settings
|
||||||
channel_menu.push({
|
channelMenu.push({
|
||||||
type: MenuEntryType.ENTRY,
|
type: MenuEntryType.ENTRY,
|
||||||
name: tr("Delete all channels"),
|
name: tr("Delete all channels"),
|
||||||
icon_class: "client-delete",
|
icon_class: "client-delete",
|
||||||
|
@ -712,7 +785,7 @@ export class ChannelTree {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: tr("Apply to all channels"),
|
text: tr("Apply to all channels"),
|
||||||
menu: channel_menu,
|
menu: channelMenu,
|
||||||
icon: "client-channel_green"
|
icon: "client-channel_green"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -253,6 +253,8 @@ export class RDPChannelTree {
|
||||||
popoutShown: boolean = false;
|
popoutShown: boolean = false;
|
||||||
popoutButtonShown: boolean = false;
|
popoutButtonShown: boolean = false;
|
||||||
|
|
||||||
|
private readonly documentDragStopListener;
|
||||||
|
|
||||||
private treeRevision: number = 0;
|
private treeRevision: number = 0;
|
||||||
private orderedTree: RDPEntry[] = [];
|
private orderedTree: RDPEntry[] = [];
|
||||||
private treeEntries: {[key: number]: RDPEntry} = {};
|
private treeEntries: {[key: number]: RDPEntry} = {};
|
||||||
|
@ -263,6 +265,13 @@ export class RDPChannelTree {
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.handlerId = handlerId;
|
this.handlerId = handlerId;
|
||||||
this.selection = new RDPTreeSelection(this);
|
this.selection = new RDPTreeSelection(this);
|
||||||
|
|
||||||
|
this.documentDragStopListener = () => {
|
||||||
|
if(this.dragOverChannelEntry) {
|
||||||
|
this.dragOverChannelEntry.setDragHint("none");
|
||||||
|
this.dragOverChannelEntry = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
|
@ -380,12 +389,20 @@ export class RDPChannelTree {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
document.addEventListener("dragend", this.documentDragStopListener);
|
||||||
|
document.addEventListener("focusout", this.documentDragStopListener);
|
||||||
|
document.addEventListener("mouseout", this.documentDragStopListener);
|
||||||
|
|
||||||
this.events.fire("query_tree_entries");
|
this.events.fire("query_tree_entries");
|
||||||
this.events.fire("query_popout_state");
|
this.events.fire("query_popout_state");
|
||||||
this.events.fire("query_selected_entry");
|
this.events.fire("query_selected_entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
document.removeEventListener("dragend", this.documentDragStopListener);
|
||||||
|
document.removeEventListener("focusout", this.documentDragStopListener);
|
||||||
|
document.removeEventListener("mouseout", this.documentDragStopListener);
|
||||||
|
|
||||||
this.events.unregister_handler(this);
|
this.events.unregister_handler(this);
|
||||||
this.registeredEventHandlers.forEach(callback => callback());
|
this.registeredEventHandlers.forEach(callback => callback());
|
||||||
this.registeredEventHandlers = [];
|
this.registeredEventHandlers = [];
|
||||||
|
|
Loading…
Reference in New Issue