2019-04-04 19:47:52 +00:00
/// <reference path="ui/frames/chat.ts" />
2018-03-07 18:06:52 +00:00
/// <reference path="ui/modal/ModalConnect.ts" />
2018-04-16 18:38:35 +00:00
/// <reference path="ui/modal/ModalCreateChannel.ts" />
2018-04-30 21:57:21 +00:00
/// <reference path="ui/modal/ModalBanClient.ts" />
2018-06-20 17:06:55 +00:00
/// <reference path="ui/modal/ModalYesNo.ts" />
2018-10-20 17:58:06 +00:00
/// <reference path="ui/modal/ModalBanList.ts" />
2018-04-11 15:56:09 +00:00
/// <reference path="settings.ts" />
2018-04-16 18:38:35 +00:00
/// <reference path="log.ts" />
2019-05-21 16:15:02 +00:00
/// <reference path="PPTListener.ts" />
2018-02-27 16:20:49 +00:00
2019-11-06 13:27:29 +00:00
import spawnYesNo = Modals . spawnYesNo ;
2018-10-03 20:04:29 +00:00
const js_render = window . jsrender || $ ;
2018-10-06 13:13:45 +00:00
const native_client = window . require !== undefined ;
2019-08-21 08:00:01 +00:00
function getUserMediaFunctionPromise ( ) : ( constraints : MediaStreamConstraints ) = > Promise < MediaStream > {
if ( 'mediaDevices' in navigator && 'getUserMedia' in navigator . mediaDevices )
return constraints = > navigator . mediaDevices . getUserMedia ( constraints ) ;
const _callbacked_function = navigator . getUserMedia || navigator . webkitGetUserMedia || navigator . mozGetUserMedia ;
if ( ! _callbacked_function )
return undefined ;
return constraints = > new Promise < MediaStream > ( ( resolve , reject ) = > _callbacked_function ( constraints , resolve , reject ) ) ;
2018-10-28 22:01:09 +00:00
}
2019-03-31 18:07:03 +00:00
interface Window {
open_connected_question : ( ) = > Promise < boolean > ;
}
2018-10-06 13:13:45 +00:00
function setup_close() {
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 = ( ) = > {
const { remote } = require ( 'electron' ) ;
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
2018-10-20 17:58:06 +00:00
declare function moment ( . . . arguments ) : any ;
2018-10-14 11:27:48 +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 ) = > {
return 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 ;
}
2018-12-09 19:18:49 +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 ( ) ;
}
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 ) ,
app_version : app.ui_version ( )
} ) . 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 ;
}
2019-04-04 19:47:52 +00:00
control_bar = new ControlBar ( $ ( "#control_bar" ) ) ; /* setup the control bar */
if ( ! audio . player . initialize ( ) )
console . warn ( tr ( "Failed to initialize audio controller!" ) ) ;
2019-04-29 17:49:14 +00:00
if ( audio . player . set_master_volume )
2019-08-21 08:00:01 +00:00
audio . player . set_master_volume ( settings . global ( Settings . KEY_SOUND_MASTER ) / 100 ) ;
2019-04-29 17:49:14 +00:00
else
2019-08-30 21:06:39 +00:00
log . warn ( LogCategory . GENERAL , tr ( "Client does not support audio.player.set_master_volume()... May client is too old?" ) ) ;
2019-05-21 17:11:53 +00:00
if ( audio . recorder . device_refresh_available ( ) )
await audio . recorder . refresh_devices ( ) ;
2019-04-04 19:47:52 +00:00
2019-05-20 16:57:14 +00:00
default_recorder = new RecorderProfile ( "default" ) ;
await default_recorder . initialize ( ) ;
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-01-26 16:10:15 +00:00
function str2ab8 ( str ) {
const buf = new ArrayBuffer ( str . length ) ;
const bufView = new Uint8Array ( buf ) ;
for ( let i = 0 , strLen = str . length ; i < strLen ; i ++ ) {
bufView [ i ] = str . charCodeAt ( i ) ;
}
return buf ;
}
/* FIXME Dont use atob, because it sucks for non UTF-8 tings */
function arrayBufferBase64 ( base64 : string ) {
base64 = atob ( base64 ) ;
const buf = new ArrayBuffer ( base64 . length ) ;
const bufView = new Uint8Array ( buf ) ;
for ( let i = 0 , strLen = base64 . length ; i < strLen ; i ++ ) {
bufView [ i ] = base64 . charCodeAt ( i ) ;
}
return buf ;
}
2019-08-21 08:00:01 +00:00
function base64_encode_ab ( source : ArrayBufferLike ) {
const encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
let base64 = "" ;
2019-01-26 16:10:15 +00:00
2019-08-21 08:00:01 +00:00
const bytes = new Uint8Array ( source ) ;
const byte_length = bytes . byteLength ;
const byte_reminder = byte_length % 3 ;
const main_length = byte_length - byte_reminder ;
2019-01-26 16:10:15 +00:00
2019-08-21 08:00:01 +00:00
let a , b , c , d ;
let chunk ;
2019-01-26 16:10:15 +00:00
// Main loop deals with bytes in chunks of 3
2019-08-21 08:00:01 +00:00
for ( let i = 0 ; i < main_length ; i = i + 3 ) {
2019-01-26 16:10:15 +00:00
// Combine the three bytes into a single integer
2019-08-21 08:00:01 +00:00
chunk = ( bytes [ i ] << 16 ) | ( bytes [ i + 1 ] << 8 ) | bytes [ i + 2 ] ;
2019-01-26 16:10:15 +00:00
// Use bitmasks to extract 6-bit segments from the triplet
2019-08-21 08:00:01 +00:00
a = ( chunk & 16515072 ) >> 18 ; // 16515072 = (2^6 - 1) << 18
b = ( chunk & 258048 ) >> 12 ; // 258048 = (2^6 - 1) << 12
c = ( chunk & 4032 ) >> 6 ; // 4032 = (2^6 - 1) << 6
d = ( chunk & 63 ) >> 0 ; // 63 = (2^6 - 1) << 0
2019-01-26 16:10:15 +00:00
// Convert the raw binary segments to the appropriate ASCII encoding
2019-08-21 08:00:01 +00:00
base64 += encodings [ a ] + encodings [ b ] + encodings [ c ] + encodings [ d ] ;
2019-01-26 16:10:15 +00:00
}
// Deal with the remaining bytes and padding
2019-08-21 08:00:01 +00:00
if ( byte_reminder == 1 ) {
chunk = bytes [ main_length ] ;
2019-01-26 16:10:15 +00:00
2019-08-21 08:00:01 +00:00
a = ( chunk & 252 ) >> 2 ; // 252 = (2^6 - 1) << 2
2019-01-26 16:10:15 +00:00
// Set the 4 least significant bits to zero
2019-08-21 08:00:01 +00:00
b = ( chunk & 3 ) << 4 ; // 3 = 2^2 - 1
2019-01-26 16:10:15 +00:00
2019-08-21 08:00:01 +00:00
base64 += encodings [ a ] + encodings [ b ] + '==' ;
} else if ( byte_reminder == 2 ) {
chunk = ( bytes [ main_length ] << 8 ) | bytes [ main_length + 1 ] ;
2019-01-26 16:10:15 +00:00
2019-08-21 08:00:01 +00:00
a = ( chunk & 64512 ) >> 10 ; // 64512 = (2^6 - 1) << 10
b = ( chunk & 1008 ) >> 4 ; // 1008 = (2^6 - 1) << 4
2019-01-26 16:10:15 +00:00
// Set the 2 least significant bits to zero
2019-08-21 08:00:01 +00:00
c = ( chunk & 15 ) << 2 ; // 15 = 2^4 - 1
2019-01-26 16:10:15 +00:00
2019-08-21 08:00:01 +00:00
base64 += encodings [ a ] + encodings [ b ] + encodings [ c ] + '=' ;
2019-01-26 16:10:15 +00:00
}
return base64
}
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 } ;
}
* /
2019-11-06 14:23:22 +00:00
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 {
Modals . spawnConnectModal ( { } , {
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 ( ) ;
2019-04-04 19:47:52 +00:00
server_connections = new ServerConnectionManager ( $ ( "#connection-handlers" ) ) ;
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 ) ;
2019-04-04 19:47:52 +00:00
control_bar . set_connection_handler ( initial_handler ) ;
2018-04-11 15:56:09 +00:00
/** Setup the XF forum identity **/
2019-08-21 08:00:01 +00:00
profiles . identities . 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 ] ) ;
2019-04-04 19:47:52 +00:00
( < any > window ) . test_upload = ( message? : string ) = > {
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 ( ) ;
}
* /
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 ( ) ;
if ( ! audio . player . initialized ( ) ) {
log . info ( LogCategory . VOICE , tr ( "Initialize audio controller later!" ) ) ;
if ( ! audio . player . initializeFromGesture ) {
console . error ( tr ( "Missing audio.player.initializeFromGesture" ) ) ;
} else
$ ( document ) . one ( 'click' , event = > audio . player . initializeFromGesture ( ) ) ;
}
} 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" ) ,
MessageHelper . formatMessage ( tr ( message ) , connect_data . address ) ,
{
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" ) ,
MessageHelper . formatMessage ( tr ( message ) , seconds_tag ) ,
{
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 ( ) ;
if ( app . is_web ( ) ) {
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