diff --git a/resources/js/EmptyWorkspace.js b/resources/js/EmptyWorkspace.js new file mode 100644 index 0000000..6361c53 --- /dev/null +++ b/resources/js/EmptyWorkspace.js @@ -0,0 +1,67 @@ +import { debug, error } from './logger'; + +export default class EmptyWorkspace { + + constructor() { + this.echo = null; + this.started = false; + this.channelName = null; + this.user = Statamic.user; + this.subscribeTimeout = null; + } + + start() { + if (this.started) return; + + this.startChannel(); + } + + startChannel() { + this.initializeEcho(); + } + + destroy() { + this.stopChannel(); + } + + stopChannel() { + + if (this.subscribeTimeout) { + clearTimeout(this.subscribeTimeout); + this.subscribeTimeout = null; + } + + if (this.channelName) { + this.echo.leave(this.channelName); + } + } + + initializeEcho() { + this.channelName = `users.delay`; + + const channelName = this.channelName; + debug(`Joining channel "${channelName}"`); + this.channel = this.echo.join(channelName); + + const timeout = setTimeout(() => { + debug(`⏳ Still waiting to subscribe to "${channelName}" — is your broadcast server running and reachable?`); + if (this.subscribeTimeout === timeout) this.subscribeTimeout = null; + }, 5000); + this.subscribeTimeout = timeout; + + const clearSubscribeTimeout = () => { + clearTimeout(timeout); + if (this.subscribeTimeout === timeout) this.subscribeTimeout = null; + }; + + this.channel + .subscribed(() => { + clearSubscribeTimeout(); + debug(`✅ Subscribed to channel "${channelName}"`); + }) + .error(e => { + clearSubscribeTimeout(); + error(`❌ Subscription error on channel "${channelName}"`, {error: e}); + }); + } +} diff --git a/resources/js/Manager.js b/resources/js/Manager.js index 755dc88..7176ff3 100644 --- a/resources/js/Manager.js +++ b/resources/js/Manager.js @@ -1,3 +1,4 @@ +import EmptyWorkspace from './EmptyWorkspace'; import Workspace from './Workspace'; export default class Manager { @@ -10,13 +11,37 @@ export default class Manager { boot() { if (! this.echo) return; + let workspaceStarted = false; + + Object.values(this.workspaces).forEach(workspace => { workspace.echo = this.echo; workspace.start(); + + workspaceStarted = true; }); + + if( !workspaceStarted ) { + this.addEmptyWorkspace(); + } + } + + addEmptyWorkspace() { + const workspace = new EmptyWorkspace(); + this.workspaces['empty'] = workspace; + this.boot(); + } + + destroyEmptyWorkspace() { + this.workspaces['empty'].destroy(); + delete this.workspaces['empty']; } addWorkspace(container) { + if( this.workspaces['empty'] ) { + this.destroyEmptyWorkspace(); + } + const workspace = new Workspace(container); this.workspaces[container.name] = workspace; this.boot(); diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 483dc65..4326285 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -19,6 +19,19 @@ public function bootAddon() { Statamic::provideToScript(['collaboration' => config('collaboration')]); + Broadcast::channel('users.delay', function ($user) { + $user = User::fromUser($user); + + return [ + 'name' => $user->name(), + 'id' => $user->id(), + 'title' => $user->title(), + 'email' => $user->email(), + 'avatar' => $user->avatar(), + 'initials' => $user->initials(), + ]; + }, ['guards' => [config('statamic.users.guards.cp')]]); + Broadcast::channel('entry.{id}.{site}', function ($user, $id, $site) { $user = User::fromUser($user);