diff --git a/shared/js/bookmarks.ts b/shared/js/bookmarks.ts index add7567e..4589e43a 100644 --- a/shared/js/bookmarks.ts +++ b/shared/js/bookmarks.ts @@ -3,10 +3,10 @@ import {LogCategory} from "./log"; import {guid} from "./crypto/uid"; import {createErrorModal, createInfoModal, createInputModal} from "./ui/elements/Modal"; import {defaultConnectProfile, findConnectProfile} from "./profiles/ConnectionProfile"; -import {spawnConnectModal} from "./ui/modal/ModalConnect"; import {ConnectionHandler} from "./ConnectionHandler"; import {server_connections} from "tc-shared/ConnectionManager"; import {Registry} from "tc-shared/events"; +import {spawnConnectModalNew} from "tc-shared/ui/modal/connect/Controller"; /* TODO: much better events? */ export interface BookmarkEvents { @@ -36,13 +36,10 @@ export const boorkmak_connect = (mark: Bookmark, new_tab?: boolean) => { } ); } else { - spawnConnectModal({}, { - url: mark.server_properties.server_address + ":" + mark.server_properties.server_port, - enforce: true - }, { - profile: profile, - enforce: true - }) + spawnConnectModalNew({ + selectedAddress: mark.server_properties.server_address + ":" + mark.server_properties.server_port, + selectedProfile: profile + }); } }; diff --git a/shared/js/events/ClientGlobalControlHandler.ts b/shared/js/events/ClientGlobalControlHandler.ts index 5b4fca50..30f1376d 100644 --- a/shared/js/events/ClientGlobalControlHandler.ts +++ b/shared/js/events/ClientGlobalControlHandler.ts @@ -3,7 +3,6 @@ import {ClientGlobalControlEvents} from "../events/GlobalEvents"; import {Sound} from "../sound/Sounds"; import {ConnectionHandler} from "../ConnectionHandler"; import {createErrorModal, createInfoModal, createInputModal} from "../ui/elements/Modal"; -import {spawnConnectModal} from "../ui/modal/ModalConnect"; import PermissionType from "../permission/PermissionType"; import {spawnQueryCreate} from "../ui/modal/ModalQuery"; import {openBanList} from "../ui/modal/ModalBanList"; @@ -19,6 +18,7 @@ import {spawnAbout} from "tc-shared/ui/modal/ModalAbout"; import {spawnVideoSourceSelectModal} from "tc-shared/ui/modal/video-source/Controller"; import {LogCategory, logError, logWarn} from "tc-shared/log"; import {spawnEchoTestModal} from "tc-shared/ui/modal/echo-test/Controller"; +import {spawnConnectModalNew} from "tc-shared/ui/modal/connect/Controller"; /* function initialize_sounds(event_registry: Registry) { @@ -171,8 +171,8 @@ export function initialize(event_registry: Registry) }); event_registry.on("action_open_window_connect", event => { - spawnConnectModal({ - default_connect_new_tab: event.newTab + spawnConnectModalNew({ + connectInANewTab: true }); }); diff --git a/shared/js/main.tsx b/shared/js/main.tsx index 39f5887e..431683b2 100644 --- a/shared/js/main.tsx +++ b/shared/js/main.tsx @@ -12,7 +12,6 @@ import {createInfoModal} from "tc-shared/ui/elements/Modal"; import * as stats from "./stats"; import * as fidentity from "./profiles/identities/TeaForumIdentity"; import {defaultRecorder, RecorderProfile, setDefaultRecorder} from "tc-shared/voice/RecorderProfile"; -import {spawnConnectModal} from "tc-shared/ui/modal/ModalConnect"; import {spawnYesNo} from "tc-shared/ui/modal/ModalYesNo"; import {formatMessage} from "tc-shared/ui/frames/chat"; import {openModalNewcomer} from "tc-shared/ui/modal/ModalNewcomer"; @@ -53,6 +52,7 @@ import {server_connections} from "tc-shared/ConnectionManager"; import ContextMenuEvent = JQuery.ContextMenuEvent; import "./ui/modal/connect/Controller"; +import {spawnConnectModalNew} from "tc-shared/ui/modal/connect/Controller"; let preventWelcomeUI = false; async function initialize() { @@ -137,12 +137,9 @@ export function handle_connect_request(properties: ConnectRequestData, connectio }); server_connections.set_active_connection(connection); } else { - spawnConnectModal({},{ - url: properties.address, - enforce: true - }, { - profile: profile, - enforce: true + spawnConnectModalNew({ + selectedAddress: properties.address, + selectedProfile: profile }); } } diff --git a/shared/js/ui/modal/ModalConnect.ts b/shared/js/ui/modal/ModalConnect.ts index 695d94ac..36ccbcfc 100644 --- a/shared/js/ui/modal/ModalConnect.ts +++ b/shared/js/ui/modal/ModalConnect.ts @@ -1,251 +1,5 @@ -import {Settings, settings} from "../../settings"; -import {createModal} from "../../ui/elements/Modal"; -import {ConnectionProfile, defaultConnectProfile, findConnectProfile, availableConnectProfiles} from "../../profiles/ConnectionProfile"; -import * as i18nc from "../../i18n/country"; -import {spawnSettingsModal} from "../../ui/modal/ModalSettings"; -import {server_connections} from "tc-shared/ConnectionManager"; -import {generateIconJQueryTag, getIconManager} from "tc-shared/file/Icons"; -import { tr } from "tc-shared/i18n/localize"; - declare const native_client; -export function spawnConnectModal(options: { - default_connect_new_tab?: boolean /* default false */ -}, defaultHost: { url: string, enforce: boolean } = { - url: "ts.TeaSpeak.de", - enforce: false -}, connect_profile?: { profile: ConnectionProfile, enforce: boolean }) { - let selected_profile: ConnectionProfile; - - const random_id = (() => { - const array = new Uint32Array(10); - window.crypto.getRandomValues(array); - return array.join(""); - })(); - - const modal = createModal({ - header: tr("Connect to a server"), - body: $("#tmpl_connect").renderTag({ - client: native_client, - forum_path: "https://forum.teaspeak.de/", - password_id: random_id, - multi_tab: !settings.static_global(Settings.KEY_DISABLE_MULTI_SESSION), - default_connect_new_tab: typeof (options.default_connect_new_tab) === "boolean" && options.default_connect_new_tab - }), - footer: () => undefined, - min_width: "28em" - }); - - modal.htmlTag.find(".modal-body").addClass("modal-connect"); - - /* server list toggle */ - { - const container_last_servers = modal.htmlTag.find(".container-last-servers"); - const button = modal.htmlTag.find(".button-toggle-last-servers"); - const set_show = shown => { - container_last_servers.toggleClass('shown', shown); - button.find(".arrow").toggleClass('down', shown).toggleClass('up', !shown); - settings.changeGlobal(Settings.KEY_CONNECT_SHOW_HISTORY, shown); - }; - button.on('click', event => { - set_show(!container_last_servers.hasClass("shown")); - }); - set_show(settings.static_global(Settings.KEY_CONNECT_SHOW_HISTORY)); - } - - const apply = (header, body, footer) => { - const container_last_server_body = modal.htmlTag.find(".container-last-servers .table .body"); - const container_empty = container_last_server_body.find(".body-empty"); - - const button_connect = footer.find(".button-connect"); - const button_connect_tab = footer.find(".button-connect-new-tab"); - const button_manage = body.find(".button-manage-profiles"); - - const input_profile = body.find(".container-select-profile select"); - const input_address = body.find(".container-address input"); - const input_nickname = body.find(".container-nickname input"); - const input_password = body.find(".container-password input"); - - let updateFields = (reset_current_data: boolean) => { - if (reset_current_data) { - container_last_server_body.find(".selected").removeClass("selected"); - } - - let address = input_address.val().toString(); - settings.changeGlobal(Settings.KEY_CONNECT_ADDRESS, address); - let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.IP_V6) || !!address.match(Regex.DOMAIN); - - let nickname = input_nickname.val().toString(); - if (nickname) - settings.changeGlobal(Settings.KEY_CONNECT_USERNAME, nickname); - else - nickname = input_nickname.attr("placeholder") || ""; - let flag_nickname = nickname.length >= 3 && nickname.length <= 32; - - input_address.attr('pattern', flag_address ? null : '^[a]{1000}$').toggleClass('is-invalid', !flag_address); - input_nickname.attr('pattern', flag_nickname ? null : '^[a]{1000}$').toggleClass('is-invalid', !flag_nickname); - - const flag_disabled = !flag_nickname || !flag_address || !selected_profile || !selected_profile.valid(); - button_connect.prop("disabled", flag_disabled); - button_connect_tab.prop("disabled", flag_disabled); - }; - - input_address.val(defaultHost.enforce ? defaultHost.url : settings.static_global(Settings.KEY_CONNECT_ADDRESS, defaultHost.url)); - input_address.on("keyup", () => updateFields(true)); - input_address.on("keypress", event => { - if (event.key === "Enter" && !event.shiftKey) { - button_connect.trigger('click'); - } - }); - - button_manage.on('click', event => { - const modal = spawnSettingsModal("identity-profiles"); - modal.close_listener.push(() => { - input_profile.trigger('change'); - }); - return true; - }); - - /* Connect Profiles */ - { - for (const profile of availableConnectProfiles()) { - input_profile.append( - $.spawn("option").text(profile.profileName).val(profile.id) - ); - } - - input_profile.on('change', event => { - selected_profile = findConnectProfile(input_profile.val() as string) || defaultConnectProfile(); - { - settings.changeGlobal(Settings.KEY_CONNECT_USERNAME, undefined); - input_nickname - .attr('placeholder', selected_profile.connectUsername() || "Another TeaSpeak user") - .val(""); - } - - settings.changeGlobal(Settings.KEY_CONNECT_PROFILE, selected_profile.id); - input_profile.toggleClass("is-invalid", !selected_profile || !selected_profile.valid()); - updateFields(true); - }); - input_profile.val(connect_profile && connect_profile.profile ? - connect_profile.profile.id : - settings.static_global(Settings.KEY_CONNECT_PROFILE, "default") - ).trigger('change'); - } - - const last_nickname = settings.static_global(Settings.KEY_CONNECT_USERNAME, undefined); - if (last_nickname) /* restore */ - settings.changeGlobal(Settings.KEY_CONNECT_USERNAME, last_nickname); - - input_nickname.val(last_nickname); - input_nickname.on("keyup", () => updateFields(true)); - setTimeout(() => updateFields(false), 100); - - const server_address = () => { - let address = input_address.val().toString(); - if (address.match(Regex.IP_V6) && !address.startsWith("[")) - return "[" + address + "]"; - return address; - }; - button_connect.on('click', event => { - modal.close(); - - const connection = server_connections.active_connection(); - if (connection) { - connection.startConnection( - current_connect_data ? current_connect_data.address.hostname + ":" + current_connect_data.address.port : server_address(), - selected_profile, - true, - { - nickname: input_nickname.val().toString() || input_nickname.attr("placeholder"), - password: (current_connect_data && current_connect_data.password_hash) ? { - password: current_connect_data.password_hash, - hashed: true - } : {password: input_password.val().toString(), hashed: false} - } - ); - } else { - button_connect_tab.trigger('click'); - } - }); - button_connect_tab.on('click', event => { - modal.close(); - - const connection = server_connections.spawn_server_connection(); - server_connections.set_active_connection(connection); - connection.startConnection( - current_connect_data ? current_connect_data.address.hostname + ":" + current_connect_data.address.port : server_address(), - selected_profile, - true, - { - nickname: input_nickname.val().toString() || input_nickname.attr("placeholder"), - password: (current_connect_data && current_connect_data.password_hash) ? { - password: current_connect_data.password_hash, - hashed: true - } : {password: input_password.val().toString(), hashed: false} - } - ); - }); - - - /* connect history show */ - { - /* connection_log.history().slice(0, 10) */ - for (const entry of []) { - $.spawn("div").addClass("row").append( - $.spawn("div").addClass("column delete").append($.spawn("div").addClass("icon_em client-delete")).on('click', event => { - event.preventDefault(); - - const row = $(event.target).parents('.row'); - row.hide(250, () => { - row.detach(); - }); - //connection_log.delete_entry(entry.address); - container_empty.toggle(container_last_server_body.children().length > 1); - }) - ).append( - $.spawn("div").addClass("column name").append([ - generateIconJQueryTag(getIconManager().resolveIcon(entry.icon_id, entry.server_unique_id), {animate: false}), - $.spawn("a").text(entry.name) - ]) - ).append( - $.spawn("div").addClass("column address").text(entry.address.hostname + (entry.address.port != 9987 ? (":" + entry.address.port) : "")) - ).append( - $.spawn("div").addClass("column password").text(entry.flag_password ? tr("Yes") : tr("No")) - ).append( - $.spawn("div").addClass("column country-name").append([ - $.spawn("div").addClass("country flag-" + entry.country.toLowerCase()), - $.spawn("a").text(i18nc.country_name(entry.country, tr("Global"))) - ]) - ).append( - $.spawn("div").addClass("column clients").text(entry.clients_online + "/" + entry.clients_total) - ).append( - $.spawn("div").addClass("column connections").text(entry.total_connection + "") - ).on('click', event => { - if (event.isDefaultPrevented()) - return; - - event.preventDefault(); - current_connect_data = entry; - container_last_server_body.find(".selected").removeClass("selected"); - $(event.target).parent('.row').addClass('selected'); - - input_address.val(entry.address.hostname + (entry.address.port != 9987 ? (":" + entry.address.port) : "")); - input_password.val(entry.flag_password && entry.password_hash ? "WolverinDEV Yeahr!" : "").trigger('change'); - }).on('dblclick', event => { - current_connect_data = entry; - button_connect.trigger('click'); - }).appendTo(container_last_server_body); - container_empty.toggle(false); - } - } - }; - apply(modal.htmlTag, modal.htmlTag, modal.htmlTag); - - modal.open(); - return; -} - export const Regex = { //DOMAIN<:port> DOMAIN: /^(localhost|((([a-zA-Z0-9_-]{0,63}\.){0,253})?[a-zA-Z0-9_-]{0,63}\.[a-zA-Z]{2,64}))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,46}))$/, diff --git a/shared/js/ui/modal/connect/Controller.ts b/shared/js/ui/modal/connect/Controller.ts index 2cbe4c9a..6fb850b8 100644 --- a/shared/js/ui/modal/connect/Controller.ts +++ b/shared/js/ui/modal/connect/Controller.ts @@ -196,28 +196,10 @@ class ConnectController { return; } - this.currentProfile = profile; - this.sendProperty("profiles").then(undefined); - settings.changeGlobal(Settings.KEY_CONNECT_PROFILE, profile.id); - - /* Clear out the nickname on profile switch and use the default nickname */ - this.uiEvents.fire("action_set_nickname", { nickname: undefined, validate: true }); - - this.validateStates["profile"] = true; - this.updateValidityStates(); + this.setSelectedProfile(profile); }); - this.uiEvents.on("action_set_address", event => { - if(this.currentAddress !== event.address) { - this.currentAddress = event.address; - this.sendProperty("address").then(undefined); - settings.changeGlobal(Settings.KEY_CONNECT_ADDRESS, event.address); - this.setSelectedHistoryId(-1); - } - - this.validateStates["address"] = event.validate; - this.updateValidityStates(); - }); + this.uiEvents.on("action_set_address", event => this.setSelectedAddress(event.address, event.validate)); this.uiEvents.on("action_set_nickname", event => { if(this.currentNickname !== event.nickname) { @@ -297,6 +279,34 @@ class ConnectController { this.sendProperty("nickname").then(undefined); } + setSelectedAddress(address: string | undefined, validate: boolean) { + if(this.currentAddress !== address) { + this.currentAddress = address; + this.sendProperty("address").then(undefined); + settings.changeGlobal(Settings.KEY_CONNECT_ADDRESS, address); + this.setSelectedHistoryId(-1); + } + + this.validateStates["address"] = validate; + this.updateValidityStates(); + } + + setSelectedProfile(profile: ConnectionProfile | undefined) { + if(this.currentProfile === profile) { + return; + } + + this.currentProfile = profile; + this.sendProperty("profiles").then(undefined); + settings.changeGlobal(Settings.KEY_CONNECT_PROFILE, profile.id); + + /* Clear out the nickname on profile switch and use the default nickname */ + this.uiEvents.fire("action_set_nickname", { nickname: undefined, validate: true }); + + this.validateStates["profile"] = true; + this.updateValidityStates(); + } + private updateValidityStates() { const newStates = Object.assign({}, kDefaultValidityStates); if(this.validateStates["nickname"]) { @@ -348,12 +358,22 @@ class ConnectController { export type ConnectModalOptions = { connectInANewTab?: boolean, - defaultAddress?: string, - defaultProfile?: string + + selectedAddress?: string, + selectedProfile?: ConnectionProfile, } export function spawnConnectModalNew(options: ConnectModalOptions) { const controller = new ConnectController(); + + if(typeof options.selectedAddress === "string") { + controller.setSelectedAddress(options.selectedAddress, false); + } + + if(typeof options.selectedProfile === "object") { + controller.setSelectedProfile(options.selectedProfile); + } + const modal = spawnReactModal(ConnectModal, controller.uiEvents, options.connectInANewTab || false); modal.show(); @@ -383,6 +403,4 @@ export function spawnConnectModalNew(options: ConnectModalOptions) { connection.startConnectionNew(parameters, false).then(undefined); }); -} - -(window as any).spawnConnectModalNew = spawnConnectModalNew; \ No newline at end of file +} \ No newline at end of file