2020-03-31 13:47:25 +00:00
import * as moment from "moment" ;
2020-03-30 11:44:18 +00:00
import * as loader from "tc-loader" ;
import { settings , Settings } from "tc-shared/settings" ;
import * as profiles from "tc-shared/profiles/ConnectionProfile" ;
import { LogCategory } from "tc-shared/log" ;
import * as log from "tc-shared/log" ;
import * as bipc from "./BrowserIPC" ;
import * as sound from "./sound/Sounds" ;
import * as i18n from "./i18n/localize" ;
import { ConnectionHandler } from "tc-shared/ConnectionHandler" ;
import { createInfoModal } from "tc-shared/ui/elements/Modal" ;
import { tra } from "./i18n/localize" ;
import { RequestFileUpload } from "tc-shared/FileManager" ;
import * as stats from "./stats" ;
import * as fidentity from "./profiles/identities/TeaForumIdentity" ;
import { default_recorder , RecorderProfile , set_default_recorder } from "tc-shared/voice/RecorderProfile" ;
import * as cmanager from "tc-shared/ui/frames/connection_handlers" ;
import { server_connections , ServerConnectionManager } from "tc-shared/ui/frames/connection_handlers" ;
import { spawnConnectModal } from "tc-shared/ui/modal/ModalConnect" ;
import * as top_menu from "./ui/frames/MenuBar" ;
import { spawnYesNo } from "tc-shared/ui/modal/ModalYesNo" ;
import { formatMessage } from "tc-shared/ui/frames/chat" ;
import { openModalNewcomer } from "tc-shared/ui/modal/ModalNewcomer" ;
import * as aplayer from "tc-backend/audio/player" ;
import * as arecorder from "tc-backend/audio/recorder" ;
import * as ppt from "tc-backend/ppt" ;
2020-04-06 14:28:15 +00:00
import * as React from "react" ;
import * as ReactDOM from "react-dom" ;
import * as cbar from "./ui/frames/control-bar" ;
2020-04-06 14:29:40 +00:00
import { Registry } from "tc-shared/events" ;
import { ClientGlobalControlEvents } from "tc-shared/events/GlobalEvents" ;
2020-04-06 14:28:15 +00:00
2020-03-30 11:44:18 +00:00
/* required import for init */
require ( "./proto" ) . initialize ( ) ;
require ( "./ui/elements/ContextDivider" ) . initialize ( ) ;
2020-04-04 19:20:58 +00:00
require ( "./ui/elements/Tab" ) ;
2020-04-01 13:36:37 +00:00
require ( "./connection/CommandHandler" ) ; /* else it might not get bundled because only the backends are accessing it */
2020-03-29 10:54:15 +00:00
const js_render = window . jsrender || $ ;
const native_client = window . require !== undefined ;
2020-03-30 11:44:18 +00:00
declare global {
interface Window {
open_connected_question : ( ) = > Promise < boolean > ;
}
2019-03-31 18:07:03 +00:00
}
2020-03-29 10:54:15 +00:00
function setup_close() {
2018-10-06 13:13:45 +00:00
window . onbeforeunload = event = > {
2018-12-28 14:39:23 +00:00
if ( profiles . requires_save ( ) )
profiles . save ( ) ;
2018-10-06 13:13:45 +00:00
2018-12-28 14:39:23 +00:00
if ( ! settings . static ( Settings . KEY_DISABLE_UNLOAD_DIALOG , false ) ) {
2019-04-04 19:47:52 +00:00
const active_connections = server_connections . server_connection_handlers ( ) . filter ( e = > e . connected ) ;
if ( active_connections . length == 0 ) return ;
2018-10-06 13:13:45 +00:00
2018-12-28 14:39:23 +00:00
if ( ! native_client ) {
event . returnValue = "Are you really sure?<br>You're still connected!" ;
} else {
2019-08-21 08:00:01 +00:00
const do_exit = ( ) = > {
const dp = server_connections . server_connection_handlers ( ) . map ( e = > {
if ( e . serverConnection . connected ( ) )
return e . serverConnection . disconnect ( tr ( "client closed" ) ) ;
return Promise . resolve ( ) ;
} ) . map ( e = > e . catch ( error = > {
console . warn ( tr ( "Failed to disconnect from server on client close: %o" ) , e ) ;
} ) ) ;
const exit = ( ) = > {
2020-03-30 11:44:18 +00:00
const { remote } = window . require ( 'electron' ) ;
2019-08-21 08:00:01 +00:00
remote . getCurrentWindow ( ) . close ( ) ;
} ;
Promise . all ( dp ) . then ( exit ) ;
/* force exit after 2500ms */
setTimeout ( exit , 2500 ) ;
} ;
2019-03-31 18:07:03 +00:00
if ( window . open_connected_question ) {
event . preventDefault ( ) ;
event . returnValue = "question" ;
window . open_connected_question ( ) . then ( result = > {
if ( result ) {
2019-08-21 08:00:01 +00:00
/* prevent quitting because we try to disconnect */
window . onbeforeunload = e = > e . preventDefault ( ) ;
2019-03-31 18:07:03 +00:00
2019-08-21 08:00:01 +00:00
/* allow a force quit after 5 seconds */
setTimeout ( ( ) = > window . onbeforeunload , 5000 ) ;
do_exit ( ) ;
2019-03-31 18:07:03 +00:00
}
} ) ;
2019-08-21 08:00:01 +00:00
} else {
/* we're in debugging mode */
do_exit ( ) ;
}
2018-12-28 14:39:23 +00:00
}
2018-10-06 13:13:45 +00:00
}
} ;
}
2018-10-03 20:04:29 +00:00
2020-03-29 10:54:15 +00:00
function setup_jsrender ( ) : boolean {
2018-10-03 20:04:29 +00:00
if ( ! js_render ) {
2019-08-30 21:06:39 +00:00
loader . critical_error ( "Missing jsrender extension!" ) ;
2018-10-14 11:27:48 +00:00
return false ;
2018-10-03 20:04:29 +00:00
}
2018-10-07 16:21:28 +00:00
if ( ! js_render . views ) {
2019-08-30 21:06:39 +00:00
loader . critical_error ( "Missing jsrender viewer extension!" ) ;
2018-10-14 11:27:48 +00:00
return false ;
2018-10-07 16:21:28 +00:00
}
2018-10-03 20:04:29 +00:00
js_render . views . settings . allowCode ( true ) ;
js_render . views . tags ( "rnd" , ( argument ) = > {
2018-06-24 11:38:53 +00:00
let min = parseInt ( argument . substr ( 0 , argument . indexOf ( '~' ) ) ) ;
let max = parseInt ( argument . substr ( argument . indexOf ( '~' ) + 1 ) ) ;
return ( Math . round ( Math . random ( ) * ( min + max + 1 ) - min ) ) . toString ( ) ;
} ) ;
2018-10-14 11:27:48 +00:00
2019-01-26 16:10:15 +00:00
js_render . views . tags ( "fmt_date" , ( . . . args ) = > {
return moment ( args [ 0 ] ) . format ( args [ 1 ] ) ;
2018-10-20 17:58:06 +00:00
} ) ;
2019-01-26 16:10:15 +00:00
js_render . views . tags ( "tr" , ( . . . args ) = > {
2020-03-31 13:19:53 +00:00
return /* @tr-ignore */ tr ( args [ 0 ] ) ;
2018-12-08 22:13:33 +00:00
} ) ;
2018-10-14 11:27:48 +00:00
$ ( ".jsrender-template" ) . each ( ( idx , _entry ) = > {
2019-08-30 21:06:39 +00:00
if ( ! js_render . templates ( _entry . id , _entry . innerHTML ) ) {
log . error ( LogCategory . GENERAL , tr ( "Failed to setup cache for js renderer template %s!" ) , _entry . id ) ;
2018-10-14 11:27:48 +00:00
} else
2019-08-30 21:06:39 +00:00
log . info ( LogCategory . GENERAL , tr ( "Successfully loaded jsrender template %s" ) , _entry . id ) ;
2018-10-14 11:27:48 +00:00
} ) ;
return true ;
}
2020-03-29 10:54:15 +00:00
async function initialize() {
2019-08-31 16:31:01 +00:00
Settings . initialize ( ) ;
2019-01-19 12:16:12 +00:00
2018-12-15 12:06:41 +00:00
try {
await i18n . initialize ( ) ;
} catch ( error ) {
console . error ( tr ( "Failed to initialized the translation system!\nError: %o" ) , error ) ;
2019-08-30 21:06:39 +00:00
loader . critical_error ( "Failed to setup the translation system" ) ;
2018-12-15 12:06:41 +00:00
return ;
}
2019-04-04 19:47:52 +00:00
bipc . setup ( ) ;
}
2020-04-06 14:29:40 +00:00
export let client_control_events : Registry < ClientGlobalControlEvents > ;
2020-03-29 10:54:15 +00:00
async function initialize_app() {
2018-12-14 23:09:47 +00:00
try { //Initialize main template
2019-08-21 08:00:01 +00:00
const main = $ ( "#tmpl_main" ) . renderTag ( {
multi_session : ! settings . static_global ( Settings . KEY_DISABLE_MULTI_SESSION ) ,
2020-04-01 19:47:33 +00:00
app_version : __build.version
2019-08-21 08:00:01 +00:00
} ) . dividerfy ( ) ;
2019-01-19 12:16:12 +00:00
2018-12-14 23:09:47 +00:00
$ ( "body" ) . append ( main ) ;
} catch ( error ) {
2019-08-30 21:06:39 +00:00
log . error ( LogCategory . GENERAL , error ) ;
loader . critical_error ( tr ( "Failed to setup main page!" ) ) ;
2018-12-14 23:09:47 +00:00
return ;
}
2020-04-06 14:29:40 +00:00
client_control_events = new Registry < ClientGlobalControlEvents > ( ) ;
2020-04-06 14:28:15 +00:00
{
const bar = (
2020-04-06 14:29:40 +00:00
< cbar.ControlBar ref = { cbar . react_reference ( ) } multiSession = { true } / >
2020-04-06 14:28:15 +00:00
) ;
ReactDOM . render ( bar , $ ( ".container-control-bar" ) [ 0 ] ) ;
2020-04-06 14:29:40 +00:00
cbar . control_bar_instance ( ) . load_default_states ( ) ;
2020-04-06 14:28:15 +00:00
}
2019-04-04 19:47:52 +00:00
2020-03-30 11:44:18 +00:00
if ( ! aplayer . initialize ( ) )
2019-04-04 19:47:52 +00:00
console . warn ( tr ( "Failed to initialize audio controller!" ) ) ;
2020-02-09 20:42:49 +00:00
2020-03-30 11:44:18 +00:00
aplayer . on_ready ( ( ) = > {
if ( aplayer . set_master_volume )
aplayer . on_ready ( ( ) = > aplayer . set_master_volume ( settings . global ( Settings . KEY_SOUND_MASTER ) / 100 ) ) ;
2020-02-09 20:42:49 +00:00
else
2020-03-30 11:44:18 +00:00
log . warn ( LogCategory . GENERAL , tr ( "Client does not support aplayer.set_master_volume()... May client is too old?" ) ) ;
if ( arecorder . device_refresh_available ( ) )
arecorder . refresh_devices ( ) ;
2020-02-09 20:42:49 +00:00
} ) ;
2019-04-04 19:47:52 +00:00
2020-03-30 11:44:18 +00:00
set_default_recorder ( new RecorderProfile ( "default" ) ) ;
2020-02-09 20:42:49 +00:00
default_recorder . initialize ( ) . catch ( error = > {
log . error ( LogCategory . AUDIO , tr ( "Failed to initialize default recorder: %o" ) , error ) ;
} ) ;
2019-05-20 16:57:14 +00:00
2019-04-04 19:47:52 +00:00
sound . initialize ( ) . then ( ( ) = > {
2019-08-30 21:06:39 +00:00
log . info ( LogCategory . AUDIO , tr ( "Sounds initialized" ) ) ;
2019-04-04 19:47:52 +00:00
} ) ;
2019-08-21 08:00:01 +00:00
sound . set_master_volume ( settings . global ( Settings . KEY_SOUND_MASTER_SOUNDS ) / 100 ) ;
2019-04-04 19:47:52 +00:00
2019-01-26 16:10:15 +00:00
await profiles . load ( ) ;
2018-04-11 15:56:09 +00:00
2018-12-09 19:18:49 +00:00
try {
await ppt . initialize ( ) ;
} catch ( error ) {
2019-08-30 21:06:39 +00:00
log . error ( LogCategory . GENERAL , tr ( "Failed to initialize ppt!\nError: %o" ) , error ) ;
loader . critical_error ( tr ( "Failed to initialize ppt!" ) ) ;
2018-12-09 19:18:49 +00:00
return ;
}
2019-02-17 15:08:10 +00:00
setup_close ( ) ;
2018-12-09 19:18:49 +00:00
}
2019-06-01 14:15:42 +00:00
/ *
class TestProxy extends bipc . MethodProxy {
constructor ( params : bipc.MethodProxyConnectParameters ) {
super ( bipc . get_handler ( ) , params . channel_id && params . client_id ? params : undefined ) ;
if ( ! this . is_slave ( ) ) {
this . register_method ( this . add_slave ) ;
}
if ( ! this . is_master ( ) ) {
this . register_method ( this . say_hello ) ;
this . register_method ( this . add_master ) ;
}
}
setup() {
super . setup ( ) ;
}
protected on_connected() {
2019-08-30 21:06:39 +00:00
log . info ( LogCategory . IPC , "Test proxy connected" ) ;
2019-06-01 14:15:42 +00:00
}
protected on_disconnected() {
2019-08-30 21:06:39 +00:00
log . info ( LogCategory . IPC , "Test proxy disconnected" ) ;
2019-06-01 14:15:42 +00:00
}
private async say_hello ( ) : Promise < void > {
2019-08-30 21:06:39 +00:00
log . info ( LogCategory . IPC , "Hello World" ) ;
2019-06-01 14:15:42 +00:00
}
private async add_slave ( a : number , b : number ) : Promise < number > {
return a + b ;
}
private async add_master ( a : number , b : number ) : Promise < number > {
return a * b ;
}
}
interface Window {
proxy_instance : TestProxy & { url : ( ) = > string } ;
}
* /
2020-04-01 13:36:37 +00:00
export function handle_connect_request ( properties : bipc.connect.ConnectRequestData , connection : ConnectionHandler ) {
2019-11-06 13:27:29 +00:00
const profile_uuid = properties . profile || ( profiles . default_profile ( ) || { id : 'default' } ) . id ;
const profile = profiles . find_profile ( profile_uuid ) || profiles . default_profile ( ) ;
const username = properties . username || profile . connect_username ( ) ;
const password = properties . password ? properties . password . value : "" ;
const password_hashed = properties . password ? properties.password.hashed : false ;
if ( profile && profile . valid ( ) ) {
connection . startConnection ( properties . address , profile , true , {
nickname : username ,
password : password.length > 0 ? {
password : password ,
hashed : password_hashed
} : undefined
} ) ;
server_connections . set_active_connection_handler ( connection ) ;
} else {
2020-03-30 11:44:18 +00:00
spawnConnectModal ( { } , {
2019-11-06 13:27:29 +00:00
url : properties.address ,
enforce : true
} , {
profile : profile ,
enforce : true
} ) ;
2019-09-18 23:25:57 +00:00
}
}
2018-12-09 19:18:49 +00:00
function main() {
2019-06-01 14:15:42 +00:00
/ *
window . proxy_instance = new TestProxy ( {
client_id : settings.static_global < string > ( "proxy_client_id" , undefined ) ,
channel_id : settings.static_global < string > ( "proxy_channel_id" , undefined )
} ) as any ;
if ( window . proxy_instance . is_master ( ) ) {
window . proxy_instance . setup ( ) ;
window . proxy_instance . url = ( ) = > {
const data = window . proxy_instance . generate_connect_parameters ( ) ;
return "proxy_channel_id=" + data . channel_id + "&proxy_client_id=" + data . client_id ;
} ;
}
* /
2018-12-09 19:18:49 +00:00
//http://localhost:63343/Web-Client/index.php?_ijt=omcpmt8b9hnjlfguh8ajgrgolr&default_connect_url=true&default_connect_type=teamspeak&default_connect_url=localhost%3A9987&disableUnloadDialog=1&loader_ignore_age=1
2019-04-04 19:47:52 +00:00
2019-08-21 08:00:01 +00:00
/* initialize font */
{
2019-09-12 21:59:35 +00:00
const font = settings . static_global ( Settings . KEY_FONT_SIZE , 14 ) ; //parseInt(getComputedStyle(document.body).fontSize)
2019-08-21 08:00:01 +00:00
$ ( document . body ) . css ( "font-size" , font + "px" ) ;
}
/* context menu prevent */
$ ( document ) . on ( 'contextmenu' , event = > {
if ( event . isDefaultPrevented ( ) )
return ;
if ( ! settings . static_global ( Settings . KEY_DISABLE_GLOBAL_CONTEXT_MENU ) )
event . preventDefault ( ) ;
} ) ;
top_menu . initialize ( ) ;
2020-03-30 11:44:18 +00:00
cmanager . initialize ( new ServerConnectionManager ( $ ( "#connection-handlers" ) ) ) ;
control_bar . control_bar . initialise ( ) ; /* before connection handler to allow property apply */
2018-12-09 19:18:49 +00:00
2019-04-04 19:47:52 +00:00
const initial_handler = server_connections . spawn_server_connection_handler ( ) ;
2019-05-20 16:57:14 +00:00
initial_handler . acquire_recorder ( default_recorder , false ) ;
2020-03-30 11:44:18 +00:00
control_bar . control_bar . set_connection_handler ( initial_handler ) ;
2018-04-11 15:56:09 +00:00
/** Setup the XF forum identity **/
2020-03-30 11:44:18 +00:00
fidentity . update_forum ( ) ;
2018-04-11 15:56:09 +00:00
2019-01-26 17:06:42 +00:00
let _resize_timeout : NodeJS.Timer ;
2019-04-04 19:47:52 +00:00
$ ( window ) . on ( 'resize' , event = > {
if ( event . target !== window )
return ;
2018-11-03 23:39:29 +00:00
if ( _resize_timeout )
clearTimeout ( _resize_timeout ) ;
_resize_timeout = setTimeout ( ( ) = > {
2019-04-04 19:47:52 +00:00
for ( const connection of server_connections . server_connection_handlers ( ) )
connection . invoke_resized_on_activate = true ;
const active_connection = server_connections . active_connection_handler ( ) ;
if ( active_connection )
active_connection . resize_elements ( ) ;
2019-04-29 17:35:16 +00:00
$ ( ".window-resize-listener" ) . trigger ( 'resize' ) ;
2018-11-03 23:39:29 +00:00
} , 1000 ) ;
2018-10-06 13:13:45 +00:00
} ) ;
2019-02-25 14:59:42 +00:00
stats . initialize ( {
verbose : true ,
anonymize_ip_addresses : true ,
volatile_collection_only : false
} ) ;
stats . register_user_count_listener ( status = > {
2019-08-30 21:06:39 +00:00
log . info ( LogCategory . STATISTICS , tr ( "Received user count update: %o" ) , status ) ;
2019-02-25 14:59:42 +00:00
} ) ;
2019-03-25 19:04:04 +00:00
2019-09-18 23:25:57 +00:00
server_connections . set_active_connection_handler ( server_connections . server_connection_handlers ( ) [ 0 ] ) ;
2020-04-06 14:28:15 +00:00
( window as any ) . test_upload = ( message? : string ) = > {
2019-04-04 19:47:52 +00:00
message = message || "Hello World" ;
const connection = server_connections . active_connection_handler ( ) ;
connection . fileManager . upload_file ( {
size : message.length ,
2019-03-28 16:30:00 +00:00
overwrite : true ,
2019-04-04 19:47:52 +00:00
channel : connection.getClient ( ) . currentChannel ( ) ,
2019-03-28 16:30:00 +00:00
name : '/HelloWorld.txt' ,
path : ''
} ) . then ( key = > {
const upload = new RequestFileUpload ( key ) ;
2019-04-04 19:47:52 +00:00
const buffer = new Uint8Array ( message . length ) ;
2019-03-28 16:30:00 +00:00
{
2019-04-04 19:47:52 +00:00
for ( let index = 0 ; index < message . length ; index ++ )
buffer [ index ] = message . charCodeAt ( index ) ;
2019-03-28 16:30:00 +00:00
}
upload . put_data ( buffer ) . catch ( error = > {
console . error ( error ) ;
} ) ;
} )
} ;
2019-04-04 19:47:52 +00:00
2019-09-18 23:25:57 +00:00
/* schedule it a bit later then the main because the main function is still within the loader */
2019-08-21 08:00:01 +00:00
setTimeout ( ( ) = > {
const connection = server_connections . active_connection_handler ( ) ;
/ *
Modals . createChannelModal ( connection , undefined , undefined , connection . permissions , ( cb , perms ) = > {
} ) ;
* /
2019-08-30 21:06:39 +00:00
// Modals.openServerInfo(connection.channelTree.server);
2019-08-21 08:00:01 +00:00
//Modals.createServerModal(connection.channelTree.server, properties => Promise.resolve());
2019-09-12 21:59:35 +00:00
//Modals.openClientInfo(connection.getClient());
//Modals.openServerInfoBandwidth(connection.channelTree.server);
2019-09-18 23:25:57 +00:00
//Modals.openBanList(connection);
/ *
Modals . spawnBanClient ( connection , [
{ name : "WolverinDEV" , unique_id : "XXXX" } ,
{ name : "WolverinDEV" , unique_id : "XXXX" } ,
{ name : "WolverinDEV" , unique_id : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } ,
{ name : "WolverinDEV" , unique_id : "YYY" }
] , ( ) = > { } ) ;
* /
2019-09-12 21:59:35 +00:00
} , 4000 ) ;
2019-08-31 16:31:01 +00:00
//Modals.spawnSettingsModal("identity-profiles");
2019-08-21 08:00:01 +00:00
//Modals.spawnKeySelect(console.log);
2019-09-12 21:59:35 +00:00
//Modals.spawnBookmarkModal();
/ *
{
const modal = createModal ( {
header : tr ( "Test Net Graph" ) ,
body : ( ) = > {
const canvas = $ . spawn ( "canvas" )
. css ( "position" , "absolute" )
. css ( {
top : 0 ,
bottom : 0 ,
right : 0 ,
left : 0
} ) ;
return $ . spawn ( "div" )
. css ( "height" , "5em" )
. css ( "width" , "30em" )
. css ( "position" , "relative" )
. append ( canvas ) ;
} ,
footer : null
} ) ;
const graph = new net . graph . Graph ( modal . htmlTag . find ( "canvas" ) [ 0 ] as any ) ;
graph . initialize ( ) ;
modal . close_listener . push ( ( ) = > graph . terminate ( ) ) ;
modal . open ( ) ;
}
* /
2020-03-27 15:15:15 +00:00
/* for testing */
if ( settings . static_global ( Settings . KEY_USER_IS_NEW ) ) {
2020-03-30 11:44:18 +00:00
const modal = openModalNewcomer ( ) ;
2020-03-27 15:15:15 +00:00
modal . close_listener . push ( ( ) = > settings . changeGlobal ( Settings . KEY_USER_IS_NEW , false ) ) ;
}
2018-04-19 16:42:34 +00:00
}
2019-04-04 19:47:52 +00:00
const task_teaweb_starter : loader.Task = {
name : "voice app starter" ,
2018-12-30 00:38:13 +00:00
function : async ( ) = > {
try {
2019-04-04 19:47:52 +00:00
await initialize_app ( ) ;
2018-12-30 00:38:13 +00:00
main ( ) ;
2020-03-30 11:44:18 +00:00
if ( ! aplayer . initialized ( ) ) {
2018-12-30 00:38:13 +00:00
log . info ( LogCategory . VOICE , tr ( "Initialize audio controller later!" ) ) ;
2020-03-30 11:44:18 +00:00
if ( ! aplayer . initializeFromGesture ) {
console . error ( tr ( "Missing aplayer.initializeFromGesture" ) ) ;
2018-12-30 00:38:13 +00:00
} else
2020-03-30 11:44:18 +00:00
$ ( document ) . one ( 'click' , event = > aplayer . initializeFromGesture ( ) ) ;
2018-12-30 00:38:13 +00:00
}
} catch ( ex ) {
console . error ( ex . stack ) ;
if ( ex instanceof ReferenceError || ex instanceof TypeError )
ex = ex . name + ": " + ex . message ;
2019-08-30 21:06:39 +00:00
loader . critical_error ( "Failed to invoke main function:<br>" + ex ) ;
2018-09-25 15:39:38 +00:00
}
2018-12-30 00:38:13 +00:00
} ,
priority : 10
2019-04-04 19:47:52 +00:00
} ;
2019-11-06 13:27:29 +00:00
const task_connect_handler : loader.Task = {
name : "Connect handler" ,
function : async ( ) = > {
const address = settings . static ( Settings . KEY_CONNECT_ADDRESS , "" ) ;
const chandler = bipc . get_connect_handler ( ) ;
if ( settings . static ( Settings . KEY_FLAG_CONNECT_DEFAULT , false ) && address ) {
const connect_data = {
address : address ,
profile : settings.static ( Settings . KEY_CONNECT_PROFILE , "" ) ,
username : settings.static ( Settings . KEY_CONNECT_USERNAME , "" ) ,
password : {
value : settings.static ( Settings . KEY_CONNECT_PASSWORD , "" ) ,
hashed : settings.static ( Settings . KEY_FLAG_CONNECT_PASSWORD , false )
}
} ;
if ( chandler ) {
try {
await chandler . post_connect_request ( connect_data , ( ) = > new Promise < boolean > ( ( resolve , reject ) = > {
spawnYesNo ( tr ( "Another TeaWeb instance is already running" ) , tra ( "Another TeaWeb instance is already running.{:br:}Would you like to connect there?" ) , response = > {
resolve ( response ) ;
} , {
closeable : false
} ) . open ( ) ;
} ) ) ;
log . info ( LogCategory . CLIENT , tr ( "Executed connect successfully in another browser window. Closing this window" ) ) ;
const message =
"You're connecting to {0} within the other TeaWeb instance.{:br:}" +
"You could now close this page." ;
createInfoModal (
tr ( "Connecting successfully within other instance" ) ,
2020-03-31 13:19:53 +00:00
formatMessage ( /* @tr-ignore */ tr ( message ) , connect_data . address ) ,
2019-11-06 13:27:29 +00:00
{
closeable : false ,
footer : undefined
}
) . open ( ) ;
return ;
} catch ( error ) {
log . info ( LogCategory . CLIENT , tr ( "Failed to execute connect within other TeaWeb instance. Using this one. Error: %o" ) , error ) ;
}
}
loader . register_task ( loader . Stage . LOADED , {
priority : 0 ,
function : async ( ) = > handle_connect_request ( connect_data , server_connections . active_connection_handler ( ) || server_connections . spawn_server_connection_handler ( ) ) ,
name : tr ( "default url connect" )
} ) ;
}
if ( chandler ) {
/* no instance avail, so lets make us avail */
chandler . callback_available = data = > {
return ! settings . static_global ( Settings . KEY_DISABLE_MULTI_SESSION ) ;
} ;
chandler . callback_execute = data = > {
handle_connect_request ( data , server_connections . spawn_server_connection_handler ( ) ) ;
return true ;
}
}
loader . register_task ( loader . Stage . LOADED , task_teaweb_starter ) ;
} ,
priority : 10
} ;
2019-04-04 19:47:52 +00:00
const task_certificate_callback : loader.Task = {
name : "certificate accept tester" ,
function : async ( ) = > {
const certificate_accept = settings . static_global ( Settings . KEY_CERTIFICATE_CALLBACK , undefined ) ;
if ( certificate_accept ) {
log . info ( LogCategory . IPC , tr ( "Using this instance as certificate callback. ID: %s" ) , certificate_accept ) ;
try {
try {
await bipc . get_handler ( ) . post_certificate_accpected ( certificate_accept ) ;
} catch ( e ) { } //FIXME remove!
log . info ( LogCategory . IPC , tr ( "Other instance has acknowledged out work. Closing this window." ) ) ;
const seconds_tag = $ . spawn ( "a" ) ;
let seconds = 5 ;
let interval_id ;
interval_id = setInterval ( ( ) = > {
seconds -- ;
seconds_tag . text ( seconds . toString ( ) ) ;
if ( seconds <= 0 ) {
clearTimeout ( interval_id ) ;
log . info ( LogCategory . GENERAL , tr ( "Closing window" ) ) ;
window . close ( ) ;
return ;
}
} , 1000 ) ;
const message =
"You've successfully accepted the certificate.{:br:}" +
"This page will close in {0} seconds." ;
createInfoModal (
tr ( "Certificate acccepted successfully" ) ,
2020-03-31 13:19:53 +00:00
formatMessage ( /* @tr-ignore */ tr ( message ) , seconds_tag ) ,
2019-04-04 19:47:52 +00:00
{
closeable : false ,
footer : undefined
}
) . open ( ) ;
return ;
} catch ( error ) {
log . warn ( LogCategory . IPC , tr ( "Failed to successfully post certificate accept status: %o" ) , error ) ;
}
} else {
log . info ( LogCategory . IPC , tr ( "We're not used to accept certificated. Booting app." ) ) ;
}
2019-11-06 13:27:29 +00:00
loader . register_task ( loader . Stage . LOADED , task_connect_handler ) ;
2019-04-04 19:47:52 +00:00
} ,
priority : 10
} ;
2019-04-25 18:22:13 +00:00
loader . register_task ( loader . Stage . JAVASCRIPT_INITIALIZING , {
name : "jrendere initialize" ,
function : async ( ) = > {
try {
if ( ! setup_jsrender ( ) )
throw "invalid load" ;
} catch ( error ) {
2019-08-30 21:06:39 +00:00
loader . critical_error ( tr ( "Failed to setup jsrender" ) ) ;
2019-04-25 18:22:13 +00:00
console . error ( tr ( "Failed to load jsrender! %o" ) , error ) ;
return ;
}
} ,
priority : 100
2019-05-20 17:28:20 +00:00
} ) ;
2019-04-25 18:22:13 +00:00
2019-05-20 17:28:20 +00:00
loader . register_task ( loader . Stage . JAVASCRIPT_INITIALIZING , {
2019-04-04 19:47:52 +00:00
name : "app starter" ,
function : async ( ) = > {
try {
await initialize ( ) ;
2020-04-01 19:47:33 +00:00
if ( __build . target == "web" ) {
2019-04-04 19:47:52 +00:00
loader . register_task ( loader . Stage . LOADED , task_certificate_callback ) ;
2019-11-06 13:27:29 +00:00
} else {
2019-04-04 19:47:52 +00:00
loader . register_task ( loader . Stage . LOADED , task_teaweb_starter ) ;
2019-11-06 13:27:29 +00:00
}
2019-04-04 19:47:52 +00:00
} catch ( ex ) {
2019-05-21 17:11:53 +00:00
if ( ex instanceof Error || typeof ( ex . stack ) !== "undefined" )
console . error ( ( tr || ( msg = > msg ) ) ( "Critical error stack trace: %o" ) , ex . stack ) ;
2019-04-04 19:47:52 +00:00
if ( ex instanceof ReferenceError || ex instanceof TypeError )
ex = ex . name + ": " + ex . message ;
2019-08-30 21:06:39 +00:00
loader . critical_error ( "Failed to boot app function:<br>" + ex ) ;
2019-04-04 19:47:52 +00:00
}
} ,
2019-05-24 20:30:58 +00:00
priority : 1000
2018-10-06 13:13:45 +00:00
} ) ;
2018-12-30 00:38:13 +00:00
2020-03-30 11:44:18 +00:00
loader . register_task ( loader . Stage . LOADED , {
name : "error task" ,
function : async ( ) = > {
if ( Settings . instance . static ( Settings . KEY_LOAD_DUMMY_ERROR , false ) ) {
loader . critical_error ( "The tea is cold!" , "Argh, this is evil! Cold tea dosn't taste good." ) ;
throw "The tea is cold!" ;
}
} ,
priority : 20
2020-04-01 13:40:45 +00:00
} ) ;