diff --git a/css/window.css b/css/window.css index e02a062..d4a4540 100644 --- a/css/window.css +++ b/css/window.css @@ -429,7 +429,7 @@ #tab_bar .project_tab { background-color: var(--color-back); cursor: pointer; - width: 200px; + width: 240px; min-width: 120px; height: 100%; padding: 2px 6px; @@ -511,6 +511,19 @@ #new_tab_button:hover { color: var(--color-light); } + #tab_bar .project_tab > label.project_tab_session_badge { + display: flex; + flex-grow: 0; + width: auto; + color: var(--color-accent); + } + #tab_bar .project_tab > label.project_tab_session_badge i { + margin-right: 2px; + margin-left: -4px; + } + #tab_bar.invisible { + visibility: hidden; + } /*Start Screen*/ diff --git a/index.html b/index.html index 178d6f2..4669dd3 100644 --- a/index.html +++ b/index.html @@ -143,34 +143,6 @@ - - dialog.edit_session.title - - - edit_session.username - - - - edit_session.token - - action.paste - - - edit_session.about - - - edit_session.status: edit_session.connected - - - - edit_session.join - edit_session.create - edit_session.quit - dialog.cancel - - clear - - dialog.toolbar_edit.title @@ -592,38 +564,40 @@ web.download_app - - - {{ project.name || project.geometry_name || project.format.name }} - - {{ project.saved ? 'clear' : 'fiber_manual_record' }} - - - - add - - - - + + + group{{ project.EditSession.client_count }} + {{ project.name || project.geometry_name || project.format.name }} + + {{ project.saved ? 'clear' : 'fiber_manual_record' }} + + + + add + + + + + diff --git a/js/desktop.js b/js/desktop.js index 9d72144..e3d48e1 100644 --- a/js/desktop.js +++ b/js/desktop.js @@ -433,7 +433,7 @@ function closeBlockbenchWindow() { Blockbench.addFlag('allow_closing'); Blockbench.dispatchEvent('before_closing') localStorage.removeItem('backup_model') - EditSession.quit() + if (Project.EditSession) Project.EditSession.quit() return currentwindow.close(); }; diff --git a/js/edit_sessions.js b/js/edit_sessions.js index 4dcf683..4fe6fd2 100644 --- a/js/edit_sessions.js +++ b/js/edit_sessions.js @@ -1,60 +1,70 @@ -const EditSession = { - active: false, - hosting: false, - BBKey: '1h3sq3hoj6vfkh', - ip: 'blckbn.ch', - clients: {}, - placeholder_names: ['R2D2', 'Tin Man', 'C3PO', 'WALL-E', 'EVE', 'BB-8', 'B1 Battle Droid', 'ASIMO', 'Atlas'], - start() { - if (EditSession.active) return; +class EditSession { + constructor() { + this.active = false; + this.hosting = false; + this.clients = {}; + this.client_count = 1; - var peer = EditSession.peer = new Peer({ + this.data_queue = []; + + this.chat_history = []; + + this.Project = Project || null; + Interface.Panels.chat.inside_vue.chat_history = this.chat_history; + if (Project) Project.EditSession = this; + } + updateClientCount() { + this.client_count = Math.clamp(Object.keys(this.clients).length, 1, 999); + } + start(username) { + if (this.active) return; + + var peer = this.peer = new Peer({ key: 'edit_session', - host: EditSession.ip, + host: EditSession.defaults.ip, port: 9000, path: '/sessions', secure: true }); - EditSession.username = $('#edit_session_username').val() || EditSession.placeholder_names.random(); - settings.username.value = EditSession.username; + this.username = username || EditSession.defaults.placeholder_names.random(); + settings.username.value = this.username; peer.on('open', (token) => { - EditSession.hosting = true; - Prop.session = true; - EditSession.setState(true); + this.hosting = true; + this.setState(true); - EditSession.self = new EditSession.Client({ - id: EditSession.peer.id, - name: EditSession.username, + this.self = new EditSession.Client(this, { + id: this.peer.id, + name: this.username, hosting: true }) $('#edit_session_token').val(token) - EditSession.token = token; + this.token = token; Clipbench.setText(token) Blockbench.dispatchEvent('create_session', {peer, token}) }) peer.on('connection', (conn) => { - conn.on('open', function() { + conn.on('open', () => { - var client = new EditSession.Client({ + var client = new EditSession.Client(this, { id: conn.peer, conn: conn, name: conn.metadata.username, hosting: false }) - Chat.processMessage({text: tl('edit_session.joined', [client.name]), color: 'green'}) + this.processChatMessage({text: tl('edit_session.joined', [client.name]), color: 'green'}) Blockbench.showQuickMessage(tl('edit_session.joined', [client.name])) //New Login client.send({ type: 'chat_message', - data: {text: tl('edit_session.welcome', [EditSession.username]), color: 'yellow'} + data: {text: tl('edit_session.welcome', [this.username]), color: 'yellow'} }) var model = Codecs.project.compile({uuids: true, bitmaps: true, backup: true, history: true}) client.send({ type: 'init_model', - fromHost: EditSession.hosting, - sender: EditSession.peer.id, + fromHost: this.hosting, + sender: this.peer.id, data: model }) }) @@ -62,25 +72,23 @@ const EditSession = { peer.on('error', error => { console.error('Error in edit session:', error) }) - }, - join() { - if (EditSession.active) return; + } + join(username, token) { + if (this.active) return; - var token = $('#edit_session_token').val() - - EditSession.hosting = false; - EditSession.peer = new Peer({ + this.hosting = false; + this.peer = new Peer({ key: 'edit_session', - host: EditSession.ip, + host: EditSession.defaults.ip, port: 9000, path: '/sessions', secure: true }); - EditSession.peer.on('open', function() { + this.peer.on('open', () => { - EditSession.username = $('#edit_session_username').val() || EditSession.placeholder_names.random(); - settings.username.value = EditSession.username; - if (!token || !EditSession._matchToken(token)) { + this.username = username || EditSession.defaults.placeholder_names.random(); + settings.username.value = this.username; + if (!token || !EditSession.matchToken(token)) { Blockbench.showMessageBox({ translateKey: 'invalid_session', icon: 'cloud_off', @@ -89,8 +97,8 @@ const EditSession = { }) return; } - EditSession.token = token; - var conn = EditSession.peer.connect(token, {metadata: {username: EditSession.username}}); + this.token = token; + var conn = this.peer.connect(token, {metadata: {username: this.username}}); conn.on('error', (err) => { console.error('peer join error', err) @@ -98,117 +106,91 @@ const EditSession = { translateKey: 'invalid_session', icon: 'cloud_off', }) - EditSession.quit() + this.quit() }) conn.on('open', () => { hideDialog() - EditSession.host = conn; - EditSession.setState(true); - EditSession.initConnection(conn) + this.host = conn; + this.setState(true); + this.initConnection(conn) Blockbench.dispatchEvent('join_session', {conn}) }) }) - EditSession.peer.on('error', error => { + this.peer.on('error', error => { console.error('Error in edit session:', error) }) - }, + } quit() { - if (!EditSession.active) return; + if (!this.active) return; Blockbench.dispatchEvent('quit_session', {}) - if (EditSession.hosting) { - EditSession.sendAll('command', 'quit_session') + if (this.hosting) { + this.sendAll('command', 'quit_session') } else { - EditSession.host.close() + this.host.close() } - setTimeout(function() { - EditSession.setState(false) - Chat.history.purge() - EditSession.peer.destroy() - Prop.session = false; - Prop.connections = 0; + ModelProject.all.forEach(project => { + if (project.EditSession == this) { + delete project.EditSession; + } + }) + setTimeout(() => { + this.setState(false) + this.chat_history.purge() + this.peer.destroy() Blockbench.showQuickMessage('edit_session.quit_session', 1500) }, 400) - }, + } setState(active) { - EditSession.active = active; - $('#edit_session_username, #edit_session_token').attr('readonly', active) - if (active) { - $('.edit_session_inactive').hide() - $('.edit_session_active').show() - $('#edit_session_status').text(EditSession.hosting ? tl('edit_session.hosting') : tl('edit_session.connected')) - $('#edit_session_copy_button .tooltip').text(tl('action.copy')) - } else { - EditSession.hosting = false; - $('.edit_session_active').hide() - $('.edit_session_inactive').show() - $('#edit_session_copy_button .tooltip').text(tl('action.paste')) - $('#edit_session_token').val('') + this.active = active; + if (!active) { + this.hosting = false; } updateInterface() - }, - dialog() { - showDialog('edit_sessions'); - if (!EditSession.active) { - var username = settings.username.value; - if (isApp) { - var token = clipboard.readText() - if (EditSession._matchToken(token) && !$('#edit_session_token').val()) { - $('#edit_session_token').val(token) - } - if (!username) { - username = process.env.USERNAME - } - } - if (!username) username = EditSession.placeholder_names.random() - if (username) { - $('#edit_session_username').val(username) - } - } - }, + } copyToken() { var input = $('#edit_session_token') - if (EditSession.active) { + if (this.active) { input.focus() document.execCommand('selectAll') document.execCommand('copy') } else { if (isApp) { var token = clipboard.readText() - if (EditSession._matchToken(token)) { + if (EditSession.matchToken(token)) { $('#edit_session_token').val(token) } } else { navigator.clipboard.readText().then((token) => { - if (EditSession._matchToken(token)) { + if (EditSession.matchToken(token)) { $('#edit_session_token').val(token) } }) } } - }, + } initNewModel(force) { - if (EditSession.active && EditSession.hosting) { + if (this.active && this.hosting) { var model = Codecs.project.compile({uuids: true, bitmaps: true, backup: true, flag: force ? 'force' : null}) if (force) { model.flag = 'force' } - EditSession.sendAll('init_model', model) + this.sendAll('init_model', model) } - }, + } initConnection(conn) { - conn.on('data', EditSession.receiveData) - }, + conn.on('data', (...args) => this.receiveData(...args)) + } sendAll(type, data) { var tag = {type, data} Blockbench.dispatchEvent('send_session_data', tag) - for (var key in EditSession.peer.connections) { - var conns = EditSession.peer.connections[key]; + for (var key in this.peer.connections) { + var conns = this.peer.connections[key]; conns.forEach(conn => { conn.send({ type: tag.type, - fromHost: EditSession.hosting, - sender: EditSession.peer.id, + fromHost: this.hosting, + sender: this.peer.id, data: tag.data }); }) @@ -216,7 +198,7 @@ const EditSession = { if (Blockbench.hasFlag('log_session')) { console.log('Sent Data:', type, data) } - }, + } sendEdit(entry) { var new_entry = { before: omitKeys(entry.before, ['aspects']), @@ -224,17 +206,17 @@ const EditSession = { save_history: entry.save_history, action: entry.action } - EditSession.sendAll('edit', JSON.stringify(new_entry)) - }, + this.sendAll('edit', JSON.stringify(new_entry)) + } receiveData(tag) { if (Blockbench.hasFlag('log_session')) { console.log('Received Data:', tag) } - if (EditSession.hosting && !tag.hostOnly && Object.keys(EditSession.peer.connections).length > 1) { + if (this.hosting && !tag.hostOnly && Object.keys(this.peer.connections).length > 1) { //Redistribute - for (var id in EditSession.peer.connections) { + for (var id in this.peer.connections) { if (id !== tag.sender) { - EditSession.peer.connections[id][0].send(tag); + this.peer.connections[id][0].send(tag); } } } @@ -247,21 +229,41 @@ const EditSession = { return; } } - Blockbench.dispatchEvent('receive_session_data', tag) + Blockbench.dispatchEvent('receive_session_data', tag); + if (tag.type === 'chat_input' && this.hosting) { + this.processChatMessage(tag.data); + + } else if (tag.type === 'chat_message') { + this.addChatMessage(tag.data); + + } else { + if (Project.EditSession == this || (!this.Project)) { + this.processData(tag); + } else { + this.data_queue.push(tag); + } + } + + + } + processData(tag) { + let {data} = tag; if (tag.type === 'edit') { - Undo.remoteEdit(data) + Undo.remoteEdit(data); } else if (tag.type === 'init_model') { newProject(data.meta.type||'free', data.flag === 'force'); Codecs.project.parse(data); + this.Project = Project; + this.Project.EditSession = this; } else if (tag.type === 'command') { switch (data) { case 'undo': Undo.undo(true); break; case 'redo': Undo.redo(true); break; - case 'quit_session': EditSession.quit(); break; + case 'quit_session': this.quit(); break; } } else if (tag.type === 'change_project_meta') { @@ -269,33 +271,87 @@ const EditSession = { Project[key] = data[key]; } - } else if (tag.type === 'chat_input' && EditSession.hosting) { - Chat.processMessage(tag.data) - - } else if (tag.type === 'chat_message') { - Chat.addMessage(tag.data) } - }, - updateClientCount() { - Prop.connections = Object.keys(EditSession.clients).length-1 - }, - _matchToken(token) { - return !!(token.length === 16 && token.match(/[a-z0-9]{16}/)) + } + catchUp() { + while (this.data_queue.length) { + let tag = this.data_queue.shift(); + try { + this.processData(tag); + } catch (err) { + console.error(err); + } + } + } + + sendChat(text) { + if (typeof text !== 'string') { + text = $('input#chat_input').val() + $('input#chat_input').val('') + } + if (!text) return; + this.processChatMessage({ + author: this.username, + text: text, + sender: this.peer.id + }) + } + addChatMessage(message) { + if (!(message instanceof EditSession.ChatMessage)) { + message = new EditSession.ChatMessage(this, message) + } + if (!message.text) return; + + this.chat_history.push(message) + Vue.nextTick(() => { + $('#chat_history').scrollTop(10000) + }) + if (!document.hasFocus() && !message.self) { + Blockbench.notification(message.author ? message.author+':' : 'Chat', message.text) + } + return message; + } + processChatMessage(data) { + if (!this.hosting) { + this.host.send({ + type: 'chat_input', + data, + sender: this.peer.id + }) + return; + } + //Host Only + Blockbench.dispatchEvent('process_chat_message', data) + + this.sendAll('chat_message', data) + this.addChatMessage(data) } } + +EditSession.matchToken = function(token) { + return !!(token.length === 16 && token.match(/[a-z0-9]{16}/)) +} + +EditSession.defaults = { + max_chat_length: 512, + ip: 'blckbn.ch', + placeholder_names: ['R2D2', 'Tin Man', 'C3PO', 'WALL-E', 'EVE', 'BB-8', 'B1 Battle Droid', 'ASIMO', 'Atlas'], +} + EditSession.Client = class { - constructor(data) { + constructor(session, data) { var scope = this; this.id = data.id; this.hosting = data.hosting; this.conn = data.conn; this.name = data.name; + this.session = session; - EditSession.clients[this.id] = this; - EditSession.updateClientCount() + this.session.clients[this.id] = this; + this.session.updateClientCount() if (this.conn) { - EditSession.initConnection(this.conn) + this.session.initConnection(this.conn) this.conn.on('close', () => { scope.disconnect() }) @@ -311,70 +367,25 @@ EditSession.Client = class { this.conn.send(tag) } disconnect(e) { - if (!EditSession.clients[this.id]) return; + if (!this.session.clients[this.id]) return; Blockbench.dispatchEvent('user_leaves_session', this) - delete EditSession.peer.connections[this.conn.peer]; - delete EditSession.clients[this.id]; - EditSession.updateClientCount(); + delete this.session.peer.connections[this.conn.peer]; + delete this.session.clients[this.id]; + this.session.updateClientCount(); - Chat.processMessage({text: tl('edit_session.left', [this.name]), color: 'red'}) + this.processChatMessage({text: tl('edit_session.left', [this.name]), color: 'red'}) Blockbench.showQuickMessage(tl('edit_session.left', [this.name])) } -} - -const Chat = { - history: [], - maxlength: 512, - send(text) { - if (typeof text !== 'string') { - text = $('input#chat_input').val() - $('input#chat_input').val('') - } - if (!text) return; - Chat.processMessage({ - author: EditSession.username, - text: text, - sender: EditSession.peer.id - }) - }, - addMessage(message) { - if (!(message instanceof Chat.Message)) { - message = new Chat.Message(message) - } - if (!message.text) return; - - Chat.history.push(message) - Vue.nextTick(() => { - $('#chat_history').scrollTop(10000) - }) - if (!document.hasFocus() && !message.self) { - Blockbench.notification(message.author ? message.author+':' : 'Chat', message.text) - } - return message; - }, - processMessage(data) { - if (!EditSession.hosting) { - EditSession.host.send({ - type: 'chat_input', - data, - sender: EditSession.peer.id - }) - return; - } - //Host Only - Blockbench.dispatchEvent('process_chat_message', data) - - EditSession.sendAll('chat_message', data) - Chat.addMessage(data) - } }; -Chat.Message = class { - constructor(data) { + +EditSession.ChatMessage = class { + constructor(session, data) { + this.session = session; this.author = data.author||''; this.author = this.author.substr(0, 64) this.sender = data.sender - this.self = data.sender == EditSession.peer.id; - this.text = data.text.substr(0, Chat.maxlength)||''; + this.self = data.sender == this.session.peer.id; + this.text = data.text.substr(0, EditSession.defaults.max_chat_length)||''; this.html = this.text.replace(//g, '>'); this.html = this.html.replace(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g, (text, i) => { @@ -402,8 +413,8 @@ Chat.Message = class { } showAuthor() { if (!this.author) return false; - var this_i = Chat.history.indexOf(this); - var prev = Chat.history[this_i-1]; + var this_i = this.session.chat_history.indexOf(this); + var prev = this.session.chat_history[this_i-1]; return (!prev) || (prev.author !== this.author); } } @@ -412,33 +423,100 @@ BARS.defineActions(function() { new Action('edit_session', { icon: 'people', category: 'blockbench', - click: EditSession.dialog + click: () => { + + let session = Project && Project.EditSession; + var username, token; + + if (session) { + username = session.username; + token = session.token; + } else { + username = settings.username.value; + if (!username && isApp) { + username = process.env.USERNAME + } + token = EditSession.token; + if (!token && isApp) { + let clipboard_token = clipboard.readText() + if (EditSession.matchToken(clipboard_token) && !$('#edit_session_token').val()) { + token = clipboard_token; + } + } + } + + new Dialog({ + id: 'edit_session', + title: 'dialog.edit_session.title', + form: { + username: {type: 'text', label: 'edit_session.username', value: username}, + token: {type: 'text', label: 'edit_session.token', value: token, readonly: !!session}, + about: {type: 'info', text: 'edit_session.about', condition: !session}, + status: {type: 'info', text: `**${tl('edit_session.status')}**: ${(session && session.hosting) ? tl('edit_session.hosting') : tl('edit_session.connected')}`, condition: !!session}, + }, + buttons: session + ? ['edit_session.quit', 'dialog.close'] + : ['edit_session.join', 'edit_session.create', 'dialog.close'], + onButton(button) { + let result = this.getFormResult(); + if (session && button == 0) { + session.quit(); + + } else if (!session && button != 2) { + if (button == 0) { + // Join + session = new EditSession(); + session.join(result.username, result.token); + } else { + // Create + if (!Project) { + Formats.free.new(); + } + session = new EditSession(); + session.start(result.username); + } + } + } + }).show(); + } }) }) +EditSession.initNewModel = function() {} Interface.definePanels(function() { Interface.Panels.chat = new Panel({ id: 'chat', icon: 'chat', - condition: {method() {return EditSession.active}}, + condition: {method() {return Project.EditSession && Project.EditSession.active}}, toolbars: {}, onResize: t => { }, component: { - data() {return Chat}, + data() {return { + chat_history: [], + chat_input: '' + }}, + methods: { + sendMessage() { + if (Project && Project.EditSession) { + Project.EditSession.sendChat(this.chat_input); + this.chat_input = ''; + } + } + }, template: ` - + {{ msg.author }}: {{ msg.timestamp }} - - send + + send ` diff --git a/js/interface/interface.js b/js/interface/interface.js index 3486aba..9769921 100644 --- a/js/interface/interface.js +++ b/js/interface/interface.js @@ -15,7 +15,7 @@ class ResizeLine { this.node = jq.get(0) jq.draggable({ axis: this.horizontal ? 'y' : 'x', - containment: '#page_wrapper', + containment: '#work_screen', revert: true, revertDuration: 0, start: function(e, u) { @@ -108,7 +108,7 @@ const Interface = { }, position: function(line) { line.setPosition({ - top: document.getElementById('page_wrapper').offsetTop, + top: document.getElementById('work_screen').offsetTop, bottom: 0, left: Interface.data.left_bar_width+2 }) @@ -139,7 +139,7 @@ const Interface = { }, position: function(line) { line.setPosition({ - top: document.getElementById('page_wrapper').offsetTop+30, + top: document.getElementById('work_screen').offsetTop+30, bottom: 0, right: Interface.data.right_bar_width-2 }) @@ -238,7 +238,7 @@ function setupInterface() { for (var key in Interface.Resizers) { var resizer = Interface.Resizers[key] - $('#page_wrapper').append(resizer.node) + $('#work_screen').append(resizer.node) } //$(document).contextmenu() @@ -826,9 +826,6 @@ onVueSetup(function() { {{ Prop.fps }} FPS - - {{ Prop.connections }} Clients - {{Prop.show_right_bar ? 'chevron_right' : 'chevron_left'}} diff --git a/js/interface/keyboard.js b/js/interface/keyboard.js index bf10955..2e41a96 100644 --- a/js/interface/keyboard.js +++ b/js/interface/keyboard.js @@ -567,9 +567,9 @@ addEventListeners(document, 'keydown mousedown', function(e) { } return; } - if ($('input#chat_input:focus').length && EditSession.active) { + if ($('input#chat_input:focus').length && Project.EditSession) { if (Keybinds.extra.confirm.keybind.isTriggered(e)) { - Chat.send(); + Interface.Panels.chat.inside_vue.sendMessage(); return; } } diff --git a/js/interface/menu.js b/js/interface/menu.js index d52fbb6..c65e8d9 100644 --- a/js/interface/menu.js +++ b/js/interface/menu.js @@ -478,7 +478,6 @@ const MenuBar = { 'project_window', '_', {name: 'menu.file.new', id: 'new', icon: 'insert_drive_file', - condition: () => (!EditSession.active || EditSession.hosting), children: function() { var arr = []; for (var key in Formats) { @@ -499,7 +498,7 @@ const MenuBar = { } }, {name: 'menu.file.recent', id: 'recent', icon: 'history', - condition: function() {return isApp && recent_projects.length && (!EditSession.active || EditSession.hosting)}, + condition: function() {return isApp && recent_projects.length}, children: function() { var arr = [] let redact = settings.streamer_mode.value; diff --git a/js/io/codec.js b/js/io/codec.js index c9d3af3..71c7ccd 100644 --- a/js/io/codec.js +++ b/js/io/codec.js @@ -211,6 +211,4 @@ function loadModelFile(file) { } } } - - EditSession.initNewModel() } diff --git a/js/io/format.js b/js/io/format.js index 84fc4c4..639a9f4 100644 --- a/js/io/format.js +++ b/js/io/format.js @@ -195,7 +195,6 @@ class ModelFormat { Canvas.updateAllBones() Canvas.updateAllFaces() updateSelection() - EditSession.initNewModel() } delete() { delete Formats[this.id]; diff --git a/js/io/formats/bedrock.js b/js/io/formats/bedrock.js index b2d92af..ebdf240 100644 --- a/js/io/formats/bedrock.js +++ b/js/io/formats/bedrock.js @@ -511,7 +511,6 @@ function calculateVisibleBox() { Project.BedrockEntityManager.initEntity() } updateSelection() - EditSession.initNewModel() } // Compile diff --git a/js/io/formats/bedrock_old.js b/js/io/formats/bedrock_old.js index 60c3220..5ba2208 100644 --- a/js/io/formats/bedrock_old.js +++ b/js/io/formats/bedrock_old.js @@ -122,7 +122,6 @@ function parseGeometry(data) { Project.BedrockEntityManager.initEntity() } updateSelection() - EditSession.initNewModel() } diff --git a/js/io/formats/skin.js b/js/io/formats/skin.js index 3bdd2ad..0c6d2fd 100644 --- a/js/io/formats/skin.js +++ b/js/io/formats/skin.js @@ -149,7 +149,6 @@ const codec = new Codec('skin_model', { Canvas.updateVisibility() setProjectTitle() updateSelection() - EditSession.initNewModel() }, }) codec.export = null; diff --git a/js/io/io.js b/js/io/io.js index f9bea3c..d8f5258 100644 --- a/js/io/io.js +++ b/js/io/io.js @@ -447,7 +447,7 @@ BARS.defineActions(function() { icon: 'assessment', category: 'file', keybind: new Keybind({key: 'o', ctrl: true}), - condition: () => (!EditSession.active || EditSession.hosting), + condition: () => (!Project.EditSession || Project.EditSession.hosting), click: function () { var startpath; if (isApp && recent_projects && recent_projects.length) { diff --git a/js/io/project.js b/js/io/project.js index f89249b..d51969a 100644 --- a/js/io/project.js +++ b/js/io/project.js @@ -19,6 +19,7 @@ class ModelProject { if (isApp) this.BedrockEntityManager = new BedrockEntityManager(); this.format = options.format instanceof ModelFormat ? options.format : Formats.free; this.mode = 'edit'; + this.EditSession = null; // Data this.elements = []; @@ -185,6 +186,11 @@ class ModelProject { BarItems.lock_motion_trail.value = !!Project.motion_trail_lock; BarItems.lock_motion_trail.updateEnabledState(); + if (this.EditSession) { + Interface.Panels.chat.inside_vue.chat_history = this.EditSession.chat_history; + this.EditSession.catchUp(); + } + Blockbench.dispatchEvent('select_project', {project: this}); setProjectTitle(this.name); @@ -589,8 +595,8 @@ BARS.defineActions(function() { Blockbench.dispatchEvent('update_project_settings', formResult); BARS.updateConditions() - if (EditSession.active) { - EditSession.sendAll('change_project_meta', JSON.stringify(Project)); + if (Project.EditSession) { + Project.EditSession.sendAll('change_project_meta', JSON.stringify(Project)); } dialog.hide() @@ -599,24 +605,19 @@ BARS.defineActions(function() { dialog.show() } }) - /* new Action('close_project', { icon: 'cancel_presentation', category: 'file', - condition: () => (!EditSession.active || EditSession.hosting) && Format, + keybind: new Keybind({key: 'w', ctrl: true}), + condition: () => Project, click: function () { - if (showSaveDialog()) { - resetProject() - Modes.options.start.select() - Modes.vue.$forceUpdate() - Blockbench.dispatchEvent('close_project'); - } + Project.close(); } - })*/ + }) new Action('convert_project', { icon: 'fas.fa-file-import', category: 'file', - condition: () => (!EditSession.active || EditSession.hosting), + condition: () => Project && (!Project.EditSession || Project.EditSession.hosting), click: function () { var options = {}; diff --git a/js/outliner/cube.js b/js/outliner/cube.js index 7fd273b..2f610f8 100644 --- a/js/outliner/cube.js +++ b/js/outliner/cube.js @@ -844,8 +844,6 @@ class Cube extends OutlinerElement { Outliner.buttons.locked, Outliner.buttons.visibility, ]; - Cube.selected = []; - Cube.all = []; new Property(Cube, 'string', 'name', {default: 'cube'}) new Property(Cube, 'boolean', 'rescale') diff --git a/js/outliner/locator.js b/js/outliner/locator.js index 85c783a..8f753c0 100644 --- a/js/outliner/locator.js +++ b/js/outliner/locator.js @@ -108,8 +108,6 @@ class Locator extends OutlinerElement { 'rename', 'delete' ]) - Locator.selected = []; - Locator.all = []; new Property(Locator, 'string', 'name', {default: 'locator'}) new Property(Locator, 'vector', 'from') diff --git a/js/outliner/null_object.js b/js/outliner/null_object.js index a7a8929..ea75eca 100644 --- a/js/outliner/null_object.js +++ b/js/outliner/null_object.js @@ -95,8 +95,6 @@ class NullObject extends OutlinerElement { 'rename', 'delete' ]) - NullObject.selected = []; - NullObject.all = []; new Property(NullObject, 'string', 'name', {default: 'null_object'}) new Property(NullObject, 'vector', 'from') diff --git a/js/outliner/outliner.js b/js/outliner/outliner.js index 64a4408..88ba993 100644 --- a/js/outliner/outliner.js +++ b/js/outliner/outliner.js @@ -703,10 +703,10 @@ function dropOutlinerObjects(item, target, event, order) { function renameOutliner(element) { stopRenameOutliner() - if (Group.selected && !element && !EditSession.active) { + if (Group.selected && !element && !Project.EditSession) { Group.selected.rename() - } else if (selected.length === 1 && !EditSession.active) { + } else if (selected.length === 1 && !Project.EditSession) { selected[0].rename() } else { diff --git a/js/texturing/textures.js b/js/texturing/textures.js index c9c6c94..4376b3e 100644 --- a/js/texturing/textures.js +++ b/js/texturing/textures.js @@ -367,13 +367,13 @@ class Texture { this.startWatcher() Painter.current = {} - if (EditSession.active) { + if (Project.EditSession) { this.load(() => { var before = {textures: {}} before.textures[scope.uuid] = true; this.edit() var post = new Undo.save({textures: [this]}) - EditSession.sendEdit({ + Project.EditSession.sendEdit({ before: before, post: post, action: 'loaded_texture', diff --git a/js/undo.js b/js/undo.js index 1d99676..a70332b 100644 --- a/js/undo.js +++ b/js/undo.js @@ -53,8 +53,8 @@ class UndoSystem { Project.saved = false; } Blockbench.dispatchEvent('finished_edit', {aspects}) - if (EditSession.active) { - EditSession.sendEdit(entry) + if (Project.EditSession && Project.EditSession.active) { + Project.EditSession.sendEdit(entry) } return entry; } @@ -84,8 +84,8 @@ class UndoSystem { var entry = this.history[this.index] this.loadSave(entry.before, entry.post) - if (EditSession.active && remote !== true) { - EditSession.sendAll('command', 'undo') + if (Project.EditSession && remote !== true) { + Project.EditSession.sendAll('command', 'undo') } Blockbench.dispatchEvent('undo', {entry}) } @@ -99,8 +99,8 @@ class UndoSystem { var entry = this.history[this.index] this.index++; this.loadSave(entry.post, entry.before) - if (EditSession.active && remote !== true) { - EditSession.sendAll('command', 'redo') + if (Project.EditSession && remote !== true) { + Project.EditSession.sendAll('command', 'redo') } Blockbench.dispatchEvent('redo', {entry}) } diff --git a/js/web.js b/js/web.js index 7e0309d..44a6e98 100644 --- a/js/web.js +++ b/js/web.js @@ -22,8 +22,8 @@ try { function loadInfoFromURL() { if (location.hash.substr(1, 8) == 'session=') { - EditSession.dialog() - $('#edit_session_token').val(location.hash.substr(9)) + EditSession.token = location.hash.substr(9); + BarItems.edit_session.click(); } if (location.hash.substr(1, 2) == 'm=') { @@ -39,7 +39,7 @@ window.onbeforeunload = function() { return 'Unsaved Changes'; } else { Blockbench.dispatchEvent('before_closing') - EditSession.quit() + if (Project.EditSession) Project.EditSession.quit() } } function showSaveDialog(close) { diff --git a/lang/en.json b/lang/en.json index b1a9157..0ef1460 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1379,7 +1379,7 @@ "dialog.edit_session.title": "Edit Session", "edit_session.username": "Username", "edit_session.token": "Token", - "edit_session.about": "Edit Sessions can be used to collaborate on models across the internet. Create a session and copy the token and send it to friends, who can then use it to join.", + "edit_session.about": "Edit Sessions can be used to collaborate on models across the internet. Create a session, copy the token, and send it to friends, who can then use it to join.", "edit_session.join": "Join Session", "edit_session.create": "Create Session", "edit_session.quit": "Quit Session",
edit_session.about
edit_session.status: edit_session.connected