2018-03-07 19:06:52 +01:00
/// <reference path="../../utils/modal.ts" />
/// <reference path="../../utils/tab.ts" />
/// <reference path="../../proto.ts" />
2018-05-05 14:58:30 +02:00
/// <reference path="../../voice/AudioController.ts" />
2018-12-30 02:41:36 +01:00
/// <reference path="../../profiles/Identity.ts" />
2018-03-07 19:06:52 +01:00
namespace Modals {
2018-12-15 14:04:29 +01:00
import TranslationRepository = i18n . TranslationRepository ;
2018-12-28 15:39:23 +01:00
import ConnectionProfile = profiles . ConnectionProfile ;
import IdentitifyType = profiles . identities . IdentitifyType ;
2018-12-15 14:04:29 +01:00
2019-01-28 20:36:11 +01:00
function spawnTeamSpeakIdentityImprove ( identity : profiles.identities.TeaSpeakIdentity ) : Modal {
let modal : Modal ;
let elapsed_timer : NodeJS.Timer ;
modal = createModal ( {
header : tr ( "Improve identity" ) ,
body : ( ) = > {
let template = $ ( "#tmpl_settings-teamspeak_improve" ) . renderTag ( ) ;
template = $ . spawn ( "div" ) . append ( template ) ;
let active ;
const button_start_stop = template . find ( ".button-start-stop" ) ;
const button_close = template . find ( ".button-close" ) ;
const input_current_level = template . find ( ".property.identity-level input" ) ;
const input_target_level = template . find ( ".property.identity-target-level input" ) ;
const input_threads = template . find ( ".property.threads input" ) ;
const input_hash_rate = template . find ( ".property.hash-rate input" ) ;
const input_elapsed = template . find ( ".property.time-elapsed input" ) ;
button_close . on ( 'click' , event = > {
if ( active )
button_start_stop . trigger ( 'click' ) ;
if ( modal . shown )
modal . close ( ) ;
} ) ;
button_start_stop . on ( 'click' , event = > {
if ( active )
button_start_stop . text ( tr ( "Start" ) ) ;
else
button_start_stop . text ( tr ( "Stop" ) ) ;
input_threads . prop ( "disabled" , ! active ) ;
input_target_level . prop ( "disabled" , ! active ) ;
if ( active ) {
input_hash_rate . val ( 0 ) ;
clearInterval ( elapsed_timer ) ;
active = false ;
return ;
}
active = true ;
input_hash_rate . val ( "nan" ) ;
const threads = parseInt ( input_threads . val ( ) as string ) ;
const target_level = parseInt ( input_target_level . val ( ) as string ) ;
if ( target_level == 0 ) {
identity . improve_level ( - 1 , threads , ( ) = > active , current_level = > {
input_current_level . val ( current_level ) ;
} ) . catch ( error = > {
console . error ( error ) ;
createErrorModal ( tr ( "Failed to improve identity" ) , tr ( "Failed to improve identity.<br>Error:" ) + error ) . open ( ) ;
if ( active )
button_start_stop . trigger ( 'click' ) ;
} ) ;
} else {
identity . improve_level ( target_level , threads , ( ) = > active , current_level = > {
input_current_level . val ( current_level ) ;
} ) . then ( success = > {
if ( success ) {
identity . level ( ) . then ( level = > {
input_current_level . val ( level ) ;
createInfoModal ( tr ( "Identity successfully improved" ) , MessageHelper . formatMessage ( tr ( "Identity successfully improved to level {}" ) , level ) ) . open ( ) ;
} ) . catch ( error = > {
input_current_level . val ( "error: " + error ) ;
} ) ;
}
if ( active )
button_start_stop . trigger ( 'click' ) ;
} ) . catch ( error = > {
console . error ( error ) ;
createErrorModal ( tr ( "Failed to improve identity" ) , tr ( "Failed to improve identity.<br>Error:" ) + error ) . open ( ) ;
if ( active )
button_start_stop . trigger ( 'click' ) ;
} ) ;
}
const begin = Date . now ( ) ;
elapsed_timer = setInterval ( ( ) = > {
const time = ( Date . now ( ) - begin ) / 1000 ;
let seconds = Math . floor ( time % 60 ) . toString ( ) ;
let minutes = Math . floor ( time / 60 ) . toString ( ) ;
if ( seconds . length < 2 )
seconds = "0" + seconds ;
if ( minutes . length < 2 )
minutes = "0" + minutes ;
input_elapsed . val ( minutes + ":" + seconds ) ;
} , 1000 ) ;
} ) ;
template . find ( ".property.identity-unique-id input" ) . val ( identity . uid ( ) ) ;
identity . level ( ) . then ( level = > {
input_current_level . val ( level ) ;
} ) . catch ( error = > {
input_current_level . val ( "error: " + error ) ;
} ) ;
return template ;
} ,
footer : undefined ,
width : 750
} ) ;
modal . close_listener . push ( ( ) = > modal . htmlTag . find ( ".button-close" ) . trigger ( 'click' ) ) ;
modal . open ( ) ;
return modal ;
}
function spawnTeamSpeakIdentityImport ( callback : ( identity : profiles.identities.TeaSpeakIdentity ) = > any ) : Modal {
let modal : Modal ;
let loaded_identity : profiles.identities.TeaSpeakIdentity ;
modal = createModal ( {
header : tr ( "Import identity" ) ,
body : ( ) = > {
let template = $ ( "#tmpl_settings-teamspeak_import" ) . renderTag ( ) ;
template = $ . spawn ( "div" ) . append ( template ) ;
template . find ( ".button-load-file" ) . on ( 'click' , event = > template . find ( ".input-file" ) . trigger ( 'click' ) ) ;
const button_import = template . find ( ".button-import" ) ;
const set_error = message = > {
template . find ( ".success" ) . hide ( ) ;
if ( message ) {
template . find ( ".error" ) . text ( message ) . show ( ) ;
button_import . prop ( "disabled" , true ) ;
} else
template . find ( ".error" ) . hide ( ) ;
} ;
const import_identity = ( data : string , ini : boolean ) = > {
profiles . identities . TeaSpeakIdentity . import_ts ( data , ini ) . then ( identity = > {
loaded_identity = identity ;
set_error ( "" ) ;
button_import . prop ( "disabled" , false ) ;
template . find ( ".success" ) . show ( ) ;
} ) . catch ( error = > {
set_error ( "Failed to load identity: " + error ) ;
} ) ;
} ;
{ /* file select button */
template . find ( ".input-file" ) . on ( 'change' , event = > {
const element = event . target as HTMLInputElement ;
const file_reader = new FileReader ( ) ;
file_reader . onload = function ( ) {
import_identity ( file_reader . result as string , true ) ;
} ;
file_reader . onerror = ev = > {
console . error ( tr ( "Failed to read give identity file: %o" ) , ev ) ;
set_error ( tr ( "Failed to read file!" ) ) ;
return ;
} ;
if ( element . files && element . files . length > 0 )
file_reader . readAsText ( element . files [ 0 ] ) ;
} ) ;
}
{ /* text input */
template . find ( ".button-load-text" ) . on ( 'click' , event = > {
createInputModal ( "Import identity from text" , "Please paste your idenity bellow<br>" , text = > text . length > 0 && text . indexOf ( 'V' ) != - 1 , result = > {
if ( result )
import_identity ( result as string , false ) ;
} ) . open ( ) ;
} ) ;
}
button_import . on ( 'click' , event = > {
modal . close ( ) ;
callback ( loaded_identity ) ;
} ) ;
set_error ( "" ) ;
button_import . prop ( "disabled" , true ) ;
return template ;
} ,
footer : undefined ,
width : 750
} ) ;
modal . open ( ) ;
return modal ;
}
export function spawnSettingsModal ( ) : Modal {
let modal : Modal ;
2018-03-08 15:40:31 +01:00
modal = createModal ( {
2018-12-05 20:46:33 +01:00
header : tr ( "Settings" ) ,
2018-03-07 19:06:52 +01:00
body : ( ) = > {
2018-12-28 15:39:23 +01:00
let template = $ ( "#tmpl_settings" ) . renderTag ( {
client : native_client ,
valid_forum_identity : profiles.identities.valid_static_forum_identity ( ) ,
forum_path : settings.static ( "forum_path" ) ,
} ) ;
2018-03-07 19:06:52 +01:00
template = $ . spawn ( "div" ) . append ( template ) ;
2019-01-28 20:36:11 +01:00
initialiseVoiceListeners ( modal , ( template = template . tabify ( ) ) . find ( ".settings_audio" ) ) ;
2018-12-15 14:04:29 +01:00
initialise_translations ( template . find ( ".settings-translations" ) ) ;
2018-12-28 15:39:23 +01:00
initialise_profiles ( modal , template . find ( ".settings-profiles" ) ) ;
2019-01-28 20:36:11 +01:00
initialise_global ( modal , template . find ( ".settings-general" ) ) ;
2018-12-28 15:39:23 +01:00
2018-03-07 19:06:52 +01:00
return template ;
} ,
footer : ( ) = > {
let footer = $ . spawn ( "div" ) ;
footer . addClass ( "modal-button-group" ) ;
footer . css ( "margin-top" , "5px" ) ;
footer . css ( "margin-bottom" , "5px" ) ;
footer . css ( "text-align" , "right" ) ;
let buttonOk = $ . spawn ( "button" ) ;
2018-12-15 14:04:29 +01:00
buttonOk . text ( tr ( "Ok" ) ) ;
2018-03-07 19:06:52 +01:00
buttonOk . click ( ( ) = > modal . close ( ) ) ;
footer . append ( buttonOk ) ;
return footer ;
} ,
width : 750
} ) ;
modal . open ( ) ;
2018-12-28 15:39:23 +01:00
return modal ;
2018-03-07 19:06:52 +01:00
}
2019-01-28 20:36:11 +01:00
function initialise_global ( modal : Modal , tag : JQuery ) {
console . log ( tag ) ;
{ /* setup the forum */
const identity = profiles . identities . static_forum_identity ( ) ;
if ( identity && identity . valid ( ) ) {
tag . find ( ".not-connected" ) . hide ( ) ;
tag . find ( ".property.username .value" ) . text ( identity . name ( ) ) ;
const premium_tag = tag . find ( ".property.premium .value" ) . text ( "" ) ;
if ( identity . is_stuff ( ) || identity . is_premium ( ) )
premium_tag . append ( $ . spawn ( "div" ) . addClass ( "premium" ) . text ( tr ( "yes" ) ) ) ;
else
premium_tag . append ( $ . spawn ( "div" ) . addClass ( "non-premium" ) . text ( tr ( "no" ) ) ) ;
} else {
tag . find ( ".connected" ) . hide ( ) ;
}
tag . find ( ".button-logout" ) . on ( 'click' , event = > {
window . location . href = settings . static ( "forum_path" ) + "auth.php?type=logout" ;
} ) ;
tag . find ( ".button-login" ) . on ( 'click' , event = > {
window . location . href = settings . static ( "forum_path" ) + "login.php" ;
} ) ;
}
2018-03-07 19:06:52 +01:00
}
2018-03-08 15:40:31 +01:00
function initialiseVoiceListeners ( modal : Modal , tag : JQuery ) {
2019-01-28 20:36:11 +01:00
let currentVAD = settings . global ( "vad_type" , "vad" ) ;
2018-03-07 19:06:52 +01:00
2018-10-28 18:25:43 +01:00
{ //Initialized voice activation detection
const vad_tag = tag . find ( ".settings-vad-container" ) ;
vad_tag . find ( 'input[type=radio]' ) . on ( 'change' , event = > {
const select = event . currentTarget as HTMLSelectElement ;
{
vad_tag . find ( ".settings-vad-impl-entry" ) . hide ( ) ;
vad_tag . find ( ".setting-vad-" + select . value ) . show ( ) ;
}
{
settings . changeGlobal ( "vad_type" , select . value ) ;
globalClient . voiceConnection . voiceRecorder . reinitialiseVAD ( ) ;
}
switch ( select . value ) {
case "ppt" :
2018-11-17 16:25:44 +01:00
let ppt_settings : PPTKeySettings = settings . global ( 'vad_ppt_settings' , undefined ) ;
ppt_settings = ppt_settings ? JSON . parse ( ppt_settings as any as string ) : { } ;
vad_tag . find ( ".vat_ppt_key" ) . text ( ppt . key_description ( ppt_settings ) ) ;
2019-01-27 13:11:40 +01:00
vad_tag . find ( ".ppt-delay input" ) . val ( ppt_settings . delay === undefined ? 300 : ppt_settings.delay ) ;
2018-10-28 18:25:43 +01:00
break ;
case "vad" :
let slider = vad_tag . find ( ".vad_vad_slider" ) ;
let vad : VoiceActivityDetectorVAD = globalClient . voiceConnection . voiceRecorder . getVADHandler ( ) as VoiceActivityDetectorVAD ;
slider . val ( vad . percentageThreshold ) ;
slider . trigger ( "change" ) ;
globalClient . voiceConnection . voiceRecorder . update ( true ) ;
vad . percentage_listener = per = > {
vad_tag . find ( ".vad_vad_bar_filler" )
. css ( "width" , per + "%" ) ;
} ;
break ;
}
2018-03-07 19:06:52 +01:00
} ) ;
2018-03-08 15:40:31 +01:00
2018-10-28 18:25:43 +01:00
{ //Initialized push to talk
vad_tag . find ( ".vat_ppt_key" ) . click ( function ( ) {
let modal = createModal ( {
body : "" ,
header : ( ) = > {
let head = $ . spawn ( "div" ) ;
2018-12-05 20:46:33 +01:00
head . text ( tr ( "Type the key you wish" ) ) ;
2018-10-28 18:25:43 +01:00
head . css ( "background-color" , "blue" ) ;
return head ;
} ,
footer : ""
} ) ;
2018-11-17 16:25:44 +01:00
let listener = ( event : ppt.KeyEvent ) = > {
if ( event . type == ppt . EventType . KEY_TYPED ) {
settings . changeGlobal ( 'vad_ppt_key' , undefined ) ; //TODO remove that because its legacy shit
2018-12-05 20:46:33 +01:00
console . log ( tr ( "Got key %o" ) , event ) ;
2018-11-17 16:25:44 +01:00
let ppt_settings : PPTKeySettings = settings . global ( 'vad_ppt_settings' , undefined ) ;
ppt_settings = ppt_settings ? JSON . parse ( ppt_settings as any as string ) : { } ;
Object . assign ( ppt_settings , event ) ;
settings . changeGlobal ( 'vad_ppt_settings' , ppt_settings ) ;
globalClient . voiceConnection . voiceRecorder . reinitialiseVAD ( ) ;
ppt . unregister_key_listener ( listener ) ;
modal . close ( ) ;
vad_tag . find ( ".vat_ppt_key" ) . text ( ppt . key_description ( event ) ) ;
}
} ;
ppt . register_key_listener ( listener ) ;
2018-10-28 18:25:43 +01:00
modal . open ( ) ;
} ) ;
2019-01-27 13:11:40 +01:00
vad_tag . find ( ".ppt-delay input" ) . on ( 'change' , event = > {
let ppt_settings : PPTKeySettings = settings . global ( 'vad_ppt_settings' , undefined ) ;
ppt_settings = ppt_settings ? JSON . parse ( ppt_settings as any as string ) : { } ;
ppt_settings . delay = ( < HTMLInputElement > event . target ) . valueAsNumber ;
settings . changeGlobal ( 'vad_ppt_settings' , ppt_settings ) ;
globalClient . voiceConnection . voiceRecorder . reinitialiseVAD ( ) ;
} ) ;
2018-10-28 18:25:43 +01:00
}
2018-03-08 15:40:31 +01:00
2018-10-28 18:25:43 +01:00
{ //Initialized voice activation detection
let slider = vad_tag . find ( ".vad_vad_slider" ) ;
slider . on ( "input change" , ( ) = > {
settings . changeGlobal ( "vad_threshold" , slider . val ( ) . toString ( ) ) ;
let vad = globalClient . voiceConnection . voiceRecorder . getVADHandler ( ) ;
if ( vad instanceof VoiceActivityDetectorVAD )
vad . percentageThreshold = slider . val ( ) as number ;
vad_tag . find ( ".vad_vad_slider_value" ) . text ( slider . val ( ) . toString ( ) ) ;
} ) ;
modal . properties . registerCloseListener ( ( ) = > {
let vad = globalClient . voiceConnection . voiceRecorder . getVADHandler ( ) ;
if ( vad instanceof VoiceActivityDetectorVAD )
vad . percentage_listener = undefined ;
2018-03-08 15:40:31 +01:00
2018-10-28 18:25:43 +01:00
} ) ;
}
let target_tag = vad_tag . find ( 'input[type=radio][name="vad_type"][value="' + currentVAD + '"]' ) ;
if ( target_tag . length == 0 ) {
2018-12-05 20:46:33 +01:00
//TODO tr
2018-10-28 18:25:43 +01:00
console . warn ( "Failed to find tag for " + currentVAD + ". Using latest tag!" ) ;
target_tag = vad_tag . find ( 'input[type=radio][name="vad_type"]' ) . last ( ) ;
}
target_tag . prop ( "checked" , true ) ;
setTimeout ( ( ) = > target_tag . trigger ( 'change' ) , 0 ) ;
}
{ //Initialize microphone
2018-03-08 15:40:31 +01:00
2018-10-28 18:25:43 +01:00
const setting_tag = tag . find ( ".settings-microphone" ) ;
const tag_select = setting_tag . find ( ".audio-select-microphone" ) ;
console . log ( setting_tag ) ;
console . log ( setting_tag . find ( ".settings-device-error" ) ) ;
console . log ( setting_tag . find ( ".settings-device-error" ) . html ( ) ) ;
2018-03-08 15:40:31 +01:00
2018-10-28 18:25:43 +01:00
{ //List devices
$ . spawn ( "option" )
. attr ( "device-id" , "" )
. attr ( "device-group" , "" )
2018-12-05 20:46:33 +01:00
. text ( tr ( "No device" ) )
2018-10-28 18:25:43 +01:00
. appendTo ( tag_select ) ;
navigator . mediaDevices . enumerateDevices ( ) . then ( devices = > {
const active_device = globalClient . voiceConnection . voiceRecorder . device_id ( ) ;
for ( const device of devices ) {
2018-12-05 20:46:33 +01:00
console . debug ( tr ( "Got device %s (%s): %s" ) , device . deviceId , device . kind , device . label ) ;
2018-10-28 18:25:43 +01:00
if ( device . kind !== 'audioinput' ) continue ;
$ . spawn ( "option" )
. attr ( "device-id" , device . deviceId )
. attr ( "device-group" , device . groupId )
. text ( device . label )
. prop ( "selected" , device . deviceId == active_device )
. appendTo ( tag_select ) ;
}
} ) . catch ( error = > {
2018-12-05 20:46:33 +01:00
console . error ( tr ( "Could not enumerate over devices!" ) ) ;
2018-10-28 18:25:43 +01:00
console . error ( error ) ;
setting_tag . find ( ".settings-device-error" )
2018-12-05 20:46:33 +01:00
. text ( tr ( "Could not get device list!" ) )
2018-10-28 18:25:43 +01:00
. css ( "display" , "block" ) ;
} ) ;
if ( tag_select . find ( "option:selected" ) . length == 0 )
tag_select . find ( "option" ) . prop ( "selected" , true ) ;
}
{
tag_select . on ( 'change' , event = > {
let selected_tag = tag_select . find ( "option:selected" ) ;
let deviceId = selected_tag . attr ( "device-id" ) ;
let groupId = selected_tag . attr ( "device-group" ) ;
2018-12-05 20:46:33 +01:00
console . log ( tr ( "Selected microphone device: id: %o group: %o" ) , deviceId , groupId ) ;
2018-10-28 18:25:43 +01:00
globalClient . voiceConnection . voiceRecorder . change_device ( deviceId , groupId ) ;
} ) ;
}
}
{ //Initialize speaker
const setting_tag = tag . find ( ".settings-speaker" ) ;
const tag_select = setting_tag . find ( ".audio-select-speaker" ) ;
const active_device = audio . player . current_device ( ) ;
audio . player . available_devices ( ) . then ( devices = > {
for ( const device of devices ) {
$ . spawn ( "option" )
. attr ( "device-id" , device . device_id )
. text ( device . name )
. prop ( "selected" , device . device_id == active_device . device_id )
. appendTo ( tag_select ) ;
}
} ) . catch ( error = > {
2018-12-05 20:46:33 +01:00
console . error ( tr ( "Could not enumerate over devices!" ) ) ;
2018-10-28 18:25:43 +01:00
console . error ( error ) ;
setting_tag . find ( ".settings-device-error" )
2018-12-05 20:46:33 +01:00
. text ( tr ( "Could not get device list!" ) )
2018-10-28 18:25:43 +01:00
. css ( "display" , "block" ) ;
} ) ;
if ( tag_select . find ( "option:selected" ) . length == 0 )
tag_select . find ( "option" ) . prop ( "selected" , true ) ;
{
const error_tag = setting_tag . find ( ".settings-device-error" ) ;
tag_select . on ( 'change' , event = > {
let selected_tag = tag_select . find ( "option:selected" ) ;
let deviceId = selected_tag . attr ( "device-id" ) ;
2018-12-05 20:46:33 +01:00
console . log ( tr ( "Selected speaker device: id: %o" ) , deviceId ) ;
2018-10-28 18:25:43 +01:00
audio . player . set_device ( deviceId ) . then ( ( ) = > error_tag . css ( "display" , "none" ) ) . catch ( error = > {
console . error ( error ) ;
error_tag
2018-12-05 20:46:33 +01:00
. text ( tr ( "Failed to change device!" ) )
2018-10-28 18:25:43 +01:00
. css ( "display" , "block" ) ;
} ) ;
} ) ;
}
}
2018-03-17 08:05:37 +01:00
2019-01-27 13:11:40 +01:00
{ /* initialize sounds */
const sound_tag = tag . find ( ".sound-settings" ) ;
{ /* master volume */
const master_tag = sound_tag . find ( ".master-volume" ) ;
master_tag . find ( "input" ) . on ( 'change input' , event = > {
const value = parseInt ( ( < HTMLInputElement > event . target ) . value ) ;
master_tag . find ( 'a' ) . text ( "(" + value + "%)" ) ;
sound . set_master_volume ( value / 100 ) ;
} ) . val ( ( sound . get_master_volume ( ) * 100 ) . toString ( ) ) . trigger ( 'change' ) ;
}
{
const overlap_tag = sound_tag . find ( ".overlap-sounds input" ) ;
overlap_tag . on ( 'change' , event = > {
const activated = ( < HTMLInputElement > event . target ) . checked ;
sound . set_overlap_activated ( activated ) ;
} ) . prop ( "checked" , sound . overlap_activated ( ) ) ;
}
{
const muted_tag = sound_tag . find ( ".muted-sounds input" ) ;
muted_tag . on ( 'change' , event = > {
const activated = ( < HTMLInputElement > event . target ) . checked ;
sound . set_ignore_output_muted ( ! activated ) ;
} ) . prop ( "checked" , ! sound . ignore_output_muted ( ) ) ;
}
{ /* sound elements */
const template_tag = $ ( "#tmpl_settings-sound_entry" ) ;
const entry_tag = sound_tag . find ( ".sound-list-entries" ) ;
for ( const _sound in Sound ) {
const sound_name = Sound [ _sound ] ;
console . log ( sound . get_sound_volume ( sound_name as Sound ) ) ;
const data = {
name : sound_name ,
activated : sound.get_sound_volume ( sound_name as Sound ) > 0
} ;
const entry = template_tag . renderTag ( data ) ;
entry . find ( "input" ) . on ( 'change' , event = > {
const activated = ( < HTMLInputElement > event . target ) . checked ;
console . log ( tr ( "Sound %s had changed to %o" ) , sound_name , activated ) ;
sound . set_sound_volume ( sound_name as Sound , activated ? 1 : 0 ) ;
} ) ;
entry . find ( ".button-playback" ) . on ( 'click' , event = > {
sound . play ( sound_name as Sound ) ;
} ) ;
entry_tag . append ( entry ) ;
}
setTimeout ( ( ) = > {
const entry_container = sound_tag . find ( ".sound-list-entries-container" ) ;
if ( entry_container . hasScrollBar ( ) )
entry_container . addClass ( "scrollbar" ) ;
} , 100 ) ;
/* filter */
const filter_tag = sound_tag . find ( ".sound-list-filter input" ) ;
filter_tag . on ( 'change keyup' , event = > {
const filter = ( ( < HTMLInputElement > event . target ) . value || "" ) . toLowerCase ( ) ;
if ( ! filter )
entry_tag . find ( ".entry" ) . show ( ) ;
else {
entry_tag . find ( ".entry" ) . each ( ( _ , _entry ) = > {
const entry = $ ( _entry ) ;
if ( entry . text ( ) . toLowerCase ( ) . indexOf ( filter ) == - 1 )
entry . hide ( ) ;
else
entry . show ( ) ;
} ) ;
}
} ) ;
}
modal . close_listener . push ( sound . save ) ;
}
2018-03-17 08:05:37 +01:00
//Initialise microphones
2018-10-28 18:25:43 +01:00
/ *
2018-05-05 14:58:30 +02:00
let select_microphone = tag . find ( ".voice_microphone_select" ) ;
let select_error = tag . find ( ".voice_microphone_select_error" ) ;
2018-03-17 08:05:37 +01:00
navigator . mediaDevices . enumerateDevices ( ) . then ( devices = > {
2018-08-12 22:31:40 +02:00
let recoder = globalClient . voiceConnection . voiceRecorder ;
2018-03-17 08:05:37 +01:00
console . log ( "Got " + devices . length + " devices:" ) ;
for ( let device of devices ) {
2018-08-12 22:31:40 +02:00
console . log ( " - Type: %s Name %s ID: %s Group: %s" , device . kind , device . label , device . deviceId , device . groupId ) ;
2018-03-17 08:05:37 +01:00
if ( device . kind == "audioinput" ) {
let dtag = $ . spawn ( "option" ) ;
dtag . attr ( "device-id" , device . deviceId ) ;
dtag . attr ( "device-group" , device . groupId ) ;
dtag . text ( device . label ) ;
2018-05-05 14:58:30 +02:00
select_microphone . append ( dtag ) ;
2018-03-17 08:05:37 +01:00
2018-08-12 22:31:40 +02:00
if ( recoder ) dtag . prop ( "selected" , device . deviceId == recoder . device_id ( ) ) ;
2018-03-17 08:05:37 +01:00
}
}
} ) . catch ( error = > {
console . error ( "Could not enumerate over devices!" ) ;
console . error ( error ) ;
2018-05-05 14:58:30 +02:00
select_error . text ( "Could not get device list!" ) . show ( ) ;
2018-03-17 08:05:37 +01:00
} ) ;
2018-05-05 14:58:30 +02:00
select_microphone . change ( event = > {
let deviceSelected = select_microphone . find ( "option:selected" ) ;
2018-03-17 08:05:37 +01:00
let deviceId = deviceSelected . attr ( "device-id" ) ;
2018-06-19 20:31:05 +02:00
let groupId = deviceSelected . attr ( "device-group" ) ;
console . log ( "Selected microphone device: id: %o group: %o" , deviceId , groupId ) ;
2018-08-12 22:31:40 +02:00
globalClient . voiceConnection . voiceRecorder . change_device ( deviceId , groupId ) ;
2018-03-17 08:05:37 +01:00
} ) ;
2018-10-28 18:25:43 +01:00
* /
2018-05-05 14:58:30 +02:00
//Initialise speakers
2018-03-07 19:06:52 +01:00
}
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
function initialise_translations ( tag : JQuery ) {
{ //Initialize the list
const tag_list = tag . find ( ".setting-list .list" ) ;
const tag_loading = tag . find ( ".setting-list .loading" ) ;
const template = $ ( "#settings-translations-list-entry" ) ;
const restart_hint = tag . find ( ".setting-list .restart-note" ) ;
restart_hint . hide ( ) ;
const update_list = ( ) = > {
tag_list . empty ( ) ;
const currently_selected = i18n . config . translation_config ( ) . current_translation_url ;
{ //Default translation
const tag = template . renderTag ( {
type : "default" ,
selected : ! currently_selected || currently_selected == "default"
} ) ;
tag . on ( 'click' , ( ) = > {
i18n . select_translation ( undefined , undefined ) ;
tag_list . find ( ".selected" ) . removeClass ( "selected" ) ;
tag . addClass ( "selected" ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
restart_hint . show ( ) ;
} ) ;
tag . appendTo ( tag_list ) ;
}
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
{
const display_repository_info = ( repository : TranslationRepository ) = > {
const info_modal = createModal ( {
header : tr ( "Repository info" ) ,
body : ( ) = > {
return $ ( "#settings-translations-list-entry-info" ) . renderTag ( {
type : "repository" ,
name : repository.name ,
url : repository.url ,
contact : repository.contact ,
translations : repository.translations || [ ]
} ) ;
} ,
footer : ( ) = > {
let footer = $ . spawn ( "div" ) ;
footer . addClass ( "modal-button-group" ) ;
footer . css ( "margin-top" , "5px" ) ;
footer . css ( "margin-bottom" , "5px" ) ;
footer . css ( "text-align" , "right" ) ;
let buttonOk = $ . spawn ( "button" ) ;
buttonOk . text ( tr ( "Close" ) ) ;
buttonOk . click ( ( ) = > info_modal . close ( ) ) ;
footer . append ( buttonOk ) ;
return footer ;
}
} ) ;
info_modal . open ( )
} ;
tag_loading . show ( ) ;
i18n . iterate_translations ( ( repo , entry ) = > {
let repo_tag = tag_list . find ( "[repository=\"" + repo . unique_id + "\"]" ) ;
if ( repo_tag . length == 0 ) {
repo_tag = template . renderTag ( {
type : "repository" ,
name : repo.name || repo . url ,
id : repo.unique_id
} ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
repo_tag . find ( ".button-delete" ) . on ( 'click' , e = > {
e . preventDefault ( ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
Modals . spawnYesNo ( tr ( "Are you sure?" ) , tr ( "Do you really want to delete this repository?" ) , answer = > {
if ( answer ) {
i18n . delete_repository ( repo ) ;
update_list ( ) ;
}
2018-12-15 14:04:29 +01:00
} ) ;
2018-12-28 15:39:23 +01:00
} ) ;
repo_tag . find ( ".button-info" ) . on ( 'click' , e = > {
e . preventDefault ( ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
display_repository_info ( repo ) ;
} ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
tag_list . append ( repo_tag ) ;
}
const tag = template . renderTag ( {
type : "translation" ,
name : entry.info.name || entry . url ,
id : repo.unique_id ,
selected : i18n.config.translation_config ( ) . current_translation_url == entry . url
} ) ;
tag . find ( ".button-info" ) . on ( 'click' , e = > {
e . preventDefault ( ) ;
const info_modal = createModal ( {
header : tr ( "Translation info" ) ,
body : ( ) = > {
const tag = $ ( "#settings-translations-list-entry-info" ) . renderTag ( {
type : "translation" ,
name : entry.info.name ,
url : entry.url ,
repository_name : repo.name ,
contributors : entry.info.contributors || [ ]
2018-12-15 14:04:29 +01:00
} ) ;
2018-12-28 15:39:23 +01:00
tag . find ( ".button-info" ) . on ( 'click' , ( ) = > display_repository_info ( repo ) ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
return tag ;
} ,
footer : ( ) = > {
let footer = $ . spawn ( "div" ) ;
footer . addClass ( "modal-button-group" ) ;
footer . css ( "margin-top" , "5px" ) ;
footer . css ( "margin-bottom" , "5px" ) ;
footer . css ( "text-align" , "right" ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
let buttonOk = $ . spawn ( "button" ) ;
buttonOk . text ( tr ( "Close" ) ) ;
buttonOk . click ( ( ) = > info_modal . close ( ) ) ;
footer . append ( buttonOk ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
return footer ;
}
2018-12-15 14:04:29 +01:00
} ) ;
2018-12-28 15:39:23 +01:00
info_modal . open ( )
2018-12-15 14:04:29 +01:00
} ) ;
2018-12-28 15:39:23 +01:00
tag . on ( 'click' , e = > {
if ( e . isDefaultPrevented ( ) ) return ;
i18n . select_translation ( repo , entry ) ;
tag_list . find ( ".selected" ) . removeClass ( "selected" ) ;
tag . addClass ( "selected" ) ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
restart_hint . show ( ) ;
} ) ;
tag . insertAfter ( repo_tag )
} , ( ) = > {
tag_loading . hide ( ) ;
2018-12-15 14:04:29 +01:00
} ) ;
}
2018-12-28 15:39:23 +01:00
} ;
2018-12-15 14:04:29 +01:00
2018-12-28 15:39:23 +01:00
{
tag . find ( ".button-add-repository" ) . on ( 'click' , ( ) = > {
createInputModal ( "Enter URL" , tr ( "Enter repository URL:<br>" ) , text = > true , url = > { //FIXME test valid url
if ( ! url ) return ;
tag_loading . show ( ) ;
i18n . load_repository ( url as string ) . then ( repository = > {
i18n . register_repository ( repository ) ;
update_list ( ) ;
} ) . catch ( error = > {
tag_loading . hide ( ) ;
createErrorModal ( "Failed to load repository" , tr ( "Failed to query repository.<br>Ensure that this repository is valid and reachable.<br>Error: " ) + error ) . open ( ) ;
} )
} ) . open ( ) ;
} ) ;
2018-12-15 14:04:29 +01:00
}
2018-12-28 15:39:23 +01:00
restart_hint . find ( ".button-reload" ) . on ( 'click' , ( ) = > {
location . reload ( ) ;
} ) ;
update_list ( ) ;
}
}
function initialise_profiles ( modal : Modal , tag : JQuery ) {
const settings_tag = tag . find ( ".profile-settings" ) ;
let selected_profile : ConnectionProfile ;
let nickname_listener : ( ) = > any ;
let status_listener : ( ) = > any ;
const display_settings = ( profile : ConnectionProfile ) = > {
selected_profile = profile ;
settings_tag . find ( ".setting-name" ) . val ( profile . profile_name ) ;
settings_tag . find ( ".setting-default-nickname" ) . val ( profile . default_username ) ;
settings_tag . find ( ".setting-default-password" ) . val ( profile . default_password ) ;
{
//change listener
const select_tag = settings_tag . find ( ".select-container select" ) [ 0 ] as HTMLSelectElement ;
const type = profile . selected_identity_type . toLowerCase ( ) ;
select_tag . onchange = ( ) = > {
console . log ( "Selected: " + select_tag . value ) ;
settings_tag . find ( ".identity-settings.active" ) . removeClass ( "active" ) ;
settings_tag . find ( ".identity-settings-" + select_tag . value ) . addClass ( "active" ) ;
profile . selected_identity_type = select_tag . value . toLowerCase ( ) ;
const selected_type = profile . selected_type ( ) ;
const identity = profile . selected_identity ( ) ;
profiles . mark_need_save ( ) ;
2019-01-19 13:42:18 +01:00
let tag : JQuery ;
2018-12-28 15:39:23 +01:00
if ( selected_type == IdentitifyType . TEAFORO ) {
2019-01-19 13:42:18 +01:00
const forum_tag = tag = settings_tag . find ( ".identity-settings-teaforo" ) ;
2018-12-28 15:39:23 +01:00
2018-12-30 02:03:34 +01:00
forum_tag . find ( ".connected, .disconnected" ) . hide ( ) ;
2018-12-28 15:39:23 +01:00
if ( identity && identity . valid ( ) ) {
forum_tag . find ( ".connected" ) . show ( ) ;
} else {
forum_tag . find ( ".disconnected" ) . show ( ) ;
}
} else if ( selected_type == IdentitifyType . TEAMSPEAK ) {
console . log ( "Set: " + identity ) ;
2019-01-19 13:42:18 +01:00
const teamspeak_tag = tag = settings_tag . find ( ".identity-settings-teamspeak" ) ;
2019-01-26 17:10:15 +01:00
teamspeak_tag . find ( ".identity_string" ) . val ( "" ) ;
2018-12-28 15:39:23 +01:00
if ( identity )
2019-01-26 17:10:15 +01:00
( identity as profiles . identities . TeaSpeakIdentity ) . export_ts ( ) . then ( e = > teamspeak_tag . find ( ".identity_string" ) . val ( e ) ) ;
2018-12-28 15:39:23 +01:00
} else if ( selected_type == IdentitifyType . NICKNAME ) {
2019-01-19 13:42:18 +01:00
const name_tag = tag = settings_tag . find ( ".identity-settings-nickname" ) ;
2018-12-28 15:39:23 +01:00
if ( identity )
name_tag . find ( "input" ) . val ( identity . name ( ) ) ;
else
name_tag . find ( "input" ) . val ( "" ) ;
}
2019-01-19 13:42:18 +01:00
if ( tag )
tag . trigger ( 'show' ) ;
2018-12-28 15:39:23 +01:00
} ;
select_tag . value = type ;
select_tag . onchange ( undefined ) ;
}
} ;
const update_profile_list = ( ) = > {
const profile_list = tag . find ( ".profile-list .list" ) . empty ( ) ;
const profile_template = $ ( "#settings-profile-list-entry" ) ;
for ( const profile of profiles . profiles ( ) ) {
const list_tag = profile_template . renderTag ( {
profile_name : profile.profile_name ,
id : profile.id
} ) ;
const profile_status_update = ( ) = > {
list_tag . find ( ".status" ) . hide ( ) ;
if ( profile . valid ( ) )
list_tag . find ( ".status-valid" ) . show ( ) ;
else
list_tag . find ( ".status-invalid" ) . show ( ) ;
} ;
list_tag . on ( 'click' , event = > {
/* update ui */
profile_list . find ( ".selected" ) . removeClass ( "selected" ) ;
list_tag . addClass ( "selected" ) ;
if ( profile == selected_profile ) return ;
nickname_listener = ( ) = > list_tag . find ( ".name" ) . text ( profile . profile_name ) ;
status_listener = profile_status_update ;
display_settings ( profile ) ;
} ) ;
profile_list . append ( list_tag ) ;
if ( ( ! selected_profile && profile . id == "default" ) || selected_profile == profile )
setTimeout ( ( ) = > list_tag . trigger ( 'click' ) , 1 ) ;
profile_status_update ( ) ;
}
} ;
2019-01-19 13:42:18 +01:00
const display_error = ( error? : string ) = > {
if ( error ) {
settings_tag . find ( ".error-message" ) . show ( ) . html ( error ) ;
} else
settings_tag . find ( ".error-message" ) . hide ( ) ;
status_listener ( ) ;
} ;
2018-12-28 15:39:23 +01:00
/* identity settings */
{
{ //TeamSpeak change listener
const teamspeak_tag = settings_tag . find ( ".identity-settings-teamspeak" ) ;
2019-01-28 20:36:11 +01:00
const identity_info_tag = teamspeak_tag . find ( ".identity-info" ) ;
const button_export = teamspeak_tag . find ( ".button-export" ) ;
const button_import = teamspeak_tag . find ( ".button-import" ) ;
const button_generate = teamspeak_tag . find ( ".button-generate" ) ;
const button_improve = teamspeak_tag . find ( ".button-improve" ) ;
button_import . on ( 'click' , event = > {
const profile = selected_profile . selected_identity ( IdentitifyType . TEAMSPEAK ) as profiles . identities . TeaSpeakIdentity ;
const set_identity = ( identity : profiles.identities.TeaSpeakIdentity ) = > {
selected_profile . set_identity ( IdentitifyType . TEAMSPEAK , identity ) ;
teamspeak_tag . trigger ( 'show' ) ;
createInfoModal ( tr ( "Identity imported" ) , tr ( "Your identity has been successfully imported!" ) ) . open ( ) ;
2018-12-28 15:39:23 +01:00
} ;
2019-01-28 20:36:11 +01:00
if ( profile && profile . valid ( ) ) {
spawnYesNo ( tr ( "Are you sure" ) , tr ( "Do you really want to import a new identity and override the old identity?" ) , result = > {
if ( result )
spawnTeamSpeakIdentityImport ( set_identity ) ;
} ) ;
} else
spawnTeamSpeakIdentityImport ( set_identity ) ;
} ) ;
button_export . on ( 'click' , event = > {
const profile = selected_profile . selected_identity ( IdentitifyType . TEAMSPEAK ) as profiles . identities . TeaSpeakIdentity ;
if ( ! profile ) return ;
createInputModal ( tr ( "File name" ) , tr ( "Please enter the file name" ) , text = > ! ! text , name = > {
if ( name ) {
profile . export_ts ( true ) . then ( data = > {
const element = $ . spawn ( "a" )
. text ( "donwload" )
. attr ( "href" , "data:test/plain;charset=utf-8," + encodeURIComponent ( data ) )
. attr ( "download" , name + ".ini" )
. css ( "display" , "none" )
. appendTo ( $ ( "body" ) ) ;
element [ 0 ] . click ( ) ;
element . detach ( ) ;
} ) . catch ( error = > {
console . error ( error ) ;
createErrorModal ( tr ( "Failed to export identity" ) , tr ( "Failed to export and save identity.<br>Error: " ) + error ) . open ( ) ;
} ) ;
}
} ) . open ( ) ;
} ) ;
button_generate . on ( 'click' , event = > {
const profile = selected_profile . selected_identity ( IdentitifyType . TEAMSPEAK ) as profiles . identities . TeaSpeakIdentity ;
const generate_identity = ( ) = > {
profiles . identities . TeaSpeakIdentity . generate_new ( ) . then ( identity = > {
selected_profile . set_identity ( IdentitifyType . TEAMSPEAK , identity ) ;
teamspeak_tag . trigger ( 'show' ) ;
createInfoModal ( tr ( "Identity generate" ) , tr ( "A new identity had been successfully generated" ) ) . open ( ) ;
} ) . catch ( error = > {
createErrorModal ( tr ( "Failed to generate identity" ) , tr ( "Failed to generate a new identity.<br>Error:" ) + error ) . open ( ) ;
} ) ;
2018-12-28 15:39:23 +01:00
} ;
2019-01-28 20:36:11 +01:00
if ( profile && profile . valid ( ) ) {
spawnYesNo ( tr ( "Are you sure" ) , tr ( "Do you really want to generate a new identity and override the old identity?" ) , result = > {
if ( result )
generate_identity ( ) ;
} ) ;
} else
generate_identity ( ) ;
2018-12-28 15:39:23 +01:00
} ) ;
2019-01-28 20:36:11 +01:00
button_improve . on ( 'click' , event = > {
const profile = selected_profile . selected_identity ( IdentitifyType . TEAMSPEAK ) as profiles . identities . TeaSpeakIdentity ;
if ( ! profile ) return ;
2018-12-28 15:39:23 +01:00
2019-01-28 20:36:11 +01:00
spawnTeamSpeakIdentityImprove ( profile ) . close_listener . push ( ( ) = > teamspeak_tag . trigger ( 'show' ) ) ;
2018-12-28 15:39:23 +01:00
} ) ;
2019-01-19 13:42:18 +01:00
2019-01-28 20:36:11 +01:00
/* updates the data */
2019-01-19 13:42:18 +01:00
teamspeak_tag . on ( 'show' , event = > {
2019-01-28 20:36:11 +01:00
const profile = selected_profile . selected_identity ( IdentitifyType . TEAMSPEAK ) as profiles . identities . TeaSpeakIdentity ;
if ( ! profile || ! profile . valid ( ) ) {
identity_info_tag . hide ( ) ;
teamspeak_tag . find ( ".identity-undefined" ) . show ( ) ;
button_export . prop ( "disabled" , true ) ;
} else {
identity_info_tag . show ( ) ;
teamspeak_tag . find ( ".identity-undefined" ) . hide ( ) ;
button_export . prop ( "disabled" , false ) ;
identity_info_tag . find ( ".property.unique-id input" ) . val ( profile . uid ( ) ) ;
const input_level = identity_info_tag . find ( ".property.level input" ) . val ( "loading..." ) ;
profile . level ( ) . then ( level = > input_level . val ( level . toString ( ) ) ) . catch ( error = > input_level . val ( "error: " + error ) ) ;
}
display_error ( ) ;
2019-01-19 13:42:18 +01:00
} ) ;
2018-12-28 15:39:23 +01:00
}
{ //The forum
const teaforo_tag = settings_tag . find ( ".identity-settings-teaforo" ) ;
if ( native_client ) {
teaforo_tag . find ( ".native-teaforo-login" ) . on ( 'click' , event = > {
setTimeout ( ( ) = > {
const forum = require ( "teaforo.js" ) ;
const call = ( ) = > {
if ( modal . shown ) {
display_settings ( selected_profile ) ;
status_listener ( ) ;
}
} ;
forum . register_callback ( call ) ;
forum . open ( ) ;
} , 0 ) ;
} ) ;
}
2019-01-19 13:42:18 +01:00
teaforo_tag . on ( 'show' , event = > {
display_error ( ) ; /* clear error */
} ) ;
}
{ //The name
const name_tag = settings_tag . find ( ".identity-settings-nickname" ) ;
name_tag . find ( ".setting-name" ) . on ( 'change keyup' , event = > {
const name = name_tag . find ( ".setting-name" ) . val ( ) as string ;
selected_profile . set_identity ( IdentitifyType . NICKNAME , new profiles . identities . NameIdentity ( name ) ) ;
profiles . mark_need_save ( ) ;
if ( name . length < 3 ) {
display_error ( "Name must be at least 3 characters long!" ) ;
return ;
}
display_error ( ) ;
} ) ;
name_tag . on ( 'show' , event = > {
const profile = selected_profile . selected_identity ( IdentitifyType . NICKNAME ) ;
if ( ! profile )
display_error ( "invalid profile" ) ;
else if ( ! profile . valid ( ) )
display_error ( "Name must be at least 3 characters long!" ) ;
else
display_error ( ) ;
} ) ;
2018-12-28 15:39:23 +01:00
}
}
/* general settings */
{
settings_tag . find ( ".setting-name" ) . on ( 'change' , event = > {
const value = settings_tag . find ( ".setting-name" ) . val ( ) as string ;
if ( value && selected_profile ) {
selected_profile . profile_name = value ;
if ( nickname_listener )
nickname_listener ( ) ;
profiles . mark_need_save ( ) ;
status_listener ( ) ;
}
} ) ;
settings_tag . find ( ".setting-default-nickname" ) . on ( 'change' , event = > {
const value = settings_tag . find ( ".setting-default-nickname" ) . val ( ) as string ;
if ( value && selected_profile ) {
selected_profile . default_username = value ;
profiles . mark_need_save ( ) ;
status_listener ( ) ;
}
} ) ;
settings_tag . find ( ".setting-default-password" ) . on ( 'change' , event = > {
const value = settings_tag . find ( ".setting-default-password" ) . val ( ) as string ;
if ( value && selected_profile ) {
selected_profile . default_username = value ;
profiles . mark_need_save ( ) ;
status_listener ( ) ;
}
} ) ;
}
/* general buttons */
{
tag . find ( ".button-add-profile" ) . on ( 'click' , event = > {
createInputModal ( tr ( "Please enter a name" ) , tr ( "Please enter a name for the new profile:<br>" ) , text = > text . length > 0 && ! profiles . find_profile_by_name ( text ) , value = > {
if ( value ) {
display_settings ( profiles . create_new_profile ( value as string ) ) ;
update_profile_list ( ) ;
profiles . mark_need_save ( ) ;
}
} ) . open ( ) ;
} ) ;
tag . find ( ".button-set-default" ) . on ( 'click' , event = > {
if ( selected_profile && selected_profile . id != 'default' ) {
profiles . set_default_profile ( selected_profile ) ;
update_profile_list ( ) ;
profiles . mark_need_save ( ) ;
}
} ) ;
tag . find ( ".button-delete" ) . on ( 'click' , event = > {
if ( selected_profile && selected_profile . id != 'default' ) {
event . preventDefault ( ) ;
spawnYesNo ( tr ( "Are you sure?" ) , tr ( "Do you really want to delete this profile?" ) , result = > {
if ( result ) {
profiles . delete_profile ( selected_profile ) ;
update_profile_list ( ) ;
}
} ) ;
}
} ) ;
}
modal . close_listener . push ( ( ) = > {
if ( profiles . requires_save ( ) )
profiles . save ( ) ;
} ) ;
update_profile_list ( ) ;
}
2018-03-07 19:06:52 +01:00
}