A lots of updates :)
This commit is contained in:
parent
bbbd8f6365
commit
89a29a8717
65 changed files with 920 additions and 42 deletions
|
@ -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)/",
|
||||||
|
|
BIN
shared/audio/effects/message_received.wav
Normal file
BIN
shared/audio/effects/message_received.wav
Normal file
Binary file not shown.
BIN
shared/audio/effects/message_send.wav
Normal file
BIN
shared/audio/effects/message_send.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/away_activated.wav
Normal file
BIN
shared/audio/speech/away_activated.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/away_deactivated.wav
Normal file
BIN
shared/audio/speech/away_deactivated.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.created.wav
Normal file
BIN
shared/audio/speech/channel.created.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.deleted.wav
Normal file
BIN
shared/audio/speech/channel.deleted.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.edited.self.wav
Normal file
BIN
shared/audio/speech/channel.edited.self.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.edited.wav
Normal file
BIN
shared/audio/speech/channel.edited.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.joined.wav
Normal file
BIN
shared/audio/speech/channel.joined.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.kicked.wav
Normal file
BIN
shared/audio/speech/channel.kicked.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/channel.moved.wav
Normal file
BIN
shared/audio/speech/channel.moved.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/connection.banned.wav
Normal file
BIN
shared/audio/speech/connection.banned.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/connection.connected.wav
Normal file
BIN
shared/audio/speech/connection.connected.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/connection.disconnected.timeout.wav
Normal file
BIN
shared/audio/speech/connection.disconnected.timeout.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/connection.disconnected.wav
Normal file
BIN
shared/audio/speech/connection.disconnected.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/connection.refused.wav
Normal file
BIN
shared/audio/speech/connection.refused.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/error.insufficient_permissions.wav
Normal file
BIN
shared/audio/speech/error.insufficient_permissions.wav
Normal file
Binary file not shown.
1
shared/audio/speech/mapping.json
Normal file
1
shared/audio/speech/mapping.json
Normal file
|
@ -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"}]
|
BIN
shared/audio/speech/server.edited.self.wav
Normal file
BIN
shared/audio/speech/server.edited.self.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/server.edited.wav
Normal file
BIN
shared/audio/speech/server.edited.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/server.kicked.wav
Normal file
BIN
shared/audio/speech/server.kicked.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/sound.egg.wav
Normal file
BIN
shared/audio/speech/sound.egg.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/sound.test.wav
Normal file
BIN
shared/audio/speech/sound.test.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.banned.wav
Normal file
BIN
shared/audio/speech/user.banned.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.joined.connect.wav
Normal file
BIN
shared/audio/speech/user.joined.connect.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.joined.kicked.wav
Normal file
BIN
shared/audio/speech/user.joined.kicked.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.joined.moved.wav
Normal file
BIN
shared/audio/speech/user.joined.moved.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.joined.wav
Normal file
BIN
shared/audio/speech/user.joined.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.left.banned.wav
Normal file
BIN
shared/audio/speech/user.left.banned.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.left.disconnect.wav
Normal file
BIN
shared/audio/speech/user.left.disconnect.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.left.kicked.channel.wav
Normal file
BIN
shared/audio/speech/user.left.kicked.channel.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.left.kicked.server.wav
Normal file
BIN
shared/audio/speech/user.left.kicked.server.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.left.moved.wav
Normal file
BIN
shared/audio/speech/user.left.moved.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.left.wav
Normal file
BIN
shared/audio/speech/user.left.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.moved.self.wav
Normal file
BIN
shared/audio/speech/user.moved.self.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.moved.wav
Normal file
BIN
shared/audio/speech/user.moved.wav
Normal file
Binary file not shown.
BIN
shared/audio/speech/user.poked.self.wav
Normal file
BIN
shared/audio/speech/user.poked.self.wav
Normal file
Binary file not shown.
49
shared/audio/speech_sentences.csv
Normal file
49
shared/audio/speech_sentences.csv
Normal file
|
@ -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;
|
||||||
|
|
||||||
|
.select_server {
|
||||||
> div {
|
> div {
|
||||||
flex-grow: 1;
|
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;
|
||||||
|
@ -315,3 +316,24 @@ footer .container {
|
||||||
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;
|
||||||
|
}
|
35
shared/css/modal-poke.scss
Normal file
35
shared/css/modal-poke.scss
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
79
shared/generate_voice.py
Normal file
79
shared/generate_voice.py
Normal file
|
@ -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', () => {
|
||||||
|
if(_resize_timeout)
|
||||||
|
clearTimeout(_resize_timeout);
|
||||||
|
_resize_timeout = setTimeout(() => {
|
||||||
globalClient.channelTree.handle_resized();
|
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;
|
||||||
}
|
}
|
||||||
|
|
212
shared/js/sound/Sounds.ts
Normal file
212
shared/js/sound/Sounds.ts
Normal file
|
@ -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",
|
||||||
|
|
110
shared/js/ui/client_move.ts
Normal file
110
shared/js/ui/client_move.ts
Normal file
|
@ -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) {
|
||||||
|
setTimeout(() => {
|
||||||
tag.find(".channel_name").trigger("change");
|
tag.find(".channel_name").trigger("change");
|
||||||
tag.find(".channel_password").trigger('change');
|
tag.find(".channel_password").trigger('change');
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
shared/js/ui/modal/ModalPoke.ts
Normal file
30
shared/js/ui/modal/ModalPoke.ts
Normal file
|
@ -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…
Add table
Reference in a new issue