diff --git a/index.html b/index.html index 3d188ea..8e834d7 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@
+ diff --git a/infocontainer.js b/infocontainer.js index f72ffa4..748abc1 100644 --- a/infocontainer.js +++ b/infocontainer.js @@ -37,6 +37,33 @@ class Infocontainer return l; } + create_double_button(text, option) + { + var div = document.createElement("div"); + div.className = "option-button-container"; + var b1 = document.createElement("button"); + var b2 = document.createElement("button"); + + b1.style.width = "10%"; + + b1.className = "infobar-button"; + b2.className = "infobar-button"; + + b1.style.width = "80%"; + b2.style.width = "20%"; + + + b1.appendChild(document.createTextNode(text)); + b2.appendChild(document.createTextNode(option)); + + div.appendChild(b1); + div.appendChild(b2); + + this.container.appendChild(div); + + return [div, b1,b2]; + } + hide() { this.container.style.display = "none"; diff --git a/main.js b/main.js index 1165331..9978035 100644 --- a/main.js +++ b/main.js @@ -22,37 +22,42 @@ create_game_container = main_menu.create_infocontainer(); create_game_container.create_label("Start Local Game"); b_local_game = create_game_container.create_button("Local Game"); + + // register container: register_container = main_menu.create_infocontainer(); register_container.create_label("Login to play online"); i_register_username = register_container.create_input("username"); i_register_pw = register_container.create_input("password", true); b_register = register_container.create_button("register/login"); -register_container.create_label("(creates new account for a new username)"); +//register_container.create_label("(creates new account for a new username)"); // logout: -logout_container = sub_menu.create_infocontainer(); +logout_container = main_menu.create_infocontainer(); l_username = logout_container.create_label("logged in as: "); b_logout = logout_container.create_button("logout"); -// match control -match_control = sub_menu.create_infocontainer(); -b_end_game = match_control.create_button("Close Match"); - // fill subcontainer: match_slot_container = sub_menu.create_infocontainer(); match_slot_container.create_label("Running Matches
(click to open)"); + +// local match control: +match_control = sub_menu.create_infocontainer(); +b_end_game = match_control.create_button("Close Match"); + + // search match: -search_match_container = main_menu.create_infocontainer(); +search_match_container = sub_menu.create_infocontainer(); search_match_container.create_label("Create Online Match"); b_match_search = search_match_container.create_button("random match"); -search_match_container.create_label("

"); l_match_op = search_match_container.create_input("player name"); b_match_invite = search_match_container.create_button("invite player"); +search_match_container.create_label("Invite friends:") + //status: @@ -222,7 +227,7 @@ reconnect = function() { connection.close(); } - connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, login_callback, on_connection_error); + connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, search_match_container, login_callback, on_connection_error); connection.reconnect(session_id); } } @@ -239,7 +244,7 @@ login = function(){ { connection.close(); } - connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, login_callback, on_connection_error); + connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, search_match_container, login_callback, on_connection_error); connection.connect(i_register_username.value.toLowerCase(), i_register_pw.value); } @@ -266,6 +271,8 @@ invite_player = function() } } + + // initiate stuff and connect events: end_local_game(); diff --git a/online_match_manager.js b/online_match_manager.js index d80c93d..b65d9af 100644 --- a/online_match_manager.js +++ b/online_match_manager.js @@ -21,10 +21,27 @@ class OnlineMatchManager // create match button in match list: this.control_container = control_container; - this.matches_container = matches_container - this.match_button = matches_container.create_button("" + this.online_opponent.get_name()); + this.matches_container = matches_container; + + var tmp = matches_container.create_double_button("" + this.online_opponent.get_name(), "+") + + this.match_button = tmp[1]; + this.match_button_div = tmp[0]; + this.match_button_option = tmp[2]; + + if (this.game_server_connection.is_friend(this.online_opponent.get_name())) + { + this.match_button_option.disabled = true; + } + else + { + this.match_button_option.addEventListener("click", () => { + this.game_server_connection.send_friend_request(this.online_opponent.get_name()); + this.match_button_option.disabled = true; + }); + } + this.match_button.addEventListener("click", () => this.open_match()); - this.match_button.style.background = "rbg(0,255,0)"; if (this.online_opponent.get_name() == this.match_state.active_player) { @@ -57,7 +74,12 @@ class OnlineMatchManager this.game_server_connection.send_end_match(this.match_id); } - this.matches_container.container.removeChild(this.match_button); + if (this.match_button_div != null) + { + clearInner(this.match_button_div) + this.matches_container.container.removeChild(this.match_button_div); + this.match_button_div = null; + } this.status_label.innerHTML = "match is closed"; this.control_container.hide(); this.is_closed = true; @@ -66,9 +88,11 @@ class OnlineMatchManager remove_match() { - if (!this.is_closed) + if (this.match_button_div != null) { - this.matches_container.container.removeChild(this.match_button); + clearInner(this.match_button_div) + this.matches_container.container.removeChild(this.match_button_div); + this.match_button_div = null; } } diff --git a/style.css b/style.css index ee17b99..b45ba66 100644 --- a/style.css +++ b/style.css @@ -162,23 +162,41 @@ a:visited { text-align: center; background: none; white-space: normal; + overflow-y: scroll; +} + +@media (max-aspect-ratio: 1/1) { + + .info-container{ + width: calc(0.3 * var(--sidebar-width)); + } } .infobar-label { color: rgba(224, 217, 235, 0.8); + font-size: calc(2 * var(--border-radius)); + margin-left: 0; + margin-right: 0; + width: 100%; display: flex; flex-direction: column; - font-size: calc(2 * var(--border-radius)); - width: calc(var(--sidebar-width) - 4 * var(--border-radius)); + text-align: center; + } -@media (max-aspect-ratio: 1/1) { - .infobar-label - { - width: calc(var(--sidebar-width) * 0.25); - } +.option-button-container +{ + border-radius: 0%; + margin: 0%; + top: 0%; + display: flex; + flex-direction:row; + padding: none; } + + + .infobar-button { border-radius: var(--border-radius); margin: var(--border-radius); @@ -189,9 +207,12 @@ a:visited { color: rgb(255, 255, 255); font-size: calc(2.8 * var(--border-radius)); height: calc(4 * var(--border-radius)); - width: calc(var(--sidebar-width) - 4 * var(--border-radius)); - vertical-align: middle; + /* width: calc(var(--sidebar-width) - 4 * var(--border-radius)); */ + margin-left: 0; + margin-right: 0; + width: 100%; display: flex; + vertical-align: middle; flex-direction: column; text-align: center; } @@ -199,7 +220,6 @@ a:visited { @media (max-aspect-ratio: 1/1) { .infobar-button{ - width: calc(0.25 * var(--sidebar-width)); height: calc(0.18 * var(--sidebar-height)); } } @@ -214,16 +234,17 @@ a:visited { color: rgb(255, 255, 255); font-size: calc(2.8 * var(--border-radius)); height: calc(4 * var(--border-radius)); - width: calc(var(--sidebar-width) - 4 * var(--border-radius)); - vertical-align: middle; + margin-left: 0; + margin-right: 0; + width: 100%; display: flex; + vertical-align: middle; flex-direction: column; } @media (max-aspect-ratio: 1/1) { .infobar-button-green{ - width: calc(0.25 * var(--sidebar-width)); height: calc(0.18 * var(--sidebar-height)); } } @@ -238,16 +259,17 @@ a:visited { color: rgb(255, 255, 255); font-size: calc(2.8 * var(--border-radius)); height: calc(4 * var(--border-radius)); - width: calc(var(--sidebar-width) - 4 * var(--border-radius)); - vertical-align: middle; + margin-left: 0; + margin-right: 0; + width: 100%; display: flex; + vertical-align: middle; flex-direction: column; } @media (max-aspect-ratio: 1/1) { .infobar-button-red{ - width: calc(0.25 * var(--sidebar-width)); height: calc(0.18 * var(--sidebar-height)); } } @@ -262,16 +284,17 @@ a:visited { color: rgb(255, 255, 255); font-size: calc(2.8 * var(--border-radius)); height: calc(4 * var(--border-radius)); - width: calc(var(--sidebar-width) - 4 * var(--border-radius)); - vertical-align: middle; + margin-left: 0; + margin-right: 0; + width: 100%; display: flex; + vertical-align: middle; flex-direction: column; } @media (max-aspect-ratio: 1/1) { .infobar-button-active{ - width: calc(0.25 * var(--sidebar-width)); height: calc(0.18 * var(--sidebar-height)); } } @@ -300,9 +323,11 @@ a:visited { color: rgb(255, 255, 255); font-size: calc(3 * var(--border-radius)); height: calc(4 * var(--border-radius)); - width: calc(var(--sidebar-width) - 4 * var(--border-radius)); - vertical-align: middle; + margin-left: 0; + margin-right: 0; + width: 100%; display: flex; + vertical-align: middle; flex-direction: column; text-align: center; } @@ -315,6 +340,5 @@ a:visited { .infobar-input{ height: calc(0.18 * var(--sidebar-height)); - width: calc(0.25 * var(--sidebar-width)); } } \ No newline at end of file diff --git a/sw.js b/sw.js index bfc5a46..6b4aaf8 100644 --- a/sw.js +++ b/sw.js @@ -7,6 +7,7 @@ self.addEventListener('install', function (e) { caches.open('your-magic-cache').then(function (cache) { return cache.addAll([ '/website/ultimate_tictactoe/', + '/website/ultimate_tictactoe/tools.js', '/website/ultimate_tictactoe/index.html', '/website/ultimate_tictactoe/manifest.json', '/website/ultimate_tictactoe/icon.png', diff --git a/tools.js b/tools.js new file mode 100644 index 0000000..211df84 --- /dev/null +++ b/tools.js @@ -0,0 +1,13 @@ + +function clear(node) { + while (node.hasChildNodes()) { + clear(node.firstChild); + } + node.parentNode.removeChild(node); +} + +function clearInner(node) { + while (node.hasChildNodes()) { + clear(node.firstChild); + } +} \ No newline at end of file diff --git a/websocket_connection.js b/websocket_connection.js index 26f4dc7..2223fdb 100644 --- a/websocket_connection.js +++ b/websocket_connection.js @@ -1,6 +1,6 @@ class WebsocketConnection { - constructor(ip, port, grid, status_label, matches_container, control_container, login_callback_func, error_callback_func) + constructor(ip, port, grid, status_label, matches_container, control_container, search_container, login_callback_func, error_callback_func) { this.ip = ip; this.port = port; @@ -13,6 +13,7 @@ class WebsocketConnection this.status_label = status_label; this.matches_container = matches_container; this.control_container = control_container; + this.search_container = search_container; this.active_match = null; @@ -27,8 +28,12 @@ class WebsocketConnection this.closed_by_user = false; - matches_container.hide(); + this.friends = []; + + this.friend_name_divs = []; + + matches_container.hide(); } @@ -52,6 +57,11 @@ class WebsocketConnection return this.connected; } + is_friend(friend) + { + return this.friends.includes(friend); + } + on_open(username, pw) { this.connected = true; @@ -120,6 +130,18 @@ class WebsocketConnection case "match_request_response": this.on_match_request_response(msg.data); break; + + case "friend_request_response": + this.on_friend_request_response(msg.data); + break; + + case "unfriend_request_response": + this.on_unfriend_request_response(msg.data); + break; + + case "friends_update": + this.on_friends_update(msg.data); + break; } } @@ -239,6 +261,51 @@ class WebsocketConnection } } + on_friend_request_response(data) + { + this.status_label.innerHTML = data.msg; + } + + on_unfriend_request_response(data) + { + this.status_label.innerHTML = data.msg; + } + + on_friends_update(data) + { + this.friends = data.friends; + + // remove complete friend list: + var n = this.friend_name_divs.length; + + var i; + + for (i = 0; i < n; i++) + { + clearInner(this.friend_name_divs[i]); + this.search_container.container.removeChild(this.friend_name_divs[i]); + this.friend_name_divs[i] = null; + } + this.friend_name_divs = []; + // rebuild friend list: + n = this.friends.length; + + for (i = 0; i < n; i++) + { + var tmp = this.search_container.create_double_button("" + this.friends[i], "-"); + var name = this.friends[i]; + + tmp[1].addEventListener("click", () => { + this.send_match_request(name); + }); + + tmp[2].addEventListener("click", () => { + this.send_unfriend_request(name); + }); + + this.friend_name_divs.push(tmp[0]) + } + } connect(username, pw) { @@ -303,6 +370,28 @@ class WebsocketConnection this.socket.send(JSON.stringify(msg_object)); } + send_friend_request(friend_name) + { + var msg_object = { + type: "friend_request", + data: { + user: friend_name + } + }; + this.socket.send(JSON.stringify(msg_object)); + } + + send_unfriend_request(friend_name) + { + var msg_object = { + type: "unfriend_request", + data: { + user: friend_name + } + }; + this.socket.send(JSON.stringify(msg_object)); + } + login(username, pw) { this.player.set_name(username); @@ -320,6 +409,10 @@ class WebsocketConnection relogin(session_id) { + for (var key in this.openmatches) + { + this.openmatches[key].remove_match(); + } // register for game queue var msg_object = { type: "reconnect",