A lots of updates :)
parent
bbbd8f6365
commit
89a29a8717
|
@ -2,6 +2,15 @@
|
||||||
* **03.11.18**
|
* **03.11.18**
|
||||||
- Reworked on the basic overlay sizes
|
- Reworked on the basic overlay sizes
|
||||||
- Added hostbanner to the UI
|
- Added hostbanner to the UI
|
||||||
|
- Implemented sounds
|
||||||
|
- Implemented poke notification
|
||||||
|
- Added local volume change to music bots
|
||||||
|
- Added move and channel kick to the music bot context menu options
|
||||||
|
- Reworked private chat format
|
||||||
|
- Added several server chat messages
|
||||||
|
- Fixed client double click chat opening
|
||||||
|
- Implemented client drag and drop
|
||||||
|
- Fixed channel select within sub channels
|
||||||
|
|
||||||
* **28.10.18**
|
* **28.10.18**
|
||||||
- Restructured the project
|
- Restructured the project
|
||||||
|
|
16
files.php
16
files.php
|
@ -35,6 +35,22 @@
|
||||||
"path" => "css/",
|
"path" => "css/",
|
||||||
"local-path" => "./shared/css/"
|
"local-path" => "./shared/css/"
|
||||||
],
|
],
|
||||||
|
[ /* shared sound files */
|
||||||
|
"type" => "wav",
|
||||||
|
"search-pattern" => "/.*\.wav$/",
|
||||||
|
"build-target" => "dev|rel",
|
||||||
|
|
||||||
|
"path" => "audio/",
|
||||||
|
"local-path" => "./shared/audio/"
|
||||||
|
],
|
||||||
|
[ /* shared data sound files */
|
||||||
|
"type" => "json",
|
||||||
|
"search-pattern" => "/.*\.json/",
|
||||||
|
"build-target" => "dev|rel",
|
||||||
|
|
||||||
|
"path" => "audio/",
|
||||||
|
"local-path" => "./shared/audio/"
|
||||||
|
],
|
||||||
[ /* shared image files */
|
[ /* shared image files */
|
||||||
"type" => "img",
|
"type" => "img",
|
||||||
"search-pattern" => "/.*\.(svg|png)/",
|
"search-pattern" => "/.*\.(svg|png)/",
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
[{"file": "sound.test.wav", "key": "sound.test"}, {"file": "sound.egg.wav", "key": "sound.egg"}, {"file": "away_activated.wav", "key": "away_activated"}, {"file": "away_deactivated.wav", "key": "away_deactivated"}, {"file": "connection.connected.wav", "key": "connection.connected"}, {"file": "connection.disconnected.wav", "key": "connection.disconnected"}, {"file": "connection.disconnected.timeout.wav", "key": "connection.disconnected.timeout"}, {"file": "connection.refused.wav", "key": "connection.refused"}, {"file": "connection.banned.wav", "key": "connection.banned"}, {"file": "server.edited.wav", "key": "server.edited"}, {"file": "server.edited.self.wav", "key": "server.edited.self"}, {"file": "server.kicked.wav", "key": "server.kicked"}, {"file": "channel.kicked.wav", "key": "channel.kicked"}, {"file": "channel.moved.wav", "key": "channel.moved"}, {"file": "channel.joined.wav", "key": "channel.joined"}, {"file": "channel.created.wav", "key": "channel.created"}, {"file": "channel.edited.wav", "key": "channel.edited"}, {"file": "channel.edited.self.wav", "key": "channel.edited.self"}, {"file": "channel.deleted.wav", "key": "channel.deleted"}, {"file": "user.moved.wav", "key": "user.moved"}, {"file": "user.moved.self.wav", "key": "user.moved.self"}, {"file": "user.poked.self.wav", "key": "user.poked.self"}, {"file": "user.banned.wav", "key": "user.banned"}, {"file": "user.joined.wav", "key": "user.joined"}, {"file": "user.joined.moved.wav", "key": "user.joined.moved"}, {"file": "user.joined.kicked.wav", "key": "user.joined.kicked"}, {"file": "user.joined.connect.wav", "key": "user.joined.connect"}, {"file": "user.left.wav", "key": "user.left"}, {"file": "user.left.kicked.channel.wav", "key": "user.left.kicked.channel"}, {"file": "user.left.kicked.server.wav", "key": "user.left.kicked.server"}, {"file": "user.left.moved.wav", "key": "user.left.moved"}, {"file": "user.left.disconnect.wav", "key": "user.left.disconnect"}, {"file": "user.left.banned.wav", "key": "user.left.banned"}, {"file": "error.insufficient_permissions.wav", "key": "error.insufficient_permissions"}]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,49 @@
|
||||||
|
#Sound test
|
||||||
|
sound.test;This is a test sound
|
||||||
|
sound.egg;WolverinDEV is the best and I love TeaSpeak!
|
||||||
|
|
||||||
|
#Away
|
||||||
|
away_activated;See you soon
|
||||||
|
away_deactivated;Welcome back
|
||||||
|
|
||||||
|
#Connection
|
||||||
|
connection.connected;Connected
|
||||||
|
connection.disconnected;Disconnected
|
||||||
|
connection.disconnected.timeout;Connection to server lost
|
||||||
|
connection.refused;Connect failed
|
||||||
|
connection.banned;You got banned from this server
|
||||||
|
|
||||||
|
#Server
|
||||||
|
server.edited;Server edited
|
||||||
|
server.edited.self;You edited the server
|
||||||
|
server.kicked;You got kicked from the server
|
||||||
|
|
||||||
|
#Channel activity
|
||||||
|
channel.kicked;You got kicked from the channel
|
||||||
|
channel.moved;Channel moved
|
||||||
|
channel.joined;Channel joined
|
||||||
|
channel.created;Channel created
|
||||||
|
channel.edited;Channel edited
|
||||||
|
channel.edited.self;You edited the channel
|
||||||
|
channel.deleted;Channel deleted
|
||||||
|
|
||||||
|
#User action
|
||||||
|
user.moved;User moved
|
||||||
|
user.moved.self;You have been moved
|
||||||
|
user.poked.self;Hey wakeup!
|
||||||
|
user.banned;User banned
|
||||||
|
|
||||||
|
user.joined;User joined your channel
|
||||||
|
user.joined.moved;User got moved to your channel
|
||||||
|
user.joined.kicked;User got kicked to your channel
|
||||||
|
user.joined.connect;User connected to your channel
|
||||||
|
|
||||||
|
user.left;User left your channel
|
||||||
|
user.left.kicked.channel;User in your channel got kicked from the channel
|
||||||
|
user.left.kicked.server;User in your channel got kicked from the server
|
||||||
|
user.left.moved;User was moved out of your channel
|
||||||
|
user.left.disconnect;User disconnected from your channel
|
||||||
|
user.left.banned;User in your channel was banned from the server
|
||||||
|
|
||||||
|
#Error
|
||||||
|
error.insufficient_permissions;insufficient permissions
|
|
|
@ -13,6 +13,7 @@
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
.button-update {
|
.button-update {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -80,13 +81,14 @@
|
||||||
.container-select-info {
|
.container-select-info {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
|
|
||||||
> div {
|
.select_server {
|
||||||
flex-grow: 1;
|
> div {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -277,6 +277,7 @@ footer .container {
|
||||||
}
|
}
|
||||||
|
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
|
max-width: 60%; /* tmp chat fix */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
@ -314,4 +315,25 @@ footer .container {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
border-radius: 0 0 2px 0;
|
border-radius: 0 0 2px 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mouse-move {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
border: 2px solid gray;
|
||||||
|
-webkit-border-radius: 2px;
|
||||||
|
-moz-border-radius: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
min-height: 500px;
|
||||||
|
min-width: 500px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
.container-poke {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.container-information {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-message {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.message {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-close {
|
||||||
|
margin-top: 5px;
|
||||||
|
width: 150px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<script class="jsrender-template" id="tmpl_poke_popup" type="text/html">
|
||||||
|
<div class="container-poke">
|
||||||
|
<div class="container-information">
|
||||||
|
<a>You have been poked by </a><node key="invoker"></node><a>:</a>
|
||||||
|
</div>
|
||||||
|
<div class="container-message">
|
||||||
|
<a class="message">{{>message}}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
*/
|
|
@ -122,6 +122,10 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 16px;
|
left: 16px;
|
||||||
|
|
||||||
|
&.move-selected {
|
||||||
|
border: 1px black solid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
"""
|
||||||
|
This should be executed as python 2.7 (because of pydub)
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import csv
|
||||||
|
import shutil
|
||||||
|
from pydub import AudioSegment
|
||||||
|
|
||||||
|
TARGET_DIRECTORY = "audio/speech"
|
||||||
|
SOURCE_FILE = "audio/speech_sentences.csv"
|
||||||
|
|
||||||
|
|
||||||
|
def tts(text, file):
|
||||||
|
voice_id = 4
|
||||||
|
language_id = 1
|
||||||
|
req = requests.post(
|
||||||
|
'https://kfiuqykx63.execute-api.us-east-1.amazonaws.com/Dev/tts?r={}&s={}&l=0&v=aca'.format(voice_id,
|
||||||
|
language_id),
|
||||||
|
stream=True,
|
||||||
|
headers={
|
||||||
|
'origin': 'https://www.naturalreaders.com',
|
||||||
|
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) '
|
||||||
|
'Chrome/69.0.3497.100 Safari/537.36 OPR/56.0.3051.52',
|
||||||
|
'content-type': 'application/x-www-form-urlencoded',
|
||||||
|
'referer': 'https://www.naturalreaders.com/online/',
|
||||||
|
'authority': 'kfiuqykx63.execute-api.us-east-1.amazonaws.com'
|
||||||
|
},
|
||||||
|
data=json.dumps({"t": text})
|
||||||
|
)
|
||||||
|
|
||||||
|
if req.status_code != 200:
|
||||||
|
raise ValueError("Invalid response code {}".format(req.status_code))
|
||||||
|
|
||||||
|
with open(file + ".mp3", "wb") as fstream:
|
||||||
|
for chunk in req.iter_content(chunk_size=128):
|
||||||
|
fstream.write(chunk)
|
||||||
|
fstream.close()
|
||||||
|
|
||||||
|
sound = AudioSegment.from_mp3(file + ".mp3")
|
||||||
|
sound.export(file, format="wav")
|
||||||
|
|
||||||
|
os.remove(file + ".mp3")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if os.path.exists(TARGET_DIRECTORY):
|
||||||
|
print("Deleting old speach directory (%s)!" % TARGET_DIRECTORY)
|
||||||
|
try:
|
||||||
|
shutil.rmtree(TARGET_DIRECTORY)
|
||||||
|
except e:
|
||||||
|
print("Cant delete old dir!")
|
||||||
|
os.makedirs(TARGET_DIRECTORY)
|
||||||
|
|
||||||
|
mapping = []
|
||||||
|
with open(SOURCE_FILE, 'r') as input:
|
||||||
|
reader = csv.reader(filter(lambda row: len(row) != 0 and row[0] != '#', input), delimiter=';', quotechar='#')
|
||||||
|
for row in reader:
|
||||||
|
if len(row) != 2:
|
||||||
|
continue
|
||||||
|
print("Generating speech for {}: {}".format(row[0], row[1]))
|
||||||
|
try:
|
||||||
|
file = "{}.wav".format(row[0])
|
||||||
|
tts(row[1], TARGET_DIRECTORY + "/" + file)
|
||||||
|
|
||||||
|
mapping.append({'key': row[0], 'file': file})
|
||||||
|
except e:
|
||||||
|
print(e)
|
||||||
|
print("Failed to generate {}", row[0])
|
||||||
|
|
||||||
|
with open("audio/speech/mapping.json", "w") as fstream:
|
||||||
|
fstream.write(json.dumps(mapping))
|
||||||
|
fstream.close()
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -53,6 +53,7 @@
|
||||||
<link rel="stylesheet" href="css/modal-banlist.css" type="text/css">
|
<link rel="stylesheet" href="css/modal-banlist.css" type="text/css">
|
||||||
<link rel="stylesheet" href="css/modal-bancreate.css" type="text/css">
|
<link rel="stylesheet" href="css/modal-bancreate.css" type="text/css">
|
||||||
<link rel="stylesheet" href="css/modal-settings.css" type="text/css">
|
<link rel="stylesheet" href="css/modal-settings.css" type="text/css">
|
||||||
|
<link rel="stylesheet" href="css/modal-poke.css" type="text/css">
|
||||||
<link rel="stylesheet" href="css/loader.css" type="text/css">
|
<link rel="stylesheet" href="css/loader.css" type="text/css">
|
||||||
<link rel="stylesheet" href="css/music/info_plate.css" type="text/css">
|
<link rel="stylesheet" href="css/music/info_plate.css" type="text/css">
|
||||||
<link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css">
|
<link rel="stylesheet" href="css/frame/SelectInfo.css" type="text/css">
|
||||||
|
@ -145,6 +146,11 @@
|
||||||
|
|
||||||
<div id="music-test"></div>
|
<div id="music-test"></div>
|
||||||
<div id="templates"></div>
|
<div id="templates"></div>
|
||||||
|
<div id="sounds"></div>
|
||||||
|
<div id="mouse-move">
|
||||||
|
<div class="container">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
|
@ -431,7 +431,7 @@
|
||||||
</x-entry>
|
</x-entry>
|
||||||
<x-entry>
|
<x-entry>
|
||||||
<x-tag>Transfers</x-tag>
|
<x-tag>Transfers</x-tag>
|
||||||
<x-content>TeaSpeak does not yet support these variables</x-content>
|
<x-content>This needs to be implemented :)</x-content>
|
||||||
</x-entry>
|
</x-entry>
|
||||||
<x-entry>
|
<x-entry>
|
||||||
<x-tag>Anti-Flood</x-tag>
|
<x-tag>Anti-Flood</x-tag>
|
||||||
|
@ -1322,9 +1322,7 @@
|
||||||
</script>
|
</script>
|
||||||
<script class="jsrender-template" id="tmpl_selected_hostbanner" type="text/html">
|
<script class="jsrender-template" id="tmpl_selected_hostbanner" type="text/html">
|
||||||
<div class="hostbanner">
|
<div class="hostbanner">
|
||||||
{{if property_virtualserver_hostbanner_url}}
|
<a href="{{:property_virtualserver_hostbanner_url}}" style="display: flex; flex-direction: row; justify-content: center;">
|
||||||
<a href="{{:property_virtualserver_hostbanner_url}}">
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<img src="
|
<img src="
|
||||||
{{:property_virtualserver_hostbanner_gfx_url}}
|
{{:property_virtualserver_hostbanner_gfx_url}}
|
||||||
|
@ -1348,9 +1346,7 @@
|
||||||
|
|
||||||
alt="Host banner"
|
alt="Host banner"
|
||||||
>
|
>
|
||||||
{{if property_virtualserver_hostbanner_url}}
|
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
<script class="jsrender-template" id="tmpl_selected_server" type="text/html">
|
<script class="jsrender-template" id="tmpl_selected_server" type="text/html">
|
||||||
|
@ -1463,5 +1459,16 @@
|
||||||
<node key="bbcode_channel_description"></node>
|
<node key="bbcode_channel_description"></node>
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
<script class="jsrender-template" id="tmpl_poke_popup" type="text/html">
|
||||||
|
<div class="container-poke">
|
||||||
|
<div class="container-information">
|
||||||
|
<a>You have been poked by </a><node key="invoker"></node><a>:</a>
|
||||||
|
</div>
|
||||||
|
<div class="container-message">
|
||||||
|
<a class="message">{{>message}}</a>
|
||||||
|
</div>
|
||||||
|
<button class="button-close">close</button>
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -65,7 +65,8 @@ namespace MessageHelper {
|
||||||
console.warn("Message to format contains invalid index (" + number + ")");
|
console.warn("Message to format contains invalid index (" + number + ")");
|
||||||
|
|
||||||
result.push(...this.formatElement(objects[number]));
|
result.push(...this.formatElement(objects[number]));
|
||||||
begin = found = found + 2 + offset;
|
found = found + 1 + offset;
|
||||||
|
begin = found + 1;
|
||||||
console.log("Offset: " + offset + " Number: " + number);
|
console.log("Offset: " + offset + " Number: " + number);
|
||||||
} while(found++);
|
} while(found++);
|
||||||
|
|
||||||
|
@ -237,6 +238,11 @@ class ChatEntry {
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this.handle.activeChat = this;
|
||||||
|
this.handle.htmlTag.find(".input_box").focus();
|
||||||
|
}
|
||||||
|
|
||||||
set name(newName : string) {
|
set name(newName : string) {
|
||||||
console.log("Change name!");
|
console.log("Change name!");
|
||||||
this._name = newName;
|
this._name = newName;
|
||||||
|
|
|
@ -98,7 +98,7 @@ class TSClient {
|
||||||
helpers.hashPassword(password.password).then(password => {
|
helpers.hashPassword(password.password).then(password => {
|
||||||
this.serverConnection.startConnection({host, port}, new HandshakeHandler(identity, name, password));
|
this.serverConnection.startConnection({host, port}, new HandshakeHandler(identity, name, password));
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
createErrorModal("Error while hasing password", "Faield to hash server password!").open();
|
createErrorModal("Error while hashing password", "Failed to hash server password!<br>" + error).open();
|
||||||
})
|
})
|
||||||
} else
|
} else
|
||||||
this.serverConnection.startConnection({host, port}, new HandshakeHandler(identity, name, password ? password.password : undefined));
|
this.serverConnection.startConnection({host, port}, new HandshakeHandler(identity, name, password ? password.password : undefined));
|
||||||
|
@ -182,6 +182,7 @@ class TSClient {
|
||||||
"Click <a href='" + this.certAcceptUrl() + "'>here</a> to accept the remote certificate"
|
"Click <a href='" + this.certAcceptUrl() + "'>here</a> to accept the remote certificate"
|
||||||
).open();
|
).open();
|
||||||
}
|
}
|
||||||
|
sound.play(Sound.CONNECTION_REFUSED);
|
||||||
break;
|
break;
|
||||||
case DisconnectReason.CONNECTION_CLOSED:
|
case DisconnectReason.CONNECTION_CLOSED:
|
||||||
console.error("Lost connection to remote server!");
|
console.error("Lost connection to remote server!");
|
||||||
|
@ -189,9 +190,11 @@ class TSClient {
|
||||||
"Connection closed",
|
"Connection closed",
|
||||||
"The connection was closed by remote host"
|
"The connection was closed by remote host"
|
||||||
).open();
|
).open();
|
||||||
|
sound.play(Sound.CONNECTION_DISCONNECTED);
|
||||||
break;
|
break;
|
||||||
case DisconnectReason.CONNECTION_PING_TIMEOUT:
|
case DisconnectReason.CONNECTION_PING_TIMEOUT:
|
||||||
console.error("Connection ping timeout");
|
console.error("Connection ping timeout");
|
||||||
|
sound.play(Sound.CONNECTION_DISCONNECTED_TIMEOUT);
|
||||||
createErrorModal(
|
createErrorModal(
|
||||||
"Connection lost",
|
"Connection lost",
|
||||||
"Lost connection to remote host (Ping timeout)<br>Even possible?"
|
"Lost connection to remote host (Ping timeout)<br>Even possible?"
|
||||||
|
@ -204,6 +207,7 @@ class TSClient {
|
||||||
"The server is closed.<br>" +
|
"The server is closed.<br>" +
|
||||||
"Reason: " + data.reasonmsg
|
"Reason: " + data.reasonmsg
|
||||||
).open();
|
).open();
|
||||||
|
sound.play(Sound.CONNECTION_DISCONNECTED);
|
||||||
break;
|
break;
|
||||||
case DisconnectReason.SERVER_REQUIRES_PASSWORD:
|
case DisconnectReason.SERVER_REQUIRES_PASSWORD:
|
||||||
chat.serverChat().appendError("Server requires password");
|
chat.serverChat().appendError("Server requires password");
|
||||||
|
@ -214,6 +218,19 @@ class TSClient {
|
||||||
this.serverConnection._handshakeHandler.name,
|
this.serverConnection._handshakeHandler.name,
|
||||||
{password: password as string, hashed: false});
|
{password: password as string, hashed: false});
|
||||||
}).open();
|
}).open();
|
||||||
|
break;
|
||||||
|
case DisconnectReason.CLIENT_KICKED:
|
||||||
|
chat.serverChat().appendError("You got kicked from the server by {0}{1}",
|
||||||
|
ClientEntry.chatTag(data["invokerid"], data["invokername"], data["invokeruid"]),
|
||||||
|
data["reasonmsg"] ? " (" + data["reasonmsg"] + ")" : "");
|
||||||
|
sound.play(Sound.SERVER_KICKED);
|
||||||
|
break;
|
||||||
|
case DisconnectReason.CLIENT_BANNED:
|
||||||
|
chat.serverChat().appendError("You got banned from the server by {0}{1}",
|
||||||
|
ClientEntry.chatTag(data["invokerid"], data["invokername"], data["invokeruid"]),
|
||||||
|
data["reasonmsg"] ? " (" + data["reasonmsg"] + ")" : "");
|
||||||
|
sound.play(Sound.CONNECTION_BANNED); //TODO findout if it was a disconnect or a connect refuse
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Got uncaught disconnect!");
|
console.error("Got uncaught disconnect!");
|
||||||
console.error("Type: " + type + " Data:");
|
console.error("Type: " + type + " Data:");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/// <reference path="ui/channel.ts" />
|
/// <reference path="ui/channel.ts" />
|
||||||
/// <reference path="client.ts" />
|
/// <reference path="client.ts" />
|
||||||
|
/// <reference path="sound/Sounds.ts" />
|
||||||
|
/// <reference path="ui/modal/ModalPoke.ts" />
|
||||||
|
|
||||||
class CommandResult {
|
class CommandResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
|
@ -227,6 +229,7 @@ class ServerConnection {
|
||||||
if(res.id == 2568) { //Permission error
|
if(res.id == 2568) { //Permission error
|
||||||
res.message = "Insufficient client permissions. Failed on permission " + this._client.permissions.resolveInfo(res.json["failed_permid"] as number).name;
|
res.message = "Insufficient client permissions. Failed on permission " + this._client.permissions.resolveInfo(res.json["failed_permid"] as number).name;
|
||||||
chat.serverChat().appendError("Insufficient client permissions. Failed on permission {}", this._client.permissions.resolveInfo(res.json["failed_permid"] as number).name);
|
chat.serverChat().appendError("Insufficient client permissions. Failed on permission {}", this._client.permissions.resolveInfo(res.json["failed_permid"] as number).name);
|
||||||
|
sound.play(Sound.ERROR_INSUFFICIENT_PERMISSIONS);
|
||||||
} else {
|
} else {
|
||||||
chat.serverChat().appendError(res.extra_message.length == 0 ? res.message : res.extra_message);
|
chat.serverChat().appendError(res.extra_message.length == 0 ? res.message : res.extra_message);
|
||||||
}
|
}
|
||||||
|
@ -473,6 +476,8 @@ class ConnectionCommandHandler {
|
||||||
this["notifyserveredited"] = this.handleNotifyServerEdited;
|
this["notifyserveredited"] = this.handleNotifyServerEdited;
|
||||||
this["notifyserverupdated"] = this.handleNotifyServerUpdated;
|
this["notifyserverupdated"] = this.handleNotifyServerUpdated;
|
||||||
|
|
||||||
|
this["notifyclientpoke"] = this.handleNotifyClientPoke;
|
||||||
|
|
||||||
this["notifymusicplayerinfo"] = this.handleNotifyMusicPlayerInfo;
|
this["notifymusicplayerinfo"] = this.handleNotifyMusicPlayerInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,6 +529,7 @@ class ConnectionCommandHandler {
|
||||||
|
|
||||||
chat.serverChat().name = this.connection._client.channelTree.server.properties["virtualserver_name"];
|
chat.serverChat().name = this.connection._client.channelTree.server.properties["virtualserver_name"];
|
||||||
chat.serverChat().appendMessage("Connected as {0}", true, this.connection._client.getClient().createChatTag(true));
|
chat.serverChat().appendMessage("Connected as {0}", true, this.connection._client.getClient().createChatTag(true));
|
||||||
|
sound.play(Sound.CONNECTION_CONNECTED);
|
||||||
globalClient.onConnected();
|
globalClient.onConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,14 +643,42 @@ class ConnectionCommandHandler {
|
||||||
chat.channelChat().name = channel.channelName();
|
chat.channelChat().name = channel.channelName();
|
||||||
tree.moveClient(client, channel);
|
tree.moveClient(client, channel);
|
||||||
}
|
}
|
||||||
|
const own_channel = this.connection._client.getClient().currentChannel();
|
||||||
|
|
||||||
if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
||||||
|
if(own_channel == channel)
|
||||||
|
if(old_channel)
|
||||||
|
sound.play(Sound.USER_ENTERED);
|
||||||
|
else
|
||||||
|
sound.play(Sound.USER_ENTERED_CONNECT);
|
||||||
if(old_channel) {
|
if(old_channel) {
|
||||||
chat.serverChat().appendMessage("{0} appeared from {1} to {2}", true, client.createChatTag(true), old_channel.createChatTag(true), channel.createChatTag(true));
|
chat.serverChat().appendMessage("{0} appeared from {1} to {2}", true, client.createChatTag(true), old_channel.createChatTag(true), channel.createChatTag(true));
|
||||||
} else {
|
} else {
|
||||||
chat.serverChat().appendMessage("{0} connected to channel {1}", true, client.createChatTag(true), channel.createChatTag(true));
|
chat.serverChat().appendMessage("{0} connected to channel {1}", true, client.createChatTag(true), channel.createChatTag(true));
|
||||||
}
|
}
|
||||||
|
} else if(json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
||||||
|
if(own_channel == channel)
|
||||||
|
sound.play(Sound.USER_ENTERED_MOVED);
|
||||||
|
|
||||||
|
chat.serverChat().appendMessage("{0} appeared from {1} to {2}, moved by {3}", true,
|
||||||
|
client.createChatTag(true),
|
||||||
|
old_channel ? old_channel.createChatTag(true) : undefined,
|
||||||
|
channel.createChatTag(true),
|
||||||
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||||
|
);
|
||||||
|
} else if(json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
||||||
|
if(own_channel == channel)
|
||||||
|
sound.play(Sound.USER_ENTERED_KICKED);
|
||||||
|
|
||||||
|
chat.serverChat().appendMessage("{0} appeared from {1} to {2}, kicked by {3}{4}", true,
|
||||||
|
client.createChatTag(true),
|
||||||
|
old_channel ? old_channel.createChatTag(true) : undefined,
|
||||||
|
channel.createChatTag(true),
|
||||||
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||||
|
json["reasonmsg"] > 0 ? " (" + json["msg"] + ")" : ""
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.warn("Unknown reasonid for " + json["reasonid"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let updates: {
|
let updates: {
|
||||||
|
@ -678,44 +712,69 @@ class ConnectionCommandHandler {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(client == this.connection._client.getClient()) {
|
if(client == this.connection._client.getClient()) {
|
||||||
if(json["reasonid"] == ViewReasonId.VREASON_BAN)
|
if(json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
||||||
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_BANNED, json);
|
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_BANNED, json);
|
||||||
else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK)
|
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
||||||
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_KICKED, json);
|
this.connection._client.handleDisconnect(DisconnectReason.CLIENT_KICKED, json);
|
||||||
else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_SHUTDOWN)
|
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_SHUTDOWN) {
|
||||||
this.connection._client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
this.connection._client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
||||||
else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_STOPPED)
|
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_STOPPED) {
|
||||||
this.connection._client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
this.connection._client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
||||||
else
|
} else
|
||||||
this.connection._client.handleDisconnect(DisconnectReason.UNKNOWN, json);
|
this.connection._client.handleDisconnect(DisconnectReason.UNKNOWN, json);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const own_channel = this.connection._client.getClient().currentChannel();
|
||||||
let channel_from = tree.findChannel(json["cfid"]);
|
let channel_from = tree.findChannel(json["cfid"]);
|
||||||
let channel_to = tree.findChannel(json["ctid"]);
|
let channel_to = tree.findChannel(json["ctid"]);
|
||||||
|
|
||||||
|
|
||||||
if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
||||||
chat.serverChat().appendMessage("{0} disappeared from {1} to {2}", true, client.createChatTag(true), channel_from.createChatTag(true), channel_to.createChatTag(true));
|
chat.serverChat().appendMessage("{0} disappeared from {1} to {2}", true, client.createChatTag(true), channel_from.createChatTag(true), channel_to.createChatTag(true));
|
||||||
|
|
||||||
|
if(channel_from == own_channel)
|
||||||
|
sound.play(Sound.USER_LEFT);
|
||||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_LEFT) {
|
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_LEFT) {
|
||||||
chat.serverChat().appendMessage("{0} left the server ({1})", true, client.createChatTag(true), json["reasonmsg"]);
|
chat.serverChat().appendMessage("{0} left the server{1}", true,
|
||||||
|
client.createChatTag(true),
|
||||||
|
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||||
|
);
|
||||||
|
|
||||||
|
if(channel_from == own_channel)
|
||||||
|
sound.play(Sound.USER_LEFT_DISCONNECT);
|
||||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
||||||
chat.serverChat().appendError("{0} was kicked from the server by {1}. ({2})",
|
chat.serverChat().appendError("{0} was kicked from the server by {1}.{2}",
|
||||||
client.createChatTag(true),
|
client.createChatTag(true),
|
||||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||||
json["reasonmsg"]
|
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||||
);
|
);
|
||||||
|
if(channel_from == own_channel)
|
||||||
|
sound.play(Sound.USER_LEFT_KICKED_SERVER);
|
||||||
|
} else if(json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
||||||
|
chat.serverChat().appendError("{0} was kicked from your channel by {1}.{2}",
|
||||||
|
client.createChatTag(true),
|
||||||
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||||
|
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||||
|
);
|
||||||
|
|
||||||
|
if(channel_from == own_channel)
|
||||||
|
sound.play(Sound.USER_LEFT_KICKED_CHANNEL);
|
||||||
} else if(json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
} else if(json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
||||||
//"Mulus" was banned for 1 second from the server by "WolverinDEV" (Sry brauchte kurz ein opfer :P <3 (Nohomo))
|
//"Mulus" was banned for 1 second from the server by "WolverinDEV" (Sry brauchte kurz ein opfer :P <3 (Nohomo))
|
||||||
let duration = "permanently";
|
let duration = "permanently";
|
||||||
if(json["bantime"])
|
if(json["bantime"])
|
||||||
duration = "for " + formatDate(Number.parseInt(json["bantime"]));
|
duration = "for " + formatDate(Number.parseInt(json["bantime"]));
|
||||||
chat.serverChat().appendError("{0} was banned {1} by {2}. ({3})",
|
|
||||||
|
chat.serverChat().appendError("{0} was banned {1} by {2}.{3}",
|
||||||
client.createChatTag(true),
|
client.createChatTag(true),
|
||||||
duration,
|
duration,
|
||||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||||
json["reasonmsg"]
|
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(channel_from == own_channel)
|
||||||
|
sound.play(Sound.USER_LEFT_BANNED);
|
||||||
} else {
|
} else {
|
||||||
console.error("Unknown client left reason!");
|
console.error("Unknown client left reason!");
|
||||||
}
|
}
|
||||||
|
@ -749,8 +808,10 @@ class ConnectionCommandHandler {
|
||||||
if(entry !== client) entry.getAudioController().stopAudio(true);
|
if(entry !== client) entry.getAudioController().stopAudio(true);
|
||||||
this.connection._client.controlBar.updateVoice(channel_to);
|
this.connection._client.controlBar.updateVoice(channel_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree.moveClient(client, channel_to);
|
tree.moveClient(client, channel_to);
|
||||||
|
|
||||||
|
const own_channel = this.connection._client.getClient().currentChannel();
|
||||||
if(json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
if(json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
||||||
chat.serverChat().appendMessage(self ? "You was moved by {3} from channel {1} to {2}" : "{0} was moved from channel {1} to {2} by {3}", true,
|
chat.serverChat().appendMessage(self ? "You was moved by {3} from channel {1} to {2}" : "{0} was moved from channel {1} to {2} by {3}", true,
|
||||||
client.createChatTag(true),
|
client.createChatTag(true),
|
||||||
|
@ -758,12 +819,39 @@ class ConnectionCommandHandler {
|
||||||
channel_to.createChatTag(true),
|
channel_to.createChatTag(true),
|
||||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"])
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"])
|
||||||
);
|
);
|
||||||
|
if(self)
|
||||||
|
sound.play(Sound.USER_MOVED_SELF);
|
||||||
|
else if(own_channel == channel_to)
|
||||||
|
sound.play(Sound.USER_ENTERED_MOVED);
|
||||||
|
else if(own_channel == channel_from)
|
||||||
|
sound.play(Sound.USER_LEFT_MOVED);
|
||||||
} else if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
} else if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
||||||
chat.serverChat().appendMessage(self ? "You switched from channel {1} to {2}" : "{0} switched from channel {1} to {2}", true,
|
chat.serverChat().appendMessage(self ? "You switched from channel {1} to {2}" : "{0} switched from channel {1} to {2}", true,
|
||||||
client.createChatTag(true),
|
client.createChatTag(true),
|
||||||
channel_from ? channel_from.createChatTag(true) : undefined,
|
channel_from ? channel_from.createChatTag(true) : undefined,
|
||||||
channel_to.createChatTag(true)
|
channel_to.createChatTag(true)
|
||||||
);
|
);
|
||||||
|
if(self) {} //If we do an action we wait for the error response
|
||||||
|
else if(own_channel == channel_to)
|
||||||
|
sound.play(Sound.USER_ENTERED);
|
||||||
|
else if(own_channel == channel_from)
|
||||||
|
sound.play(Sound.USER_LEFT);
|
||||||
|
} else if(json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
||||||
|
chat.serverChat().appendMessage(self ? "You got kicked out of the channel {1} to channel {2} by {3}{4}" : "{0} got kicked from channel {1} to {2} by {3}{4}", true,
|
||||||
|
client.createChatTag(true),
|
||||||
|
channel_from ? channel_from.createChatTag(true) : undefined,
|
||||||
|
channel_to.createChatTag(true),
|
||||||
|
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||||
|
(json["reasonmsg"] || "").length > 0 ? " (" + json["msg"] + ")" : ""
|
||||||
|
);
|
||||||
|
if(self) {
|
||||||
|
sound.play(Sound.CHANNEL_KICKED);
|
||||||
|
} else if(own_channel == channel_to)
|
||||||
|
sound.play(Sound.USER_ENTERED_KICKED);
|
||||||
|
else if(own_channel == channel_from)
|
||||||
|
sound.play(Sound.USER_LEFT_KICKED_CHANNEL);
|
||||||
|
} else {
|
||||||
|
console.warn("Unknown reason id " + json["reasonid"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,14 +924,20 @@ class ConnectionCommandHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(invoker == this.connection._client.getClient()) {
|
if(invoker == this.connection._client.getClient()) {
|
||||||
target.chat(true).appendMessage("<< " + json["msg"]);
|
sound.play(Sound.MESSAGE_SEND, { background_notification: true });
|
||||||
|
target.chat(true).appendMessage("{0}: {1}", true, this.connection._client.getClient().createChatTag(true), json["msg"]);
|
||||||
} else {
|
} else {
|
||||||
invoker.chat(true).appendMessage(">> " + json["msg"]);
|
sound.play(Sound.MESSAGE_RECEIVED, { background_notification: true });
|
||||||
|
invoker.chat(true).appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), json["msg"]);
|
||||||
}
|
}
|
||||||
} else if(mode == 2) {
|
} else if(mode == 2) {
|
||||||
chat.channelChat().appendMessage("{0} >> {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), json["msg"])
|
if(json["invokerid"] == this.connection._client.clientId)
|
||||||
|
sound.play(Sound.MESSAGE_SEND, { background_notification: true });
|
||||||
|
else
|
||||||
|
sound.play(Sound.MESSAGE_RECEIVED, { background_notification: true });
|
||||||
|
chat.channelChat().appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), json["msg"])
|
||||||
} else if(mode == 3) {
|
} else if(mode == 3) {
|
||||||
chat.serverChat().appendMessage("{0} >> {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), json["msg"]);
|
chat.serverChat().appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), json["msg"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -921,4 +1015,15 @@ class ConnectionCommandHandler {
|
||||||
|
|
||||||
bot.handlePlayerInfo(json);
|
bot.handlePlayerInfo(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNotifyClientPoke(json) {
|
||||||
|
json = json[0];
|
||||||
|
Modals.spawnPoke({
|
||||||
|
id: parseInt(json["invokerid"]),
|
||||||
|
name: json["invokername"],
|
||||||
|
unique_id: json["invokeruid"]
|
||||||
|
}, json["msg"]);
|
||||||
|
|
||||||
|
sound.play(Sound.USER_POKED_SELF);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -394,7 +394,7 @@ namespace sha {
|
||||||
export function sha1(message: string | ArrayBuffer) : PromiseLike<ArrayBuffer> {
|
export function sha1(message: string | ArrayBuffer) : PromiseLike<ArrayBuffer> {
|
||||||
let buffer = message instanceof ArrayBuffer ? message : encode_text(message as string);
|
let buffer = message instanceof ArrayBuffer ? message : encode_text(message as string);
|
||||||
|
|
||||||
if(/Edge/.test(navigator.userAgent))
|
if(!crypto || !crypto.subtle || !crypto.subtle.digest || /Edge/.test(navigator.userAgent))
|
||||||
return new Promise<ArrayBuffer>(resolve => {
|
return new Promise<ArrayBuffer>(resolve => {
|
||||||
resolve(_sha1.arrayBuffer(buffer as ArrayBuffer));
|
resolve(_sha1.arrayBuffer(buffer as ArrayBuffer));
|
||||||
});
|
});
|
||||||
|
|
|
@ -129,6 +129,8 @@ function loadDebug() {
|
||||||
//Load general API's
|
//Load general API's
|
||||||
"js/log.js",
|
"js/log.js",
|
||||||
|
|
||||||
|
"js/sound/Sounds.js",
|
||||||
|
|
||||||
"js/utils/modal.js",
|
"js/utils/modal.js",
|
||||||
"js/utils/tab.js",
|
"js/utils/tab.js",
|
||||||
"js/utils/helpers.js",
|
"js/utils/helpers.js",
|
||||||
|
@ -147,6 +149,7 @@ function loadDebug() {
|
||||||
"js/ui/modal/ModalBanCreate.js",
|
"js/ui/modal/ModalBanCreate.js",
|
||||||
"js/ui/modal/ModalBanList.js",
|
"js/ui/modal/ModalBanList.js",
|
||||||
"js/ui/modal/ModalYesNo.js",
|
"js/ui/modal/ModalYesNo.js",
|
||||||
|
"js/ui/modal/ModalPoke.js",
|
||||||
"js/ui/modal/ModalPermissionEdit.js",
|
"js/ui/modal/ModalPermissionEdit.js",
|
||||||
"js/ui/modal/ModalServerGroupDialog.js",
|
"js/ui/modal/ModalServerGroupDialog.js",
|
||||||
|
|
||||||
|
@ -154,6 +157,7 @@ function loadDebug() {
|
||||||
"js/ui/client.js",
|
"js/ui/client.js",
|
||||||
"js/ui/server.js",
|
"js/ui/server.js",
|
||||||
"js/ui/view.js",
|
"js/ui/view.js",
|
||||||
|
"js/ui/client_move.js",
|
||||||
|
|
||||||
"js/ui/frames/SelectedItemInfo.js",
|
"js/ui/frames/SelectedItemInfo.js",
|
||||||
"js/ui/frames/ControlBar.js",
|
"js/ui/frames/ControlBar.js",
|
||||||
|
|
|
@ -152,8 +152,14 @@ function main() {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
setup_close();
|
setup_close();
|
||||||
|
|
||||||
|
let _resize_timeout: NodeJS.Timer;
|
||||||
$(window).on('resize', () => {
|
$(window).on('resize', () => {
|
||||||
globalClient.channelTree.handle_resized();
|
if(_resize_timeout)
|
||||||
|
clearTimeout(_resize_timeout);
|
||||||
|
_resize_timeout = setTimeout(() => {
|
||||||
|
globalClient.channelTree.handle_resized();
|
||||||
|
}, 1000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ if(typeof ($) !== "undefined") {
|
||||||
result = $(result);
|
result = $(result);
|
||||||
}
|
}
|
||||||
result.find("node").each((index, element) => {
|
result.find("node").each((index, element) => {
|
||||||
$(element).replaceWith(values[$(element).attr("key")] || values[0][$(element).attr("key")]);
|
$(element).replaceWith(values[$(element).attr("key")] || (values[0] || [])[$(element).attr("key")]);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
enum Sound {
|
||||||
|
SOUND_TEST = "sound.test",
|
||||||
|
SOUND_EGG = "sound.egg",
|
||||||
|
|
||||||
|
AWAY_ACTIVATED = "away_activated",
|
||||||
|
AWAY_DEACTIVATED = "away_deactivated",
|
||||||
|
|
||||||
|
CONNECTION_CONNECTED = "connection.connected",
|
||||||
|
CONNECTION_DISCONNECTED = "connection.disconnected",
|
||||||
|
CONNECTION_BANNED = "connection.banned",
|
||||||
|
CONNECTION_DISCONNECTED_TIMEOUT = "connection.disconnected.timeout",
|
||||||
|
CONNECTION_REFUSED = "connection.refused",
|
||||||
|
|
||||||
|
SERVER_EDITED = "server.edited",
|
||||||
|
SERVER_EDITED_SELF = "server.edited.self",
|
||||||
|
SERVER_KICKED = "server.kicked",
|
||||||
|
|
||||||
|
CHANNEL_CREATED = "channel.created",
|
||||||
|
CHANNEL_MOVED = "channel.moved",
|
||||||
|
CHANNEL_EDITED = "channel.edited",
|
||||||
|
CHANNEL_EDITED_SELF = "channel.edited.self",
|
||||||
|
CHANNEL_DELETED = "channel.deleted",
|
||||||
|
|
||||||
|
CHANNEL_JOINED = "channel.joined",
|
||||||
|
CHANNEL_KICKED = "channel.kicked", //You got kicked from the channel
|
||||||
|
|
||||||
|
USER_MOVED = "user.moved", //User moved
|
||||||
|
USER_MOVED_SELF = "user.moved.self", //You were moved
|
||||||
|
USER_POKED_SELF = "user.poked.self", //Hey wakeup
|
||||||
|
USER_BANNED = "user.banned",
|
||||||
|
|
||||||
|
USER_ENTERED = "user.joined", //User joined your channel
|
||||||
|
USER_ENTERED_MOVED = "user.joined.moved", //User was moved to your channel
|
||||||
|
USER_ENTERED_KICKED = "user.joined.kicked", //User was kicked to your channel
|
||||||
|
USER_ENTERED_CONNECT = "user.joined.connect",
|
||||||
|
|
||||||
|
USER_LEFT = "user.left", //User left your channel
|
||||||
|
USER_LEFT_MOVED = "user.left.moved", //User was move out of your channel
|
||||||
|
USER_LEFT_KICKED_CHANNEL = "user.left.kicked.server", //User was kicked out of your channel
|
||||||
|
USER_LEFT_KICKED_SERVER = "user.left.kicked.channel", //User is your channel was kicked from the server
|
||||||
|
USER_LEFT_DISCONNECT = "user.left.disconnect",
|
||||||
|
USER_LEFT_BANNED = "user.left.banned",
|
||||||
|
|
||||||
|
ERROR_INSUFFICIENT_PERMISSIONS = "error.insufficient_permissions",
|
||||||
|
|
||||||
|
MESSAGE_SEND = "message.send",
|
||||||
|
MESSAGE_RECEIVED = "message.received"
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sound {
|
||||||
|
interface SpeechFile {
|
||||||
|
key: string;
|
||||||
|
filename: string;
|
||||||
|
|
||||||
|
not_supported?: boolean;
|
||||||
|
not_supported_timeout?: number;
|
||||||
|
cached?: AudioBuffer;
|
||||||
|
node?: HTMLAudioElement;
|
||||||
|
|
||||||
|
}
|
||||||
|
let warned = false
|
||||||
|
let speech_mapping: {[key: string]:SpeechFile} = {};
|
||||||
|
|
||||||
|
function register_sound(key: string, file: string) {
|
||||||
|
speech_mapping[key] = {key: key, filename: file} as SpeechFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initialize() : Promise<void> {
|
||||||
|
$.ajaxSetup({
|
||||||
|
beforeSend: function(jqXHR,settings){
|
||||||
|
if (settings.dataType === 'binary'){
|
||||||
|
console.log("Settins binary");
|
||||||
|
settings.xhr().responseType = 'arraybuffer';
|
||||||
|
settings.processData = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
register_sound("message.received", "effects/message_received.wav");
|
||||||
|
register_sound("message.send", "effects/message_send.wav");
|
||||||
|
|
||||||
|
return new Promise<void>(resolve => {
|
||||||
|
$.ajax({
|
||||||
|
url: "audio/speech/mapping.json",
|
||||||
|
success: response => {
|
||||||
|
for(const entry of response)
|
||||||
|
register_sound(entry.key, "speech/" + entry.file);
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
console.log("error!");
|
||||||
|
console.dir(...arguments);
|
||||||
|
},
|
||||||
|
timeout: 5000,
|
||||||
|
async: true,
|
||||||
|
type: 'GET'
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function str2ab(str) {
|
||||||
|
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
|
||||||
|
var bufView = new Uint16Array(buf);
|
||||||
|
for (var i = 0, strLen=str.length; i<strLen; i++) {
|
||||||
|
bufView[i] = str.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function play(sound: Sound, options?: {
|
||||||
|
background_notification?: boolean
|
||||||
|
}) {
|
||||||
|
console.log("playback sound " + sound);
|
||||||
|
const file: SpeechFile = speech_mapping[sound];
|
||||||
|
if(!file) {
|
||||||
|
console.warn("Missing sound " + sound);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(file.not_supported) {
|
||||||
|
if(!file.not_supported_timeout || Date.now() < file.not_supported_timeout) //Test if the not supported isnt may timeouted
|
||||||
|
return;
|
||||||
|
file.not_supported = false;
|
||||||
|
file.not_supported_timeout = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = "audio/" + file.filename;
|
||||||
|
const context = audio.player.context();
|
||||||
|
const volume = options && options.background_notification ? .5 : 1;
|
||||||
|
|
||||||
|
if(context.decodeAudioData) {
|
||||||
|
if(file.cached) {
|
||||||
|
console.log("Using cached buffer: %o", file.cached);
|
||||||
|
const player = context.createBufferSource();
|
||||||
|
player.buffer = file.cached;
|
||||||
|
player.start(0);
|
||||||
|
|
||||||
|
if(volume != 1 && context.createGain) {
|
||||||
|
const gain = context.createGain();
|
||||||
|
if(gain.gain.setValueAtTime)
|
||||||
|
gain.gain.setValueAtTime(volume, 0);
|
||||||
|
else
|
||||||
|
gain.gain.value = volume;
|
||||||
|
|
||||||
|
player.connect(gain);
|
||||||
|
gain.connect(audio.player.destination());
|
||||||
|
} else
|
||||||
|
player.connect(audio.player.destination());
|
||||||
|
} else {
|
||||||
|
const decode_data = buffer => {
|
||||||
|
console.log(buffer);
|
||||||
|
try {
|
||||||
|
console.log("Decoding data");
|
||||||
|
context.decodeAudioData(buffer, result => {
|
||||||
|
console.log("Got decoded data");
|
||||||
|
file.cached = result;
|
||||||
|
play(sound, options);
|
||||||
|
}, error => {
|
||||||
|
console.error("Failed to decode audio data for " + sound);
|
||||||
|
console.error(error);
|
||||||
|
file.not_supported = true;
|
||||||
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
file.not_supported = true;
|
||||||
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', path, true);
|
||||||
|
xhr.responseType = 'arraybuffer';
|
||||||
|
|
||||||
|
xhr.onload = function(e) {
|
||||||
|
if (this.status == 200) {
|
||||||
|
decode_data(this.response);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to load audio file. (Response code " + this.status + ")");
|
||||||
|
file.not_supported = true;
|
||||||
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = error => {
|
||||||
|
console.error("Failed to load audio file " + sound);
|
||||||
|
console.error(error);
|
||||||
|
file.not_supported = true;
|
||||||
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Replaying " + path);
|
||||||
|
if(file.node) {
|
||||||
|
file.node.currentTime = 0;
|
||||||
|
file.node.play();
|
||||||
|
} else {
|
||||||
|
if(!warned) {
|
||||||
|
warned = true;
|
||||||
|
console.warn("Your browser does not support decodeAudioData! Using a node to playback! This bypasses the audio output and volume regulation!");
|
||||||
|
}
|
||||||
|
const container = $("#sounds");
|
||||||
|
const node = $.spawn("audio").attr("src", path);
|
||||||
|
node.appendTo(container);
|
||||||
|
|
||||||
|
file.node = node[0];
|
||||||
|
file.node.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ class ChannelEntry {
|
||||||
|
|
||||||
private _channelAlign: string;
|
private _channelAlign: string;
|
||||||
private _formatedChannelName: string;
|
private _formatedChannelName: string;
|
||||||
|
private _family_index: number = 0;
|
||||||
|
|
||||||
//HTML DOM elements
|
//HTML DOM elements
|
||||||
private _tag_root: JQuery<HTMLElement>;
|
private _tag_root: JQuery<HTMLElement>;
|
||||||
|
@ -161,8 +162,10 @@ class ChannelEntry {
|
||||||
|
|
||||||
//Tag channel
|
//Tag channel
|
||||||
this._tag_channel = $.spawn("div");
|
this._tag_channel = $.spawn("div");
|
||||||
|
this._tag_channel.attr('channel-id', this.channelId);
|
||||||
this._tag_channel.addClass("channelLine");
|
this._tag_channel.addClass("channelLine");
|
||||||
this._tag_channel.addClass(this._channelAlign); //For left
|
this._tag_channel.addClass(this._channelAlign); //For left
|
||||||
|
this._tag_channel.css('z-index', this._family_index);
|
||||||
|
|
||||||
let channelType = $.spawn("div");
|
let channelType = $.spawn("div");
|
||||||
channelType.addClass("channel_only_normal channel_type icon client-channel_green_subscribed");
|
channelType.addClass("channel_only_normal channel_type icon client-channel_green_subscribed");
|
||||||
|
@ -373,7 +376,9 @@ class ChannelEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
perms[0]["cid"] = this.channelId;
|
perms[0]["cid"] = this.channelId;
|
||||||
this.channelTree.client.serverConnection.sendCommand("channeladdperm", perms, ["continueonerror"]);
|
this.channelTree.client.serverConnection.sendCommand("channeladdperm", perms, ["continueonerror"]).then(() => {
|
||||||
|
sound.play(Sound.CHANNEL_EDITED_SELF);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -383,7 +388,11 @@ class ChannelEntry {
|
||||||
icon: "client-channel_delete",
|
icon: "client-channel_delete",
|
||||||
name: "Delete channel",
|
name: "Delete channel",
|
||||||
invalidPermission: !flagDelete,
|
invalidPermission: !flagDelete,
|
||||||
callback: () => this.channelTree.client.serverConnection.sendCommand("channeldelete", {cid: this.channelId})
|
callback: () => {
|
||||||
|
this.channelTree.client.serverConnection.sendCommand("channeldelete", {cid: this.channelId}).then(() => {
|
||||||
|
sound.play(Sound.CHANNEL_DELETED);
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
MenuEntry.HR(),
|
MenuEntry.HR(),
|
||||||
{
|
{
|
||||||
|
@ -564,8 +573,10 @@ class ChannelEntry {
|
||||||
this.updateChannelTypeIcon();
|
this.updateChannelTypeIcon();
|
||||||
});
|
});
|
||||||
}).open();
|
}).open();
|
||||||
} else
|
} else if(this.channelTree.client.getClient().currentChannel() != this)
|
||||||
this.channelTree.client.getServerConnection().joinChannel(this, this._cachedPassword).catch(error => {
|
this.channelTree.client.getServerConnection().joinChannel(this, this._cachedPassword).then(() => {
|
||||||
|
sound.play(Sound.CHANNEL_JOINED);
|
||||||
|
}).catch(error => {
|
||||||
if(error instanceof CommandResult) {
|
if(error instanceof CommandResult) {
|
||||||
if(error.id == 781) { //Invalid password
|
if(error.id == 781) { //Invalid password
|
||||||
this._cachedPassword = undefined;
|
this._cachedPassword = undefined;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/// <reference path="channel.ts" />
|
/// <reference path="channel.ts" />
|
||||||
/// <reference path="modal/ModalChangeVolume.ts" />
|
/// <reference path="modal/ModalChangeVolume.ts" />
|
||||||
/// <reference path="modal/ModalServerGroupDialog.ts" />
|
/// <reference path="modal/ModalServerGroupDialog.ts" />
|
||||||
|
/// <reference path="client_move.ts" />
|
||||||
|
|
||||||
enum ClientType {
|
enum ClientType {
|
||||||
CLIENT_VOICE,
|
CLIENT_VOICE,
|
||||||
|
@ -80,7 +81,7 @@ class ClientEntry {
|
||||||
return this._properties;
|
return this._properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChannel() { return this._channel; }
|
currentChannel() : ChannelEntry { return this._channel; }
|
||||||
clientNickName(){ return this.properties.client_nickname; }
|
clientNickName(){ return this.properties.client_nickname; }
|
||||||
clientUid(){ return this.properties.client_unique_identifier; }
|
clientUid(){ return this.properties.client_unique_identifier; }
|
||||||
clientId(){ return this._clientId; }
|
clientId(){ return this._clientId; }
|
||||||
|
@ -95,6 +96,11 @@ class ClientEntry {
|
||||||
_this.channelTree.onSelect(_this);
|
_this.channelTree.onSelect(_this);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(this.clientId() != this.channelTree.client.clientId && !(this instanceof MusicClientEntry))
|
||||||
|
this.tag.dblclick(event => {
|
||||||
|
this.chat(true).focus();
|
||||||
|
});
|
||||||
|
|
||||||
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
||||||
this.tag.on("contextmenu", function (event) {
|
this.tag.on("contextmenu", function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -105,6 +111,25 @@ class ClientEntry {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.tag.mousedown(event => {
|
||||||
|
this.channelTree.client_mover.activate(this, target => {
|
||||||
|
if(!target) return;
|
||||||
|
if(target == this._channel) return;
|
||||||
|
|
||||||
|
const source = this._channel;
|
||||||
|
const self = this.channelTree.client.getClient();
|
||||||
|
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
||||||
|
clid: this.clientId(),
|
||||||
|
cid: target.getChannelId()
|
||||||
|
}).then(event => {
|
||||||
|
if(this.clientId() == this.channelTree.client.clientId)
|
||||||
|
sound.play(Sound.CHANNEL_JOINED);
|
||||||
|
else if(target !== source && target != self.currentChannel())
|
||||||
|
sound.play(Sound.USER_MOVED);
|
||||||
|
});
|
||||||
|
}, event);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected assignment_context() : ContextMenuEntry[] {
|
protected assignment_context() : ContextMenuEntry[] {
|
||||||
|
@ -312,7 +337,9 @@ class ClientEntry {
|
||||||
uid: this.properties.client_unique_identifier,
|
uid: this.properties.client_unique_identifier,
|
||||||
banreason: data.reason,
|
banreason: data.reason,
|
||||||
time: data.length
|
time: data.length
|
||||||
}, [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]);
|
}, [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]).then(() => {
|
||||||
|
sound.play(Sound.USER_BANNED);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -780,6 +807,48 @@ class MusicClientEntry extends ClientEntry {
|
||||||
},
|
},
|
||||||
MenuEntry.HR(),
|
MenuEntry.HR(),
|
||||||
...super.assignment_context(),
|
...super.assignment_context(),
|
||||||
|
MenuEntry.HR(),{
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
icon: "client-move_client_to_own_channel",
|
||||||
|
name: "Move client to your channel",
|
||||||
|
callback: () => {
|
||||||
|
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
||||||
|
clid: this.clientId(),
|
||||||
|
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
icon: "client-kick_channel",
|
||||||
|
name: "Kick client from channel",
|
||||||
|
callback: () => {
|
||||||
|
createInputModal("Kick client from channel", "Kick reason:<br>", text => true, result => {
|
||||||
|
if(result) {
|
||||||
|
console.log("Kicking client " + this.clientNickName() + " from channel with reason " + result);
|
||||||
|
this.channelTree.client.serverConnection.sendCommand("clientkick", {
|
||||||
|
clid: this.clientId(),
|
||||||
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||||
|
reasonmsg: result
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}, { width: 400, maxLength: 255 }).open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MenuEntry.HR(),
|
||||||
|
{
|
||||||
|
type: MenuEntryType.ENTRY,
|
||||||
|
icon: "client-volume",
|
||||||
|
name: "Change Volume",
|
||||||
|
callback: () => {
|
||||||
|
Modals.spawnChangeVolume(this.audioController.volume, volume => {
|
||||||
|
settings.changeServer("volume_client_" + this.clientUid(), volume);
|
||||||
|
this.audioController.volume = volume;
|
||||||
|
if(globalClient.selectInfo.currentSelected == this)
|
||||||
|
globalClient.selectInfo.update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
MenuEntry.HR(),
|
MenuEntry.HR(),
|
||||||
{
|
{
|
||||||
name: "Delete bot",
|
name: "Delete bot",
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/// <reference path="client.ts" />
|
||||||
|
|
||||||
|
class ClientMover {
|
||||||
|
static readonly listener_root = $(document);
|
||||||
|
static readonly move_element = $("#mouse-move");
|
||||||
|
readonly channel_tree: ChannelTree;
|
||||||
|
|
||||||
|
selected_client: ClientEntry;
|
||||||
|
|
||||||
|
hovered_channel: HTMLDivElement;
|
||||||
|
callback: (channel?: ChannelEntry) => any;
|
||||||
|
|
||||||
|
private _bound_finish;
|
||||||
|
private _bound_move;
|
||||||
|
private _active: boolean = false;
|
||||||
|
|
||||||
|
private origin_point: {x: number, y: number} = undefined;
|
||||||
|
|
||||||
|
constructor(tree: ChannelTree) {
|
||||||
|
this.channel_tree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
activate(client: ClientEntry, callback: (channel?: ChannelEntry) => any, event: any) {
|
||||||
|
this.finish_listener(undefined);
|
||||||
|
|
||||||
|
this.selected_client = client;
|
||||||
|
this.callback = callback;
|
||||||
|
console.log("Starting mouse move");
|
||||||
|
|
||||||
|
ClientMover.listener_root.on('mouseup', this._bound_finish = this.finish_listener.bind(this)).on('mousemove', this._bound_move = this.move_listener.bind(this));
|
||||||
|
|
||||||
|
{
|
||||||
|
const content = ClientMover.move_element.find(".container");
|
||||||
|
content.empty();
|
||||||
|
content.append($.spawn("a").text(client.clientNickName()));
|
||||||
|
}
|
||||||
|
this.move_listener(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private move_listener(event) {
|
||||||
|
//console.log("Mouse move: " + event.pageX + " - " + event.pageY);
|
||||||
|
if(!event.pageX || !event.pageY) return;
|
||||||
|
if(!this.origin_point)
|
||||||
|
this.origin_point = {x: event.pageX, y: event.pageY};
|
||||||
|
|
||||||
|
ClientMover.move_element.css({
|
||||||
|
"top": (event.pageY - 1) + "px",
|
||||||
|
"left": (event.pageX + 10) + "px"
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!this._active) {
|
||||||
|
const d_x = this.origin_point.x - event.pageX;
|
||||||
|
const d_y = this.origin_point.y - event.pageY;
|
||||||
|
this._active = Math.sqrt(d_x * d_x + d_y * d_y) > 5 * 5;
|
||||||
|
|
||||||
|
if(this._active)
|
||||||
|
ClientMover.move_element.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
const elements = document.elementsFromPoint(event.pageX, event.pageY);
|
||||||
|
while(elements.length > 0) {
|
||||||
|
if(elements[0].classList.contains("channelLine")) break;
|
||||||
|
elements.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.hovered_channel) {
|
||||||
|
this.hovered_channel.classList.remove("move-selected");
|
||||||
|
this.hovered_channel = undefined;
|
||||||
|
}
|
||||||
|
if(elements.length > 0) {
|
||||||
|
elements[0].classList.add("move-selected");
|
||||||
|
this.hovered_channel = elements[0] as HTMLDivElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private finish_listener(event) {
|
||||||
|
ClientMover.move_element.hide();
|
||||||
|
|
||||||
|
const channel_id = this.hovered_channel ? parseInt(this.hovered_channel.getAttribute("channel-id")) : 0;
|
||||||
|
ClientMover.listener_root.unbind('mouseleave', this._bound_finish);
|
||||||
|
ClientMover.listener_root.unbind('mouseup', this._bound_finish);
|
||||||
|
ClientMover.listener_root.unbind('mousemove', this._bound_move);
|
||||||
|
if(this.hovered_channel) {
|
||||||
|
this.hovered_channel.classList.remove("move-selected");
|
||||||
|
this.hovered_channel = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.origin_point = undefined;
|
||||||
|
if(!this._active) {
|
||||||
|
this.selected_client = undefined;
|
||||||
|
this.callback = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._active = false;
|
||||||
|
if(this.callback) {
|
||||||
|
if(!channel_id)
|
||||||
|
this.callback(undefined);
|
||||||
|
else {
|
||||||
|
this.callback(this.channel_tree.findChannel(channel_id));
|
||||||
|
}
|
||||||
|
this.callback = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivate() {
|
||||||
|
this.callback = undefined;
|
||||||
|
this.finish_listener(undefined);
|
||||||
|
}
|
||||||
|
}
|
|
@ -232,6 +232,7 @@ class ControlBar {
|
||||||
private onDisconnect() {
|
private onDisconnect() {
|
||||||
this.handle.handleDisconnect(DisconnectReason.REQUESTED); //TODO message?
|
this.handle.handleDisconnect(DisconnectReason.REQUESTED); //TODO message?
|
||||||
this.update_connection_state();
|
this.update_connection_state();
|
||||||
|
sound.play(Sound.CONNECTION_DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private on_token_use() {
|
private on_token_use() {
|
||||||
|
|
|
@ -530,10 +530,64 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const player = properties["music_player"];
|
||||||
|
const player_transformer = $.spawn("div").append(player);
|
||||||
|
player_transformer.css({
|
||||||
|
'display': 'block',
|
||||||
|
//'width': "100%",
|
||||||
|
'height': '100%'
|
||||||
|
});
|
||||||
|
properties["music_player"] = player_transformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rendered = $("#tmpl_selected_music").renderTag([properties]);
|
let rendered = $("#tmpl_selected_music").renderTag([properties]);
|
||||||
html_tag.append(rendered);
|
html_tag.append(rendered);
|
||||||
|
|
||||||
|
{
|
||||||
|
const player = properties["music_player"] as JQuery;
|
||||||
|
const player_width = 400; //player.width();
|
||||||
|
const player_height = 400; //player.height();
|
||||||
|
|
||||||
|
const parent = player.parent();
|
||||||
|
parent.css({
|
||||||
|
'flex-grow': 1,
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-direction': 'row',
|
||||||
|
'justify-content': 'space-around',
|
||||||
|
});
|
||||||
|
|
||||||
|
const padding = 14;
|
||||||
|
const scale_x = Math.min((parent.width() - padding) / player_width, 1.5);
|
||||||
|
const scale_y = Math.min((parent.height() - padding) / player_height, 1.5);
|
||||||
|
let scale = Math.min(scale_x, scale_y);
|
||||||
|
|
||||||
|
let translate_x = 50, translate_y = 50;
|
||||||
|
if(scale_x == scale_y && scale_x == scale) {
|
||||||
|
//Equal scale
|
||||||
|
} else if(scale_x == scale) {
|
||||||
|
//We scale on the x-Axis
|
||||||
|
//We have to adjust the y-Axis
|
||||||
|
} else {
|
||||||
|
//We scale on the y-Axis
|
||||||
|
//We have to adjust the x-Axis
|
||||||
|
|
||||||
|
}
|
||||||
|
//1 => 0 | 0
|
||||||
|
//1.5 => 0 | 25
|
||||||
|
//0.5 => 0 | -25
|
||||||
|
//const translate_x = scale_x != scale ? 0 : undefined || 50 - (50 * ((parent.width() - padding) / player_width));
|
||||||
|
//const translate_y = scale_y != scale || scale_y > 1 ? 0 : undefined || 50 - (50 * ((parent.height() - padding) / player_height));
|
||||||
|
const transform = ("translate(0%, " + (scale * 50 - 50) + "%) scale(" + scale.toPrecision(2) + ")");
|
||||||
|
|
||||||
|
console.log("Parents: %o | %o", parent.width(), parent.height());
|
||||||
|
console.log("Player: %o | %o", player_width, player_height);
|
||||||
|
console.log("Scale: %f => translate: %o | %o", scale, translate_x, translate_y);
|
||||||
|
player.css({
|
||||||
|
transform: transform
|
||||||
|
});
|
||||||
|
console.log("Transform: " + transform);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
available<V>(object: V): boolean {
|
available<V>(object: V): boolean {
|
||||||
|
|
|
@ -6,7 +6,10 @@ namespace Modals {
|
||||||
const modal = createModal({
|
const modal = createModal({
|
||||||
header: channel ? "Edit channel" : "Create channel",
|
header: channel ? "Edit channel" : "Create channel",
|
||||||
body: () => {
|
body: () => {
|
||||||
let template = $("#tmpl_channel_edit").renderTag(channel ? channel.properties : new ChannelProperties());
|
let template = $("#tmpl_channel_edit").renderTag(channel ? channel.properties : {
|
||||||
|
channel_flag_maxfamilyclients_unlimited: true,
|
||||||
|
channel_flag_maxclients_unlimited: true
|
||||||
|
} as ChannelProperties);
|
||||||
template = $.spawn("div").append(template);
|
template = $.spawn("div").append(template);
|
||||||
return template.tabify();
|
return template.tabify();
|
||||||
},
|
},
|
||||||
|
@ -62,6 +65,8 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
|
|
||||||
modal.open();
|
modal.open();
|
||||||
|
if(!channel)
|
||||||
|
modal.htmlTag.find(".channel_name").focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyGeneralListener(properties: ChannelProperties, tag: JQuery, button: JQuery, create: boolean) {
|
function applyGeneralListener(properties: ChannelProperties, tag: JQuery, button: JQuery, create: boolean) {
|
||||||
|
@ -71,7 +76,7 @@ namespace Modals {
|
||||||
else button.attr("disabled", "true");
|
else button.attr("disabled", "true");
|
||||||
};
|
};
|
||||||
|
|
||||||
tag.find(".channel_name").change(function (this: HTMLInputElement) {
|
tag.find(".channel_name").on('change keyup', function (this: HTMLInputElement) {
|
||||||
properties.channel_name = this.value;
|
properties.channel_name = this.value;
|
||||||
|
|
||||||
$(this).removeClass("input_error");
|
$(this).removeClass("input_error");
|
||||||
|
@ -101,8 +106,10 @@ namespace Modals {
|
||||||
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DESCRIPTION : PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1));
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DESCRIPTION : PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1));
|
||||||
|
|
||||||
if(create) {
|
if(create) {
|
||||||
tag.find(".channel_name").trigger("change");
|
setTimeout(() => {
|
||||||
tag.find(".channel_password").trigger('change');
|
tag.find(".channel_name").trigger("change");
|
||||||
|
tag.find(".channel_password").trigger('change');
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/// <reference path="../../utils/modal.ts" />
|
||||||
|
/// <reference path="../../proto.ts" />
|
||||||
|
/// <reference path="../../client.ts" />
|
||||||
|
|
||||||
|
namespace Modals {
|
||||||
|
export function spawnPoke(invoker: {
|
||||||
|
name: string,
|
||||||
|
id: number,
|
||||||
|
unique_id: string
|
||||||
|
}, message) {
|
||||||
|
let modal;
|
||||||
|
modal = createModal({
|
||||||
|
header: "You have been poked!",
|
||||||
|
body: () => {
|
||||||
|
let template = $("#tmpl_poke_popup").renderTag({
|
||||||
|
"invoker": ClientEntry.chatTag(invoker.id, invoker.name, invoker.unique_id, true),
|
||||||
|
"message": message
|
||||||
|
});
|
||||||
|
template = $.spawn("div").append(template);
|
||||||
|
|
||||||
|
template.find(".button-close").on('click', event => modal.close());
|
||||||
|
|
||||||
|
return template;
|
||||||
|
},
|
||||||
|
footer: undefined,
|
||||||
|
width: 750
|
||||||
|
});
|
||||||
|
modal.open();
|
||||||
|
}
|
||||||
|
}
|
|
@ -130,7 +130,9 @@ class ServerEntry {
|
||||||
log.info(LogCategory.SERVER, "Changing server properties %o", properties);
|
log.info(LogCategory.SERVER, "Changing server properties %o", properties);
|
||||||
console.log("Changed properties: %o", properties);
|
console.log("Changed properties: %o", properties);
|
||||||
if (properties)
|
if (properties)
|
||||||
this.channelTree.client.serverConnection.sendCommand("serveredit", properties);
|
this.channelTree.client.serverConnection.sendCommand("serveredit", properties).then(() => {
|
||||||
|
sound.play(Sound.SERVER_EDITED_SELF);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,9 +13,14 @@ class ChannelTree {
|
||||||
channels: ChannelEntry[];
|
channels: ChannelEntry[];
|
||||||
clients: ClientEntry[];
|
clients: ClientEntry[];
|
||||||
|
|
||||||
|
readonly client_mover: ClientMover;
|
||||||
|
|
||||||
constructor(client, htmlTree) {
|
constructor(client, htmlTree) {
|
||||||
|
document.addEventListener("touchstart", function(){}, true);
|
||||||
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.htmlTree = htmlTree;
|
this.htmlTree = htmlTree;
|
||||||
|
this.client_mover = new ClientMover(this);
|
||||||
this.reset();
|
this.reset();
|
||||||
|
|
||||||
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
if(!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
||||||
|
@ -122,6 +127,7 @@ class ChannelTree {
|
||||||
elm.after(entry);
|
elm.after(entry);
|
||||||
|
|
||||||
channel.adjustSize(true);
|
channel.adjustSize(true);
|
||||||
|
|
||||||
channel.initializeListener();
|
channel.initializeListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +170,12 @@ class ChannelTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(oldParent) oldParent.adjustSize();
|
if(oldParent) {
|
||||||
if(channel) channel.adjustSize();
|
oldParent.adjustSize();
|
||||||
|
}
|
||||||
|
if(channel) {
|
||||||
|
channel.adjustSize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteClient(client: ClientEntry) {
|
deleteClient(client: ClientEntry) {
|
||||||
|
@ -306,6 +316,7 @@ class ChannelTree {
|
||||||
return new Promise<ChannelEntry>(resolve => { resolve(channel); })
|
return new Promise<ChannelEntry>(resolve => { resolve(channel); })
|
||||||
}).then(channel => {
|
}).then(channel => {
|
||||||
chat.serverChat().appendMessage("Channel {} successfully created!", true, channel.createChatTag());
|
chat.serverChat().appendMessage("Channel {} successfully created!", true, channel.createChatTag());
|
||||||
|
sound.play(Sound.CHANNEL_CREATED);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ class AudioController {
|
||||||
static initializeAudioController() {
|
static initializeAudioController() {
|
||||||
if(!audio.player.initialize())
|
if(!audio.player.initialize())
|
||||||
console.warn("Failed to initialize audio controller!");
|
console.warn("Failed to initialize audio controller!");
|
||||||
|
sound.initialize().then(() => {
|
||||||
|
console.log("Sounds initialitzed");
|
||||||
|
});
|
||||||
//this._globalReplayScheduler = setInterval(() => { AudioController.invokeNextReplay(); }, 20); //Fix me
|
//this._globalReplayScheduler = setInterval(() => { AudioController.invokeNextReplay(); }, 20); //Fix me
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue