Added a welcomer guide
parent
dce44b6486
commit
a7c8d764f4
|
@ -1,4 +1,7 @@
|
|||
# Changelog:
|
||||
* **21.03.20**
|
||||
- Fixed identity import throwing an "btoa" error
|
||||
|
||||
* **19.03.20**
|
||||
- Using proper icons for the client info
|
||||
- Added an image preview overlay
|
||||
|
|
|
@ -35,6 +35,7 @@ files=(
|
|||
"css/static/modal-group-assignment.css"
|
||||
"css/static/modal-icons.css"
|
||||
"css/static/modal-identity.css"
|
||||
"css/static/modal-newcomer.css"
|
||||
"css/static/modal-invite.css"
|
||||
"css/static/modal-keyselect.css"
|
||||
"css/static/modal-permissions.css"
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
& {
|
||||
/* for moz */
|
||||
scrollbar-color: #353535 #555;
|
||||
scrollbarWidth: .5em;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
@import "mixin";
|
||||
@import "properties";
|
||||
|
||||
.modal-body.modal-newcomer {
|
||||
display: flex!important;
|
||||
flex-direction: column!important;
|
||||
justify-content: stretch!important;
|
||||
|
||||
padding: 0!important;
|
||||
|
||||
min-width: 20em;
|
||||
width: 50em;
|
||||
|
||||
@include user-select(none);
|
||||
|
||||
.container-header {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
color: #565656;
|
||||
padding: .5em .5em .25em;
|
||||
|
||||
position: relative;
|
||||
font-size: 1.5em;
|
||||
text-transform: uppercase;
|
||||
|
||||
.step {
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
height: 1.25px;
|
||||
//background: linear-gradient(90deg, rgba(49,49,53,1) 80%, rgba(49,49,53,0) 100%);
|
||||
background: rgba(49,49,53,1);
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
&::after {
|
||||
content: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-body {
|
||||
//flex-grow: 1;
|
||||
//flex-shrink: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: 18em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
overflow: auto;
|
||||
@include chat-scrollbar-horizontal();
|
||||
@include chat-scrollbar-vertical();
|
||||
|
||||
.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
padding: .5em .5em .5em;
|
||||
|
||||
&.height-transition {
|
||||
@include transition(max-height .25s ease-in-out, min-height .25s ease-in-out);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.step {
|
||||
&.step-welcome, &.step-finish {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
.text {
|
||||
align-self: center;
|
||||
h1 {
|
||||
line-height: 1.1em;
|
||||
|
||||
margin-bottom: .8em;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&.step-welcome h1 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-height: 15em;
|
||||
max-width: 15em;
|
||||
|
||||
align-self: center;
|
||||
margin-right: 1em;
|
||||
|
||||
img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* for step-identity or step-microphone */
|
||||
.container-settings-identity-profile, .container-settings-audio-microphone {
|
||||
padding: .5em;
|
||||
|
||||
.left .body {
|
||||
// background-color: #19191b;
|
||||
background-color: hsla(220, 4%, 13%, 1);
|
||||
.overlay {
|
||||
background-color: hsla(220, 4%, 13%, 1);
|
||||
|
||||
}
|
||||
.profile.selected {
|
||||
background-color: hsla(240, 2%, 8%, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.step-identity {
|
||||
}
|
||||
|
||||
&.step-microphone {
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
border-top: 1.25px solid rgba(49,49,53,1);
|
||||
padding: .5em;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -409,7 +409,7 @@
|
|||
background-image: linear-gradient(0deg, #008aff 2px, rgba(0, 150, 136, 0) 0), linear-gradient(0deg, #393939 1px, transparent 0);
|
||||
|
||||
&:focus {
|
||||
height: calc(2.25em - 1px); /* Center the blue line */
|
||||
height: 2.25em;
|
||||
|
||||
background-size: 100% 100%, 100% 100%;
|
||||
transition-duration: .3s;
|
||||
|
|
|
@ -2237,102 +2237,7 @@
|
|||
</div>
|
||||
|
||||
<div class="container audio-microphone">
|
||||
<div class="left">
|
||||
<div class="header">
|
||||
<a>{{tr "Select your Microphone Device" /}}</a>
|
||||
<button class="btn btn-info button-update">{{tr "Update" /}}</button>
|
||||
</div>
|
||||
<div class="body container-devices">
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="header">
|
||||
<a>{{tr "Microphone Settings" /}}</a>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-volume">
|
||||
<a>{{tr "Volume" /}}</a>
|
||||
<div class="container-slider">
|
||||
<div class="filler" style="width: 30%"></div>
|
||||
<div class="thumb container-tooltip" style="left: 30%">
|
||||
<div class="tooltip">
|
||||
<a>86%</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-select-vad">
|
||||
<div class="fieldset">
|
||||
<div class="container container-ppt">
|
||||
<label class="container-ppt">
|
||||
<div class="ratio-button">
|
||||
<input type="radio" name="vad-type" value="push_to_talk">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Push to Talk" /}}</a>
|
||||
</label>
|
||||
<div class="container-button">
|
||||
<button class="btn">{{tr "T" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container container-vad">
|
||||
<label>
|
||||
<div class="ratio-button">
|
||||
<input type="radio" name="vad-type" value="threshold">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Voice activity detection" /}}</a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="container container-always-active">
|
||||
<label>
|
||||
<div class="ratio-button">
|
||||
<input type="radio" name="vad-type" value="active">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Always active" /}}</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header">
|
||||
<a>{{tr "Sensitivity Settings" /}}</a>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-sensitivity">
|
||||
<div class="container-activity-bar">
|
||||
<div class="bar-hider" style="width: 80%;"></div>
|
||||
<div class="bar-error"></div>
|
||||
<div class="thumb container-tooltip" style="left: 20%">
|
||||
<div class="tooltip">
|
||||
<a>20%</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header">
|
||||
<a>{{tr "Advanced Settings" /}}</a>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-advanced">
|
||||
<div class="container-ppt-delay">
|
||||
<label>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" class="delay-enabled">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Delay on Push to Talk" /}}</a>
|
||||
</label>
|
||||
<div class="container-input">
|
||||
<input type="number" class="delay-time" min="0" max="4" step="0.1">
|
||||
<label>{{tr "Sec" /}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{include tmpl="#tmpl_settings-microphone" /}}
|
||||
</div>
|
||||
<div class="container audio-speaker">
|
||||
<div class="left">
|
||||
|
@ -2421,103 +2326,7 @@
|
|||
</div>
|
||||
|
||||
<div class="container identity-profiles">
|
||||
<div class="left">
|
||||
<div class="header">
|
||||
<a>{{tr "Your Profiles" /}}</a>
|
||||
<button class="btn btn-info button-create">{{tr "Create new" /}}</button>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-profiles">
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-danger button-delete">{{tr "Delete selected" /}}</button>
|
||||
<div class="spacer"></div>
|
||||
<button class="btn btn-success button-set-default">{{tr "Select as Default" /}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="header">
|
||||
<a>{{tr "Profile Settings" /}}</a>
|
||||
<div class="spacer"></div>
|
||||
<div class="container-avatar"></div>
|
||||
<button class="btn btn-info button-change-avatar">{{tr "Change Avatar" /}}</button>
|
||||
<!-- AVATAR -->
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-general">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Profile Name" /}}</label>
|
||||
<input class="form-control profile-name">
|
||||
<div class="invalid-feedback">{{tr "Profile name is invalid" /}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{tr "Default Nickname" /}}</label>
|
||||
<input class="form-control profile-default-name"
|
||||
placeholder="Another TeaSpeak user">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{tr "Identity Type" /}}</label>
|
||||
<select class="form-control profile-identity-type">
|
||||
<option value="unset" style="display: none">{{tr "Unset" /}}</option>
|
||||
<option value="teaforo">{{tr "Forum Account" /}}</option>
|
||||
<option value="teamspeak">{{tr "TeamSpeak Identity" /}}</option>
|
||||
<option value="nickname">{{tr "Nickname (Debug only!)" /}}</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">{{tr "Invalid identity type" /}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-teamspeak">
|
||||
<div class="container-valid">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Unique-ID" /}}</label>
|
||||
<input class="form-control unique-id" readonly>
|
||||
</div>
|
||||
<div class="container-level">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Level" /}}</label>
|
||||
<input class="form-control current-level" readonly>
|
||||
</div>
|
||||
<button class="btn button-improve">{{tr "Improve" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-invalid">
|
||||
{{tr "You have'nt generated/imported an identity." /}}<br>
|
||||
{{tr "Generate a new one or import one." /}}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-danger button-new">{{tr "Generate new" /}}</button>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-danger button-import">{{tr "Import identity" /}}
|
||||
</button>
|
||||
<button class="btn btn-success button-export">{{tr "Export identity" /}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-teaforo">
|
||||
<div class="container-valid">
|
||||
{{tr "You're using your forum account as identification" /}}
|
||||
</div>
|
||||
<div class="container-invalid">
|
||||
<a>{{tr "You cant use your TeaSpeak forum account. You're not connected with your forum Account!" /}}</a>
|
||||
<button class="btn btn-success button-setup">{{tr "Setup your connection" /}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-nickname">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Nickname" /}}</label>
|
||||
<input class="form-control nickname">
|
||||
<div class="invalid-feedback">{{tr "Invalid nickname. Name must be at least 5 characters" /}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{include tmpl="#tmpl_settings-profiles" /}}
|
||||
</div>
|
||||
<div class="container identity-forum">
|
||||
<div class="fill">
|
||||
|
@ -2558,6 +2367,238 @@
|
|||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script class="jsrender-template" id="tmpl_settings-microphone" type="text/html">
|
||||
<div class="container-settings-audio-microphone">
|
||||
<div class="left highlightable highlight-microphone-list">
|
||||
<div class="header">
|
||||
<a>{{tr "Select your Microphone Device" /}}</a>
|
||||
<button class="btn btn-info button-update">{{tr "Update" /}}</button>
|
||||
</div>
|
||||
<div class="body container-devices">
|
||||
<div class="overlay overlay-error">
|
||||
<a class="error-text"></a>
|
||||
</div>
|
||||
<div class="overlay overlay-loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right highlightable highlight-microphone-settings">
|
||||
<div class="header">
|
||||
<a>{{tr "Microphone Settings" /}}</a>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-volume">
|
||||
<a>{{tr "Volume" /}}</a>
|
||||
<div class="container-slider">
|
||||
<div class="filler" style="width: 30%"></div>
|
||||
<div class="thumb container-tooltip" style="left: 30%">
|
||||
<div class="tooltip">
|
||||
<a>86%</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-select-vad">
|
||||
<div class="fieldset">
|
||||
<div class="container container-ppt">
|
||||
<label class="container-ppt">
|
||||
<div class="ratio-button">
|
||||
<input type="radio" name="vad-type" value="push_to_talk">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Push to Talk" /}}</a>
|
||||
</label>
|
||||
<div class="container-button">
|
||||
<button class="btn">{{tr "T" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container container-vad">
|
||||
<label>
|
||||
<div class="ratio-button">
|
||||
<input type="radio" name="vad-type" value="threshold">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Voice activity detection" /}}</a>
|
||||
</label>
|
||||
</div>
|
||||
<div class="container container-always-active">
|
||||
<label>
|
||||
<div class="ratio-button">
|
||||
<input type="radio" name="vad-type" value="active">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Always active" /}}</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header">
|
||||
<a>{{tr "Sensitivity Settings" /}}</a>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-sensitivity">
|
||||
<div class="container-activity-bar">
|
||||
<div class="bar-hider" style="width: 80%;"></div>
|
||||
<div class="bar-error"></div>
|
||||
<div class="thumb container-tooltip" style="left: 20%">
|
||||
<div class="tooltip">
|
||||
<a>20%</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header">
|
||||
<a>{{tr "Advanced Settings" /}}</a>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-advanced">
|
||||
<div class="container-ppt-delay">
|
||||
<label>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" class="delay-enabled">
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
<a>{{tr "Delay on Push to Talk" /}}</a>
|
||||
</label>
|
||||
<div class="container-input">
|
||||
<input type="number" class="delay-time" min="0" max="4" step="0.1">
|
||||
<label>{{tr "Sec" /}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-background"></div>
|
||||
<div class="container-help-text window-resize-listener">
|
||||
<a class="help-text">Hello nice to see you. This is even working with new lines etc....</a>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script class="jsrender-template" id="tmpl_settings-profiles" type="text/html">
|
||||
<div class="container-settings-identity-profile">
|
||||
<div class="left highlight-profile-list highlightable">
|
||||
<div class="header">
|
||||
<a>{{tr "Your Profiles" /}}</a>
|
||||
<button class="btn btn-info button-create">{{tr "Create new" /}}</button>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-profiles">
|
||||
<div class="overlay overlay-error"><a class="error">error: error</a></div>
|
||||
<div class="overlay overlay-timeout">
|
||||
<a>{{tr "Timeout while loading" /}}</a><br>
|
||||
<button class="btn btn-blue button-reload-list">{{tr "Reload" /}}</button>
|
||||
</div>
|
||||
<div class="overlay overlay-empty">
|
||||
<a>{{tr "You've not profiles yet" /}}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-danger button-delete">{{tr "Delete selected" /}}</button>
|
||||
<div class="spacer"></div>
|
||||
<button class="btn btn-success button-set-default">{{tr "Select as Default" /}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="buttons-small">
|
||||
<button class="btn btn-danger button-delete">{{tr "Delete" /}}</button>
|
||||
<div class="spacer"></div>
|
||||
<button class="btn btn-success button-set-default">{{tr "Default" /}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="header">
|
||||
<a>{{tr "Profile Settings" /}}</a>
|
||||
<div class="spacer"></div>
|
||||
<div class="container-avatar"></div>
|
||||
<button class="btn btn-info button-change-avatar">{{tr "Change Avatar" /}}</button>
|
||||
<!-- AVATAR -->
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="container-general highlight-profile-settings highlightable">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Profile Name" /}}</label>
|
||||
<input class="form-control profile-name">
|
||||
<div class="invalid-feedback">{{tr "Profile name is invalid" /}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{tr "Default Nickname" /}}</label>
|
||||
<input class="form-control profile-default-name"
|
||||
placeholder="Another TeaSpeak user">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{tr "Identity Type" /}}</label>
|
||||
<select class="form-control profile-identity-type">
|
||||
<option value="error" style="display: none">error: error</option>
|
||||
<option value="unset" style="display: none">{{tr "Unset" /}}</option>
|
||||
<option value="teaforo">{{tr "Forum Account" /}}</option>
|
||||
<option value="teamspeak">{{tr "TeamSpeak Identity" /}}</option>
|
||||
<option value="nickname">{{tr "Nickname (Debug only!)" /}}</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">{{tr "Invalid identity type" /}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-teamspeak">
|
||||
<div class="container-valid">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Unique-ID" /}}</label>
|
||||
<input class="form-control unique-id" readonly>
|
||||
</div>
|
||||
<div class="container-level">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Level" /}}</label>
|
||||
<input class="form-control current-level" readonly>
|
||||
</div>
|
||||
<button class="btn button-improve">{{tr "Improve" /}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-invalid">
|
||||
{{tr "You have'nt generated/imported an identity." /}}<br>
|
||||
{{tr "Generate a new one or import one." /}}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-danger button-new">{{tr "Generate new" /}}</button>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-danger button-import">{{tr "Import identity" /}}
|
||||
</button>
|
||||
<button class="btn btn-success button-export">{{tr "Export identity" /}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-teaforo">
|
||||
<div class="container-valid">
|
||||
{{tr "You're using your forum account as identification" /}}
|
||||
</div>
|
||||
<div class="container-invalid">
|
||||
<a>{{tr "You cant use your TeaSpeak forum account. You're not connected with your forum Account!" /}}</a>
|
||||
<button class="btn btn-success button-setup">{{tr "Setup your connection" /}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-nickname">
|
||||
<div class="form-group">
|
||||
<label>{{tr "Nickname" /}}</label>
|
||||
<input class="form-control nickname">
|
||||
<div class="invalid-feedback">{{tr "Invalid nickname. Name must be at least 5 characters" /}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="container-highlight-dummy highlight-identity-settings highlightable"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-background"></div>
|
||||
<div class="container-help-text window-resize-listener">
|
||||
<a class="help-text">Hello nice to see you. This is even working with new lines etc....</a>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script class="jsrender-template" id="tmpl_settings-sound_entry" type="text/html">
|
||||
<div class="entry">
|
||||
<div class="column sound-name">
|
||||
|
@ -2860,12 +2901,6 @@
|
|||
</div>
|
||||
</script>
|
||||
|
||||
<script class="jsrender-template" id="tmpl_newcomer" type="text/html">
|
||||
<div> <!-- required for the renderer -->
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Permission overview -->
|
||||
<script class="jsrender-template" id="tmpl_server_permissions" type="text/html">
|
||||
<div class="container">
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Template modal newcomer</title>
|
||||
</head>
|
||||
<body>
|
||||
<script class="jsrender-template" id="tmpl_newcomer" type="text/html">
|
||||
<div> <!-- required for the renderer -->
|
||||
<div class="container-header">
|
||||
<!-- We don't have a title here because we've put it into the body. -->
|
||||
<!-- <div class="step step-welcome">{{tr "Welcome to the easy setup guide!" /}} </div> -->
|
||||
<div class="step step-identity">{{tr "Identity setup" /}}</div>
|
||||
<div class="step step-microphone">{{tr "Microphone setup" /}}</div>
|
||||
<div class="step step-speaker">{{tr "Speaker setup" /}}</div>
|
||||
<!-- <div class="step step-finish">{{tr "Setup finished" /}}</div> -->
|
||||
</div>
|
||||
<div class="container-body">
|
||||
<div class="body">
|
||||
<div class="step step-welcome">
|
||||
<div class="logo">
|
||||
<img src="img/teaspeak_cup_animated.png">
|
||||
</div>
|
||||
<div class="text">
|
||||
<h1>{{tr "Welcome dear TeaSpeak user." /}}</h1>
|
||||
{{tr "We would like to setup a few things before you're ready to go.<br>" /}}
|
||||
{{tr "Dont worry! We'll guide you thru the basic setup process." /}}<br>
|
||||
{{tr "Together we'll go thru these steps:" /}}
|
||||
<ol>
|
||||
<li>{{tr "Welcome Greeting" /}}</li>
|
||||
<li>{{tr "Microphone configuration" /}}</li>
|
||||
<li>{{tr "Identity setup" /}}</li>
|
||||
{{if !is_web}}
|
||||
<!-- <li>{{tr "Speaker configuration" /}}</li> -->
|
||||
{{/if}}
|
||||
</ol>
|
||||
{{tr "It is save to exit this guide at any point and directly jump ahead using the client." /}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="step step-microphone">
|
||||
{{include tmpl="#tmpl_settings-microphone" /}}
|
||||
</div>
|
||||
<div class="step step-identity">
|
||||
{{include tmpl="#tmpl_settings-profiles" /}}
|
||||
</div>
|
||||
<div class="step step-speaker">
|
||||
<h1>TODO</h1>
|
||||
</div>
|
||||
<div class="step step-finish">
|
||||
<div class="logo">
|
||||
<img src="img/teaspeak_cup_animated.png">
|
||||
</div>
|
||||
<div class="text">
|
||||
<h1>{{tr "Congratulations,<br>your done setting up TeaSpeak" /}}</h1>
|
||||
{{tr "You're done setting up your client. But dont worry,<br>" /}}
|
||||
{{tr "your could find all these settings within the settings menu<br>" /}}
|
||||
{{tr 'To open the client settings click on "tools" and than "settings"<br>' /}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="btn btn-red button-last-step">error: last step</button>
|
||||
<button class="btn btn-green button-next-step">error: next step</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
<svg id="Flat" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><g fill="#8690fa"><circle cx="48" cy="304" r="24"/><circle cx="192" cy="448" r="24"/><circle cx="101" cy="395" r="24"/><circle cx="48" cy="304" r="24"/><path d="m216 448a24 24 0 1 0 -24 24 24 24 0 0 0 24-24"/><circle cx="101" cy="395" r="24"/><circle cx="48" cy="192" r="24"/><circle cx="192" cy="48" r="24"/><circle cx="101" cy="101" r="24"/><circle cx="48" cy="192" r="24"/><path d="m216 48a24 24 0 1 1 -24-24 24 24 0 0 1 24 24"/><circle cx="101" cy="101" r="24"/><path d="m311.992 472a24 24 0 0 1 -6.433-47.123 185.506 185.506 0 0 0 96.328-64.917 181.561 181.561 0 0 0 38.113-111.96c0-81.5-55.349-154.248-134.6-176.922a24 24 0 0 1 13.2-46.147 236.543 236.543 0 0 1 121 82.086 230.506 230.506 0 0 1 .276 282.283 233.819 233.819 0 0 1 -121.421 81.812 24.04 24.04 0 0 1 -6.463.888z"/></g><path d="m456.029 488a24.512 24.512 0 0 1 -2.679-.148l-144-16a24 24 0 0 1 -20.474-30.278l40-144a24 24 0 1 1 46.248 12.848l-32.454 116.838 115.98 12.886a24 24 0 0 1 -2.621 47.854z" fill="#5153ff"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
|
@ -15,10 +15,17 @@ namespace events {
|
|||
}
|
||||
|
||||
export class Registry<Events> {
|
||||
private handler: {[key: string]:((event) => void)[]} = {};
|
||||
private readonly registry_uuid;
|
||||
|
||||
private handler: {[key: string]: ((event) => void)[]} = {};
|
||||
private connections: {[key: string]:Registry<string>[]} = {};
|
||||
private debug_prefix = undefined;
|
||||
|
||||
constructor() {
|
||||
this.registry_uuid = "evreg_data_" + guid();
|
||||
}
|
||||
|
||||
|
||||
enable_debug(prefix: string) { this.debug_prefix = prefix || "---"; }
|
||||
disable_debug() { this.debug_prefix = undefined; }
|
||||
|
||||
|
@ -28,12 +35,30 @@ namespace events {
|
|||
if(!Array.isArray(events))
|
||||
events = [events];
|
||||
|
||||
handler[this.registry_uuid] = {
|
||||
singleshot: false
|
||||
};
|
||||
for(const event of events) {
|
||||
const handlers = this.handler[event] || (this.handler[event] = []);
|
||||
handlers.push(handler);
|
||||
}
|
||||
}
|
||||
|
||||
/* one */
|
||||
one<T extends keyof Events>(event: T, handler: (event?: Events[T] & Event<T> & EventConvert<Events>) => void);
|
||||
one(events: (keyof Events)[], handler: (event?: Event<keyof Events> & EventConvert<Events>) => void);
|
||||
one(events, handler) {
|
||||
if(!Array.isArray(events))
|
||||
events = [events];
|
||||
|
||||
for(const event of events) {
|
||||
const handlers = this.handler[event] || (this.handler[event] = []);
|
||||
|
||||
handler[this.registry_uuid] = { singleshot: true };
|
||||
handlers.push(handler);
|
||||
}
|
||||
}
|
||||
|
||||
off<T extends keyof Events>(handler: (event?: Event<T>) => void);
|
||||
off<T extends keyof Events>(event: T, handler: (event?: Event<T> & EventConvert<Events>) => void);
|
||||
off(event: (keyof Events)[], handler: (event?: Event<keyof Events> & EventConvert<Events>) => void);
|
||||
|
@ -73,12 +98,22 @@ namespace events {
|
|||
as: function () { return this; }
|
||||
});
|
||||
|
||||
for(const handler of (this.handler[event_type as string] || []))
|
||||
for(const handler of (this.handler[event_type as string] || [])) {
|
||||
handler(event);
|
||||
|
||||
const reg_data = handler[this.registry_uuid];
|
||||
if(typeof reg_data === "object" && reg_data.singleshot)
|
||||
this.handler[event_type as string].remove(handler);
|
||||
}
|
||||
|
||||
for(const evhandler of (this.connections[event_type as string] || []))
|
||||
evhandler.fire(event_type as any, event as any);
|
||||
}
|
||||
|
||||
fire_async<T extends keyof Events>(event_type: T, data?: Events[T]) {
|
||||
setTimeout(() => this.fire(event_type, data));
|
||||
}
|
||||
|
||||
destory() {
|
||||
this.handler = {};
|
||||
}
|
||||
|
@ -312,6 +347,252 @@ namespace events {
|
|||
error_msg?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface newcomer {
|
||||
"show_step": {
|
||||
"step": "welcome" | "microphone" | "identity" | "finish"
|
||||
},
|
||||
"exit_guide": {
|
||||
ask_yesno: boolean
|
||||
},
|
||||
|
||||
"modal-shown": {},
|
||||
|
||||
|
||||
"step-status": {
|
||||
next_button: boolean,
|
||||
previous_button: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export namespace settings {
|
||||
export type ProfileInfo = {
|
||||
id: string,
|
||||
name: string,
|
||||
nickname: string,
|
||||
identity_type: "teaforo" | "teamspeak" | "nickname",
|
||||
|
||||
identity_forum?: {
|
||||
valid: boolean,
|
||||
fallback_name: string
|
||||
},
|
||||
identity_nickname?: {
|
||||
name: string,
|
||||
fallback_name: string
|
||||
},
|
||||
identity_teamspeak?: {
|
||||
unique_id: string,
|
||||
fallback_name: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface profiles {
|
||||
"reload-profile": { profile_id?: string },
|
||||
"select-profile": { profile_id: string },
|
||||
|
||||
"query-profile-list": { },
|
||||
"query-profile-list-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
|
||||
error?: string;
|
||||
profiles?: ProfileInfo[]
|
||||
}
|
||||
|
||||
"query-profile": { profile_id: string },
|
||||
"query-profile-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
profile_id: string,
|
||||
|
||||
error?: string;
|
||||
info?: ProfileInfo
|
||||
},
|
||||
|
||||
"select-identity-type": {
|
||||
profile_id: string,
|
||||
identity_type: "teamspeak" | "teaforo" | "nickname" | "unset"
|
||||
},
|
||||
|
||||
"query-profile-validity": { profile_id: string },
|
||||
"query-profile-validity-result": {
|
||||
profile_id: string,
|
||||
status: "error" | "success" | "timeout",
|
||||
|
||||
error?: string,
|
||||
valid?: boolean
|
||||
}
|
||||
|
||||
"create-profile": { name: string },
|
||||
"create-profile-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
name: string;
|
||||
|
||||
profile_id?: string;
|
||||
error?: string;
|
||||
},
|
||||
|
||||
"delete-profile": { profile_id: string },
|
||||
"delete-profile-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
profile_id: string,
|
||||
error?: string
|
||||
}
|
||||
|
||||
"set-default-profile": { profile_id: string },
|
||||
"set-default-profile-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
|
||||
/* the profile which now has the id "default" */
|
||||
old_profile_id: string,
|
||||
|
||||
/* the "default" profile which now has a new id */
|
||||
new_profile_id?: string
|
||||
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/* profile name events */
|
||||
"set-profile-name": {
|
||||
profile_id: string,
|
||||
name: string
|
||||
},
|
||||
"set-profile-name-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
profile_id: string,
|
||||
name?: string
|
||||
},
|
||||
|
||||
/* profile nickname events */
|
||||
"set-default-name": {
|
||||
profile_id: string,
|
||||
name: string | null
|
||||
},
|
||||
"set-default-name-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
profile_id: string,
|
||||
name?: string | null
|
||||
},
|
||||
|
||||
"query-identity-teamspeak": { profile_id: string },
|
||||
"query-identity-teamspeak-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
profile_id: string,
|
||||
|
||||
error?: string,
|
||||
level?: number
|
||||
}
|
||||
|
||||
"set-identity-name-name": { profile_id: string, name: string },
|
||||
"set-identity-name-name-result": {
|
||||
status: "error" | "success" | "timeout",
|
||||
profile_id: string,
|
||||
|
||||
error?: string,
|
||||
name?: string
|
||||
},
|
||||
|
||||
"generate-identity-teamspeak": { profile_id: string },
|
||||
"generate-identity-teamspeak-result": {
|
||||
profile_id: string,
|
||||
status: "error" | "success" | "timeout",
|
||||
|
||||
error?: string,
|
||||
|
||||
level?: number
|
||||
unique_id?: string
|
||||
},
|
||||
|
||||
"improve-identity-teamspeak-level": { profile_id: string },
|
||||
"improve-identity-teamspeak-level-update": {
|
||||
profile_id: string,
|
||||
new_level: number
|
||||
},
|
||||
|
||||
"import-identity-teamspeak": { profile_id: string },
|
||||
"import-identity-teamspeak-result": {
|
||||
profile_id: string,
|
||||
|
||||
level?: number
|
||||
unique_id?: string
|
||||
}
|
||||
|
||||
"export-identity-teamspeak": {
|
||||
profile_id: string,
|
||||
filename: string
|
||||
},
|
||||
|
||||
|
||||
"setup-forum-connection": {}
|
||||
}
|
||||
|
||||
export type MicrophoneSettings = "volume" | "vad-type" | "ppt-key" | "ppt-release-delay" | "ppt-release-delay-active" | "threshold-threshold";
|
||||
export interface microphone {
|
||||
"query-devices": { refresh_list: boolean },
|
||||
"query-device-result": {
|
||||
status: "success" | "error" | "timeout",
|
||||
|
||||
error?: string,
|
||||
devices?: {
|
||||
id: string,
|
||||
name: string,
|
||||
driver: string
|
||||
}[]
|
||||
active_device?: string;
|
||||
},
|
||||
|
||||
"query-settings": {},
|
||||
"query-settings-result": {
|
||||
status: "success" | "error" | "timeout",
|
||||
|
||||
error?: string,
|
||||
info?: {
|
||||
volume: number,
|
||||
vad_type: string,
|
||||
|
||||
vad_ppt: {
|
||||
key: ppt.KeyDescriptor,
|
||||
release_delay: number,
|
||||
release_delay_active: boolean
|
||||
},
|
||||
vad_threshold: {
|
||||
threshold: number
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"set-device": { device_id: string },
|
||||
"set-device-result": {
|
||||
device_id: string,
|
||||
status: "success" | "error" | "timeout",
|
||||
|
||||
error?: string
|
||||
},
|
||||
|
||||
"set-setting": {
|
||||
setting: MicrophoneSettings;
|
||||
value: any;
|
||||
},
|
||||
"set-setting-result": {
|
||||
setting: MicrophoneSettings,
|
||||
status: "success" | "error" | "timeout",
|
||||
|
||||
error?: string,
|
||||
value?: any
|
||||
},
|
||||
|
||||
"update-device-level": {
|
||||
devices: {
|
||||
device_id: string,
|
||||
status: "success" | "error",
|
||||
|
||||
level?: number,
|
||||
error?: string
|
||||
}[]
|
||||
},
|
||||
|
||||
"audio-initialized": {},
|
||||
"deinitialize": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -477,6 +477,13 @@ function main() {
|
|||
modal.open();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* for testing */
|
||||
if(settings.static_global(Settings.KEY_USER_IS_NEW)) {
|
||||
const modal = Modals.openModalNewcomer();
|
||||
modal.close_listener.push(() => settings.changeGlobal(Settings.KEY_USER_IS_NEW, false));
|
||||
}
|
||||
}
|
||||
|
||||
const task_teaweb_starter: loader.Task = {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
namespace profiles {
|
||||
|
||||
export class ConnectionProfile {
|
||||
id: string;
|
||||
|
||||
|
@ -8,14 +7,14 @@ namespace profiles {
|
|||
default_password: string;
|
||||
|
||||
selected_identity_type: string = "unset";
|
||||
identities: {[key:string]:identities.Identity} = {};
|
||||
identities: { [key: string]: identities.Identity } = {};
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
connect_username() : string {
|
||||
if(this.default_username && this.default_username !== "Another TeaSpeak user")
|
||||
connect_username(): string {
|
||||
if (this.default_username && this.default_username !== "Another TeaSpeak user")
|
||||
return this.default_username;
|
||||
|
||||
let selected = this.selected_identity();
|
||||
|
@ -23,41 +22,41 @@ namespace profiles {
|
|||
return name || "Another TeaSpeak user";
|
||||
}
|
||||
|
||||
selected_identity(current_type?: identities.IdentitifyType) : identities.Identity {
|
||||
if(!current_type)
|
||||
selected_identity(current_type?: identities.IdentitifyType): identities.Identity {
|
||||
if (!current_type)
|
||||
current_type = this.selected_type();
|
||||
|
||||
if(current_type === undefined)
|
||||
if (current_type === undefined)
|
||||
return undefined;
|
||||
|
||||
if(current_type == identities.IdentitifyType.TEAFORO) {
|
||||
if (current_type == identities.IdentitifyType.TEAFORO) {
|
||||
return identities.static_forum_identity();
|
||||
} else if(current_type == identities.IdentitifyType.TEAMSPEAK || current_type == identities.IdentitifyType.NICKNAME) {
|
||||
return this.identities[this.selected_identity_type.toLowerCase()];
|
||||
} else if (current_type == identities.IdentitifyType.TEAMSPEAK || current_type == identities.IdentitifyType.NICKNAME) {
|
||||
return this.identities[identities.IdentitifyType[current_type].toLowerCase()];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
selected_type?() : identities.IdentitifyType {
|
||||
return identities.IdentitifyType[this.selected_identity_type.toUpperCase()];
|
||||
selected_type?(): identities.IdentitifyType {
|
||||
return this.selected_identity_type ? identities.IdentitifyType[this.selected_identity_type.toUpperCase()] : undefined;
|
||||
}
|
||||
|
||||
set_identity(type: identities.IdentitifyType, identity: identities.Identity) {
|
||||
this.identities[identities.IdentitifyType[type].toLowerCase()] = identity;
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler?(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler?(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler {
|
||||
const identity = this.selected_identity();
|
||||
if(!identity)
|
||||
if (!identity)
|
||||
return undefined;
|
||||
return identity.spawn_identity_handshake_handler(connection);
|
||||
}
|
||||
|
||||
encode?() : string {
|
||||
encode?(): string {
|
||||
const identity_data = {};
|
||||
for(const key in this.identities)
|
||||
if(this.identities[key])
|
||||
for (const key in this.identities)
|
||||
if (this.identities[key])
|
||||
identity_data[key] = this.identities[key].encode();
|
||||
|
||||
return JSON.stringify({
|
||||
|
@ -71,17 +70,17 @@ namespace profiles {
|
|||
});
|
||||
}
|
||||
|
||||
valid() : boolean {
|
||||
valid(): boolean {
|
||||
const identity = this.selected_identity();
|
||||
if(!identity || !identity.valid()) return false;
|
||||
if (!identity || !identity.valid()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function decode_profile(data) : Promise<ConnectionProfile | string> {
|
||||
async function decode_profile(data): Promise<ConnectionProfile | string> {
|
||||
data = JSON.parse(data);
|
||||
if(data.version !== 1)
|
||||
if (data.version !== 1)
|
||||
return "invalid version";
|
||||
|
||||
const result: ConnectionProfile = new ConnectionProfile(data.id);
|
||||
|
@ -90,14 +89,14 @@ namespace profiles {
|
|||
result.profile_name = data.profile_name;
|
||||
result.selected_identity_type = (data.identity_type || "").toLowerCase();
|
||||
|
||||
if(data.identity_data) {
|
||||
for(const key in data.identity_data) {
|
||||
if (data.identity_data) {
|
||||
for (const key in data.identity_data) {
|
||||
const type = identities.IdentitifyType[key.toUpperCase() as string];
|
||||
const _data = data.identity_data[key];
|
||||
if(type == undefined) continue;
|
||||
if (type == undefined) continue;
|
||||
|
||||
const identity = await identities.decode_identity(type, _data);
|
||||
if(identity == undefined) continue;
|
||||
if (identity == undefined) continue;
|
||||
|
||||
result.identities[key.toLowerCase()] = identity;
|
||||
}
|
||||
|
@ -112,6 +111,7 @@ namespace profiles {
|
|||
}
|
||||
|
||||
let available_profiles: ConnectionProfile[] = [];
|
||||
|
||||
export async function load() {
|
||||
available_profiles = [];
|
||||
|
||||
|
@ -119,7 +119,7 @@ namespace profiles {
|
|||
let profiles_data: ProfilesData = (() => {
|
||||
try {
|
||||
return profiles_json ? JSON.parse(profiles_json) : {version: 0} as any;
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
debugger;
|
||||
console.error(tr("Invalid profile json! Resetting profiles :( (%o)"), profiles_json);
|
||||
createErrorModal(tr("Profile data invalid"), MessageHelper.formatMessage(tr("The profile data is invalid.{:br:}This might cause data loss."))).open();
|
||||
|
@ -127,16 +127,16 @@ namespace profiles {
|
|||
}
|
||||
})();
|
||||
|
||||
if(profiles_data.version === 0) {
|
||||
if (profiles_data.version === 0) {
|
||||
profiles_data = {
|
||||
version: 1,
|
||||
profiles: []
|
||||
};
|
||||
}
|
||||
if(profiles_data.version == 1) {
|
||||
for(const profile_data of profiles_data.profiles) {
|
||||
if (profiles_data.version == 1) {
|
||||
for (const profile_data of profiles_data.profiles) {
|
||||
const profile = await decode_profile(profile_data);
|
||||
if(typeof(profile) === 'string') {
|
||||
if (typeof (profile) === 'string') {
|
||||
console.error(tr("Failed to load profile. Reason: %s, Profile data: %s"), profile, profiles_data);
|
||||
continue;
|
||||
}
|
||||
|
@ -144,9 +144,9 @@ namespace profiles {
|
|||
}
|
||||
}
|
||||
|
||||
if(!find_profile("default")) { //Create a default profile and teaforo profile
|
||||
if (!find_profile("default")) { //Create a default profile and teaforo profile
|
||||
{
|
||||
const profile = create_new_profile("default","default");
|
||||
const profile = create_new_profile("default", "default");
|
||||
profile.default_password = "";
|
||||
profile.default_username = "";
|
||||
profile.profile_name = "Default Profile";
|
||||
|
@ -161,13 +161,13 @@ namespace profiles {
|
|||
await identity.improve_level(8, 1, () => active);
|
||||
profile.set_identity(identities.IdentitifyType.TEAMSPEAK, identity);
|
||||
profile.selected_identity_type = identities.IdentitifyType[identities.IdentitifyType.TEAMSPEAK];
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
createErrorModal(tr("Failed to generate default identity"), tr("Failed to generate default identity!<br>Please manually generate the identity within your settings => profiles")).open();
|
||||
}
|
||||
}
|
||||
|
||||
{ /* forum identity (works only when connected to the forum) */
|
||||
const profile = create_new_profile("TeaSpeak Forum","teaforo");
|
||||
const profile = create_new_profile("TeaSpeak Forum", "teaforo");
|
||||
profile.default_password = "";
|
||||
profile.default_username = "";
|
||||
profile.profile_name = "TeaSpeak Forum profile";
|
||||
|
@ -180,7 +180,7 @@ namespace profiles {
|
|||
}
|
||||
}
|
||||
|
||||
export function create_new_profile(name: string, id?: string) : ConnectionProfile {
|
||||
export function create_new_profile(name: string, id?: string): ConnectionProfile {
|
||||
const profile = new ConnectionProfile(id || guid());
|
||||
profile.profile_name = name;
|
||||
profile.default_username = "";
|
||||
|
@ -189,9 +189,10 @@ namespace profiles {
|
|||
}
|
||||
|
||||
let _requires_save = false;
|
||||
|
||||
export function save() {
|
||||
const profiles: string[] = [];
|
||||
for(const profile of available_profiles)
|
||||
for (const profile of available_profiles)
|
||||
profiles.push(profile.encode());
|
||||
|
||||
const data = JSON.stringify({
|
||||
|
@ -205,42 +206,43 @@ namespace profiles {
|
|||
_requires_save = true;
|
||||
}
|
||||
|
||||
export function requires_save() : boolean {
|
||||
export function requires_save(): boolean {
|
||||
return _requires_save;
|
||||
}
|
||||
|
||||
export function profiles() : ConnectionProfile[] {
|
||||
export function profiles(): ConnectionProfile[] {
|
||||
return available_profiles;
|
||||
}
|
||||
|
||||
export function find_profile(id: string) : ConnectionProfile | undefined {
|
||||
for(const profile of profiles())
|
||||
if(profile.id == id)
|
||||
export function find_profile(id: string): ConnectionProfile | undefined {
|
||||
for (const profile of profiles())
|
||||
if (profile.id == id)
|
||||
return profile;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function find_profile_by_name(name: string) : ConnectionProfile | undefined {
|
||||
export function find_profile_by_name(name: string): ConnectionProfile | undefined {
|
||||
name = name.toLowerCase();
|
||||
for(const profile of profiles())
|
||||
if((profile.profile_name || "").toLowerCase() == name)
|
||||
for (const profile of profiles())
|
||||
if ((profile.profile_name || "").toLowerCase() == name)
|
||||
return profile;
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
export function default_profile() : ConnectionProfile {
|
||||
export function default_profile(): ConnectionProfile {
|
||||
return find_profile("default");
|
||||
}
|
||||
|
||||
export function set_default_profile(profile: ConnectionProfile) {
|
||||
const old_default = default_profile();
|
||||
if(old_default && old_default != profile) {
|
||||
if (old_default && old_default != profile) {
|
||||
old_default.id = guid();
|
||||
}
|
||||
profile.id = "default";
|
||||
return old_default;
|
||||
}
|
||||
|
||||
export function delete_profile(profile: ConnectionProfile) {
|
||||
|
|
|
@ -107,6 +107,8 @@ namespace profiles.identities {
|
|||
export function update_forum() {
|
||||
if(forum.logged_in() && (!static_identity || static_identity.data() !== forum.data())) {
|
||||
static_identity = new TeaForumIdentity(forum.data());
|
||||
} else {
|
||||
static_identity = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,11 @@ class StaticSettings extends SettingsBase {
|
|||
}
|
||||
|
||||
class Settings extends StaticSettings {
|
||||
static readonly KEY_USER_IS_NEW: SettingsKey<boolean> = {
|
||||
key: 'user_is_new_user',
|
||||
default_value: true
|
||||
};
|
||||
|
||||
static readonly KEY_DISABLE_COSMETIC_SLOWDOWN: SettingsKey<boolean> = {
|
||||
key: 'disable_cosmetic_slowdown',
|
||||
description: 'Disable the cosmetic slowdows in some processes, like icon upload.'
|
||||
|
|
|
@ -3,19 +3,432 @@
|
|||
/// <reference path="../../proto.ts" />
|
||||
|
||||
namespace Modals {
|
||||
export function openModalNewcomer() {
|
||||
const next_step: {[key: string]:string} = {
|
||||
"welcome": "microphone",
|
||||
//"microphone": app.is_web() ? "identity" : "speaker", /* speaker setup only for the native client! */
|
||||
"microphone": "identity",
|
||||
"speaker": "identity",
|
||||
"identity": "finish"
|
||||
};
|
||||
const last_step: {[key: string]:string} = (() => {
|
||||
const result = {};
|
||||
for(const key of Object.keys(next_step))
|
||||
if(!result[next_step[key]])
|
||||
result[next_step[key]] = key;
|
||||
return result;
|
||||
})();
|
||||
|
||||
export function openModalNewcomer() : Modal {
|
||||
let modal = createModal({
|
||||
header: tra("Welcome to the {}", app.is_web() ? "TeaWeb-Client" : "TeaSpeak-Client"),
|
||||
body: () => $("#tmpl_newcomer").renderTag().children(),
|
||||
header: tra("Welcome to the {}", app.is_web() ? "TeaSpeak - Web client" : "TeaSpeak - Client"),
|
||||
body: () => $("#tmpl_newcomer").renderTag({
|
||||
is_web: app.is_web()
|
||||
}).children(),
|
||||
footer: null,
|
||||
|
||||
width: "",
|
||||
closeable: false
|
||||
});
|
||||
|
||||
//TODO!
|
||||
const event_registry = new events.Registry<events.modal.newcomer>();
|
||||
event_registry.enable_debug("newcomer");
|
||||
|
||||
modal.htmlTag.find(".modal-body").addClass("modal-newcomer");
|
||||
|
||||
initializeBasicFunctionality(modal.htmlTag, event_registry);
|
||||
initializeStepWelcome(modal.htmlTag.find(".container-body .step.step-welcome"), event_registry);
|
||||
initializeStepIdentity(modal.htmlTag.find(".container-body .step.step-identity"), event_registry);
|
||||
initializeStepMicrophone(modal.htmlTag.find(".container-body .step.step-microphone"), event_registry, modal);
|
||||
initializeStepFinish(modal.htmlTag.find(".container-body .step.step-finish"), event_registry);
|
||||
|
||||
event_registry.on("exit_guide", event => {
|
||||
if(event.ask_yesno)
|
||||
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to skip the basic setup guide?"), result => {
|
||||
if(result)
|
||||
event_registry.fire("exit_guide", {ask_yesno: false});
|
||||
});
|
||||
else
|
||||
modal.close();
|
||||
});
|
||||
|
||||
event_registry.fire("show_step", {step: "welcome"});
|
||||
modal.open();
|
||||
event_registry.fire_async("modal-shown");
|
||||
return modal;
|
||||
}
|
||||
|
||||
function initializeBasicFunctionality(tag: JQuery, event_registry: events.Registry<events.modal.newcomer>) {
|
||||
const container_header = tag.find(".container-header");
|
||||
const tag_body = tag.find(".container-body .body");
|
||||
|
||||
/* step navigation */
|
||||
event_registry.on("show_step", event => {
|
||||
tag_body.find(".step").addClass("hidden");
|
||||
container_header.find(".step").addClass("hidden");
|
||||
|
||||
tag_body.find(".step.step-" + event.step).removeClass("hidden");
|
||||
container_header.find(".step.step-" + event.step).removeClass("hidden");
|
||||
});
|
||||
|
||||
/* button controller */
|
||||
{
|
||||
const buttons = tag.find(".buttons");
|
||||
const button_last_step = buttons.find(".button-last-step");
|
||||
const button_next_step = buttons.find(".button-next-step");
|
||||
|
||||
button_last_step.on('click', event => {
|
||||
if(last_step[current_step])
|
||||
event_registry.fire("show_step", { step: last_step[current_step] as any });
|
||||
else
|
||||
event_registry.fire("exit_guide", {ask_yesno: true});
|
||||
});
|
||||
|
||||
let current_step;
|
||||
button_next_step.on('click', event => {
|
||||
if(next_step[current_step])
|
||||
event_registry.fire("show_step", { step: next_step[current_step] as any });
|
||||
else
|
||||
event_registry.fire("exit_guide", {ask_yesno: false});
|
||||
});
|
||||
|
||||
event_registry.on("show_step", event => {
|
||||
current_step = event.step;
|
||||
button_next_step.text(next_step[current_step] ? tr("Next step") : tr("Finish guide"));
|
||||
button_last_step.text(last_step[current_step] ? tr("Last step") : tr("Skip guide"));
|
||||
});
|
||||
|
||||
event_registry.on("show_step", event => button_next_step.prop("disabled", true));
|
||||
event_registry.on("show_step", event => button_last_step.prop("disabled", true));
|
||||
|
||||
event_registry.on("step-status", event => button_next_step.prop("disabled", !event.next_button));
|
||||
event_registry.on("step-status", event => button_last_step.prop("disabled", !event.previous_button));
|
||||
}
|
||||
}
|
||||
|
||||
function initializeStepWelcome(tag: JQuery, event_registry: events.Registry<events.modal.newcomer>) {
|
||||
event_registry.on("show_step", e => {
|
||||
if(e.step !== "welcome") return;
|
||||
|
||||
event_registry.fire_async("step-status", { next_button: true, previous_button: true });
|
||||
});
|
||||
}
|
||||
|
||||
function initializeStepFinish(tag: JQuery, event_registry: events.Registry<events.modal.newcomer>) {
|
||||
event_registry.on("show_step", e => {
|
||||
if(e.step !== "finish") return;
|
||||
|
||||
event_registry.fire_async("step-status", {next_button: true, previous_button: true });
|
||||
});
|
||||
}
|
||||
|
||||
function initializeStepIdentity(tag: JQuery, event_registry: events.Registry<events.modal.newcomer>) {
|
||||
const profile_events = new events.Registry<events.modal.settings.profiles>();
|
||||
profile_events.enable_debug("settings-identity");
|
||||
modal_settings.initialize_identity_profiles_controller(profile_events);
|
||||
modal_settings.initialize_identity_profiles_view(tag, profile_events, { forum_setuppable: false });
|
||||
|
||||
let step_shown = false;
|
||||
let help_animation_done = false;
|
||||
const profiles_valid = () => profiles.profiles().findIndex(e => e.valid()) !== -1;
|
||||
const update_step_status = () => {
|
||||
event_registry.fire_async("step-status", { next_button: help_animation_done && profiles_valid(), previous_button: help_animation_done });
|
||||
};
|
||||
profile_events.on("query-profile-validity-result", event => step_shown && event.status === "success" && event.valid && update_step_status());
|
||||
event_registry.on("show_step", e => {
|
||||
step_shown = e.step === "identity";
|
||||
if(!step_shown) return;
|
||||
|
||||
update_step_status();
|
||||
});
|
||||
|
||||
/* the help sequence */
|
||||
{
|
||||
const container = tag.find(".container-settings-identity-profile");
|
||||
const container_help_text = tag.find(".container-help-text");
|
||||
|
||||
const container_profile_list = tag.find(".highlight-profile-list");
|
||||
const container_profile_settings = tag.find(".highlight-profile-settings");
|
||||
const container_identity_settings = tag.find(".highlight-identity-settings");
|
||||
|
||||
let is_first_show = true;
|
||||
|
||||
event_registry.on("show_step", event => {
|
||||
if(!is_first_show || event.step !== "identity") return;
|
||||
is_first_show = false;
|
||||
|
||||
container.addClass("help-shown");
|
||||
|
||||
|
||||
const text = tr(
|
||||
"After you've successfully set upped your microphone,\n" +
|
||||
"lets setup some profiles and identities!\n" +
|
||||
"\n" +
|
||||
"Connect profiles determine, how your're authenticating yourself with the server.\n" +
|
||||
"So basically they're your identity.\n" +
|
||||
"In the following I'll guid you thru the options and GUI elements.\n" +
|
||||
"\n" +
|
||||
"To continue click anywhere on the screen."
|
||||
);
|
||||
set_help_text(text);
|
||||
$("body").one('mousedown', event => show_profile_list_help());
|
||||
});
|
||||
|
||||
const set_help_text = text => {
|
||||
container_help_text.empty();
|
||||
text.split("\n").forEach(e => container_help_text.append(e == "" ? $.spawn("br") : $.spawn("a").text(e)));
|
||||
};
|
||||
|
||||
const show_profile_list_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container_profile_list.addClass("highlighted");
|
||||
|
||||
const update_position = () => {
|
||||
const font_size = parseFloat(getComputedStyle(container_help_text[0]).fontSize);
|
||||
|
||||
const offset = container_profile_list.offset();
|
||||
const abs = container.offset();
|
||||
|
||||
container_help_text.css({
|
||||
top: offset.top - abs.top,
|
||||
left: ((offset.left - abs.left) + container_profile_list.outerWidth() + font_size) + "px",
|
||||
right: "1em",
|
||||
bottom: "1em"
|
||||
});
|
||||
};
|
||||
update_position();
|
||||
container_help_text.off('resize').on('resize', update_position);
|
||||
|
||||
const text = tr(
|
||||
"You could have as many connect profiles as you want.\n" +
|
||||
"All created profiles will be listed here.\n" +
|
||||
"\n" +
|
||||
"To create a new profile just simply click the blue button \"Create profile\" and enter a profile name.\n" +
|
||||
"If you want to delete a profile you've to select that profile and click the delete button.\n" +
|
||||
"\n" +
|
||||
"By default we're using the \"default\" profile\n" +
|
||||
"to connect to any server. o change the default profile\n" +
|
||||
"just select the new profile and press the \"select as default\" button.\n" +
|
||||
"\n" +
|
||||
"To continue click anywhere on the screen."
|
||||
);
|
||||
set_help_text(text);
|
||||
$("body").one('mousedown', event => show_profile_settings_help());
|
||||
};
|
||||
|
||||
const show_profile_settings_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container_profile_settings.addClass("highlighted");
|
||||
|
||||
const update_position = () => {
|
||||
const font_size = parseFloat(getComputedStyle(container_help_text[0]).fontSize);
|
||||
const container_settings_offset = container_profile_settings.offset();
|
||||
const right = container_profile_settings.outerWidth() + font_size * 2;
|
||||
container_help_text.css({
|
||||
top: container_settings_offset.top - container.offset().top,
|
||||
left: "1em",
|
||||
right: right + "px",
|
||||
bottom: "1em"
|
||||
});
|
||||
};
|
||||
set_help_text(tr(
|
||||
"In the upper left, you'll find the profile settings for the selected profile.\n" +
|
||||
"You could give each profile an individual name. You could also specify the default connect nickname here.\n" +
|
||||
"\n" +
|
||||
"The last option \"Identity Type\" determines on what your identity is based on.\n" +
|
||||
"TeaSpeak has two possibilities to identify yourself:\n" +
|
||||
"1. Identify yourself by your TeaSpeak forum account\n" +
|
||||
"2. Identify by an own generated cryptographic identity\n" +
|
||||
"The second methods is also known as a TeamSpeak 3 identity.\n" +
|
||||
"\n" +
|
||||
"To continue click anywhere on the screen."
|
||||
));
|
||||
update_position();
|
||||
container_help_text.off('resize').on('resize', update_position);
|
||||
|
||||
$("body").one('mousedown', event => show_identity_settings_help());
|
||||
};
|
||||
|
||||
const show_identity_settings_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container_identity_settings.addClass("highlighted");
|
||||
|
||||
const update_position = () => {
|
||||
const font_size = parseFloat(getComputedStyle(container_help_text[0]).fontSize);
|
||||
const container_identity_offset = container_identity_settings.offset();
|
||||
const right = container_profile_settings.outerWidth() + font_size * 2;
|
||||
container_help_text.css({
|
||||
top: container_identity_offset.top - container.offset().top,
|
||||
left: "1em",
|
||||
right: right + "px",
|
||||
bottom: "1em"
|
||||
});
|
||||
};
|
||||
set_help_text(tr(
|
||||
"When selecting an identify type, some corresponding will pop up in the highlighted area.\n" +
|
||||
"\n" +
|
||||
"But don't worry, we've already generated\n" +
|
||||
"a cryptographic identity for you!\n" +
|
||||
"So you don't have to change anything before you start."
|
||||
));
|
||||
update_position();
|
||||
container_help_text.off('resize').on('resize', update_position);
|
||||
|
||||
$("body").one('mousedown', event => hide_help());
|
||||
};
|
||||
|
||||
const hide_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container.addClass("hide-help");
|
||||
setTimeout(() => container.removeClass("help-shown"), 1000);
|
||||
container_help_text.off('resize');
|
||||
|
||||
help_animation_done = true;
|
||||
update_step_status();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function initializeStepMicrophone(tag: JQuery, event_registry: events.Registry<events.modal.newcomer>, modal: Modal) {
|
||||
const microphone_events = new events.Registry<events.modal.settings.microphone>();
|
||||
//microphone_events.enable_debug("settings-microphone");
|
||||
modal_settings.initialize_audio_microphone_controller(microphone_events);
|
||||
modal_settings.initialize_audio_microphone_view(tag, microphone_events);
|
||||
modal.close_listener.push(() => microphone_events.fire_async("deinitialize"));
|
||||
|
||||
let help_animation_done = false;
|
||||
const update_step_status = () => event_registry.fire_async("step-status", { next_button: help_animation_done, previous_button: help_animation_done });
|
||||
event_registry.on("show_step", e => {
|
||||
if(e.step !== "microphone") return;
|
||||
|
||||
update_step_status();
|
||||
});
|
||||
|
||||
/* the help sequence */
|
||||
{
|
||||
const container = tag.find(".container-settings-audio-microphone");
|
||||
const container_help_text = tag.find(".container-help-text");
|
||||
|
||||
const container_profile_list = tag.find(".highlight-microphone-list");
|
||||
const container_profile_settings = tag.find(".highlight-microphone-settings");
|
||||
|
||||
let is_first_show = true;
|
||||
event_registry.on("show_step", event => {
|
||||
if(!is_first_show || event.step !== "microphone") return;
|
||||
is_first_show = false;
|
||||
|
||||
container.addClass("help-shown");
|
||||
const text = tr(
|
||||
"Firstly we need to setup a microphone.\n" +
|
||||
"Let me guide you thru the basic UI elements.\n" +
|
||||
"\n" +
|
||||
"To continue click anywhere on the screen."
|
||||
);
|
||||
set_help_text(text);
|
||||
$("body").one('mousedown', event => show_microphone_list_help());
|
||||
});
|
||||
|
||||
const set_help_text = text => {
|
||||
container_help_text.empty();
|
||||
text.split("\n").forEach(e => container_help_text.append(e == "" ? $.spawn("br") : $.spawn("a").text(e)));
|
||||
};
|
||||
|
||||
const show_microphone_list_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container_profile_list.addClass("highlighted");
|
||||
|
||||
const update_position = () => {
|
||||
const font_size = parseFloat(getComputedStyle(container_help_text[0]).fontSize);
|
||||
|
||||
const offset = container_profile_list.offset();
|
||||
const abs = container.offset();
|
||||
|
||||
container_help_text.css({
|
||||
top: offset.top - abs.top,
|
||||
left: ((offset.left - abs.left) + container_profile_list.outerWidth() + font_size) + "px",
|
||||
right: "1em",
|
||||
bottom: "1em"
|
||||
});
|
||||
};
|
||||
update_position();
|
||||
container_help_text.off('resize').on('resize', update_position);
|
||||
|
||||
const text = tr(
|
||||
"All your available microphones are listed within this box.\n" +
|
||||
"\n" +
|
||||
"The currently selected microphone\n" +
|
||||
"is marked with a green checkmark. To change the selected microphone\n" +
|
||||
"just click on the new one.\n" +
|
||||
"\n" +
|
||||
"To continue click anywhere on the screen."
|
||||
);
|
||||
set_help_text(text);
|
||||
$("body").one('mousedown', event => show_microphone_settings_help());
|
||||
};
|
||||
|
||||
const show_microphone_settings_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container_profile_settings.addClass("highlighted");
|
||||
|
||||
const update_position = () => {
|
||||
const font_size = parseFloat(getComputedStyle(container_help_text[0]).fontSize);
|
||||
const container_settings_offset = container_profile_settings.offset();
|
||||
const right = container_profile_settings.outerWidth() + font_size * 2;
|
||||
container_help_text.css({
|
||||
top: container_settings_offset.top - container.offset().top,
|
||||
left: "1em",
|
||||
right: right + "px",
|
||||
bottom: "1em"
|
||||
});
|
||||
};
|
||||
|
||||
container_help_text.empty();
|
||||
container_help_text.append($.spawn("div").addClass("help-microphone-settings").append(
|
||||
$.spawn("a").text(tr("On the right side you'll find all microphone settings.")),
|
||||
$.spawn("br"),
|
||||
$.spawn("a").text("TeaSpeak has three voice activity detection types:"),
|
||||
$.spawn("ol").append(
|
||||
$.spawn("li").addClass("vad-type").append(
|
||||
$.spawn("a").addClass("title").text(tr("Push to Talk")),
|
||||
$.spawn("a").addClass("description").html(tr(
|
||||
"To transmit audio data you'll have to<br>" +
|
||||
"press a key. The key could be selected " +
|
||||
"via the button right to the radio button."
|
||||
))
|
||||
),
|
||||
$.spawn("li").addClass("vad-type").append(
|
||||
$.spawn("a").addClass("title").text(tr("Voice activity detection")),
|
||||
$.spawn("a").addClass("description").html(tr(
|
||||
"In this mode, TeaSpeak will continuously analyze your microphone input. " +
|
||||
"If the audio level is grater than a certain threshold, " +
|
||||
"the audio will be transmitted. " +
|
||||
"The threshold is changeable via the \"Sensitivity Settings\" slider."
|
||||
))
|
||||
),
|
||||
$.spawn("li").addClass("vad-type").append(
|
||||
$.spawn("a").addClass("title").html(tr("Always active")),
|
||||
$.spawn("a").addClass("description").text(tr(
|
||||
"Continuously transmit any audio data.\n"
|
||||
))
|
||||
)
|
||||
),
|
||||
$.spawn("br"),
|
||||
$.spawn("a").text(tr("Now you're ready to configure your microphone. Just click anywhere on the screen."))
|
||||
));
|
||||
update_position();
|
||||
container_help_text.off('resize').on('resize', update_position);
|
||||
|
||||
$("body").one('mousedown', event => hide_help());
|
||||
};
|
||||
|
||||
const hide_help = () => {
|
||||
container.find(".highlighted").removeClass("highlighted");
|
||||
container.addClass("hide-help");
|
||||
setTimeout(() => container.removeClass("help-shown"), 1000);
|
||||
container_help_text.off('resize');
|
||||
|
||||
help_animation_done = true;
|
||||
update_step_status();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,7 @@ namespace permissions {
|
|||
PermissionType.B_SERVERQUERY_LOGIN,
|
||||
|
||||
//Not sensefull to assign virtual server permission to channel groups
|
||||
...Object.keys(PermissionType).filter(e => e.toLowerCase().startsWith("b_virtualserver")).map(e => PermissionType[e]),
|
||||
...Object.keys(PermissionType).filter(e => e.toLowerCase().startsWith("b_virtualserver") && e.toLowerCase() === "b_virtualserver_channel_permission_list").map(e => PermissionType[e]),
|
||||
|
||||
//Not sensefull to require some playlist permissions
|
||||
...Object.keys(PermissionType).filter(e => e.toLowerCase().startsWith("i_playlist")).map(e => PermissionType[e]),
|
||||
|
|
|
@ -197,13 +197,16 @@ class RecorderProfile {
|
|||
}
|
||||
|
||||
get_vad_type() { return this.config.vad_type; }
|
||||
set_vad_type(type: VadType) {
|
||||
set_vad_type(type: VadType) : boolean {
|
||||
if(this.config.vad_type === type)
|
||||
return;
|
||||
return true;
|
||||
if(["push_to_talk", "threshold", "active"].findIndex(e => e === type) == -1)
|
||||
return false;
|
||||
|
||||
this.config.vad_type = type;
|
||||
this.reinitialize_filter();
|
||||
this.save();
|
||||
return true;
|
||||
}
|
||||
|
||||
get_vad_threshold() { return parseInt(this.config.vad_threshold.threshold as any); } /* for some reason it might be a string... */
|
||||
|
|
|
@ -187,6 +187,7 @@ const loader_javascript = {
|
|||
"js/ui/modal/ModalBookmarks.js",
|
||||
"js/ui/modal/ModalConnect.js",
|
||||
"js/ui/modal/ModalSettings.js",
|
||||
"js/ui/modal/ModalNewcomer.js",
|
||||
"js/ui/modal/ModalCreateChannel.js",
|
||||
"js/ui/modal/ModalServerEdit.js",
|
||||
"js/ui/modal/ModalChangeVolume.js",
|
||||
|
@ -369,6 +370,7 @@ const loader_style = {
|
|||
"css/static/modal-musicmanage.css",
|
||||
"css/static/modal-serverinfobandwidth.css",
|
||||
"css/static/modal-identity.css",
|
||||
"css/static/modal-newcomer.css",
|
||||
"css/static/modal-settings.css",
|
||||
"css/static/modal-poke.css",
|
||||
"css/static/modal-server.css",
|
||||
|
@ -483,7 +485,8 @@ loader.register_task(loader.Stage.TEMPLATES, {
|
|||
function: async () => {
|
||||
await loader.load_templates([
|
||||
"templates.html",
|
||||
"templates/music/manage.html"
|
||||
"templates/modal/musicmanage.html",
|
||||
"templates/modal/newcomer.html",
|
||||
]);
|
||||
},
|
||||
priority: 10
|
||||
|
|
Loading…
Reference in New Issue