Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Heavily defer requires for faster activation time #234

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 12 additions & 8 deletions lib/popover-component.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const etch = require('etch')
const $ = etch.dom
const PortalListComponent = require('./portal-list-component')
const SignInComponent = require('./sign-in-component')
const PackageOutdatedComponent = require('./package-outdated-component')
const PackageInitializationErrorComponent = require('./package-initialization-error-component')
let PortalListComponent = null
let SignInComponent = null
let PackageOutdatedComponent = null
let PackageInitializationErrorComponent = null

module.exports =
class PopoverComponent {
Expand All @@ -21,22 +21,25 @@ class PopoverComponent {

render () {
const {
isClientOutdated, initializationError,
isClientOutdated, hasInitializationError,
authenticationProvider, portalBindingManager,
commandRegistry, credentialCache, clipboard, workspace, notificationManager
} = this.props

let activeComponent
if (isClientOutdated) {
if (isClientOutdated()) {
if (!PackageOutdatedComponent) PackageOutdatedComponent = require('./package-outdated-component')
activeComponent = $(PackageOutdatedComponent, {
ref: 'packageOutdatedComponent',
workspace
})
} else if (initializationError) {
} else if (hasInitializationError()) {
if (!PackageInitializationErrorComponent) PackageInitializationErrorComponent = require('./package-initialization-error-component')
activeComponent = $(PackageInitializationErrorComponent, {
ref: 'packageInitializationErrorComponent'
})
} else if (this.props.authenticationProvider.isSignedIn()) {
} else if (authenticationProvider.isSignedIn()) {
if (!PortalListComponent) PortalListComponent = require('./portal-list-component')
activeComponent = $(PortalListComponent, {
ref: 'portalListComponent',
localUserIdentity: authenticationProvider.getIdentity(),
Expand All @@ -46,6 +49,7 @@ class PopoverComponent {
notificationManager
})
} else {
if (!SignInComponent) SignInComponent = require('./sign-in-component')
activeComponent = $(SignInComponent, {
ref: 'signInComponent',
authenticationProvider,
Expand Down
61 changes: 40 additions & 21 deletions lib/portal-status-bar-indicator.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
const {CompositeDisposable} = require('atom')
const PopoverComponent = require('./popover-component')
let PopoverComponent = null

module.exports =
class PortalStatusBarIndicator {
constructor (props) {
this.props = props
this.subscriptions = new CompositeDisposable()
this.element = buildElement(props)
this.popoverComponent = new PopoverComponent(props)

if (props.portalBindingManager) {
this.portalBindingManager = props.portalBindingManager
this.subscriptions.add(this.portalBindingManager.onDidChange(() => {
this.updatePortalStatus()
}))
}
this.element.onclick = this.handleInitialClick.bind(this)
}

attach () {
Expand All @@ -23,15 +16,6 @@ class PortalStatusBarIndicator {
item: this,
priority: PRIORITY_BETWEEN_BRANCH_NAME_AND_GRAMMAR
})
this.tooltip = this.props.tooltipManager.add(
this.element,
{
item: this.popoverComponent,
class: 'TeletypePopoverTooltip',
trigger: 'click',
placement: 'top'
}
)
}

destroy () {
Expand All @@ -49,6 +33,7 @@ class PortalStatusBarIndicator {
}

isPopoverVisible () {
if (!this.popoverComponent) return false
return document.contains(this.popoverComponent.element)
}

Expand All @@ -60,13 +45,47 @@ class PortalStatusBarIndicator {
this.element.classList.remove('transmitting')
}
}

async handleInitialClick () {
this.initialOpenPromise = new Promise((resolve, reject) => this.resolveInitialOpenPromise = resolve)
this.element.onclick = null
this.portalBindingManager = await this.props.getPortalBindingManager()
if (this.portalBindingManager) {
this.subscriptions.add(this.portalBindingManager.onDidChange(() => {
this.updatePortalStatus()
}))
}

this.authenticationProvider = await this.props.getAuthenticationProvider()
if (this.authenticationProvider) await this.authenticationProvider.signInUsingSavedToken()

if (!PopoverComponent) PopoverComponent = require('./popover-component')
this.popoverComponent = new PopoverComponent(Object.assign(
{portalBindingManager: this.portalBindingManager},
{authenticationProvider: this.authenticationProvider},
this.props
))
this.tooltip = this.props.tooltipManager.add(
this.element,
{
item: this.popoverComponent,
class: 'TeletypePopoverTooltip',
trigger: 'click',
placement: 'top'
}
)

if (this.props.isClientOutdated()) this.element.classList.add('outdated')
if (this.props.hasInitializationError()) this.element.classList.add('initialization-error')

this.element.click()
this.resolveInitialOpenPromise(this.popoverComponent)
}
}

function buildElement (props) {
function buildElement () {
const anchor = document.createElement('a')
anchor.classList.add('PortalStatusBarIndicator', 'inline-block')
if (props.isClientOutdated) anchor.classList.add('outdated')
if (props.initializationError) anchor.classList.add('initialization-error')

const icon = document.createElement('span')
icon.classList.add('icon', 'icon-radio-tower')
Expand Down
87 changes: 53 additions & 34 deletions lib/teletype-package.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const {TeletypeClient, Errors} = require('@atom/teletype-client')
const {CompositeDisposable} = require('atom')
const PortalBindingManager = require('./portal-binding-manager')
const PortalStatusBarIndicator = require('./portal-status-bar-indicator')
const AuthenticationProvider = require('./authentication-provider')
const CredentialCache = require('./credential-cache')
let [TeletypeClient, Errors] = []
let PortalBindingManager = null
let PortalStatusBarIndicator = null
let AuthenticationProvider = null
let CredentialCache = null

module.exports =
class TeletypePackage {
Expand All @@ -23,21 +23,13 @@ class TeletypePackage {
this.pusherOptions = pusherOptions
this.baseURL = baseURL
this.tetherDisconnectWindow = tetherDisconnectWindow
this.credentialCache = credentialCache || new CredentialCache()
this.client = new TeletypeClient({
pusherKey: this.pusherKey,
pusherOptions: this.pusherOptions,
baseURL: this.baseURL,
pubSubGateway: this.pubSubGateway,
tetherDisconnectWindow: this.tetherDisconnectWindow
})
this.client.onConnectionError(this.handleConnectionError.bind(this))
this.credentialCache = credentialCache
this.portalBindingManagerPromise = null
}

activate () {
console.log('teletype: Using pusher key:', this.pusherKey)
console.log('teletype: Using base URL:', this.baseURL)
// console.log('teletype: Using pusher key:', this.pusherKey)
// console.log('teletype: Using base URL:', this.baseURL)

this.subscriptions = new CompositeDisposable()

Expand All @@ -53,10 +45,6 @@ class TeletypePackage {
this.subscriptions.add(this.commandRegistry.add('atom-workspace.teletype-Host', {
'teletype:close-portal': () => this.closeHostPortal()
}))

// Initiate sign-in, which will continue asynchronously, since we don't want
// to block here.
this.signInUsingSavedToken()
}

async deactivate () {
Expand All @@ -65,11 +53,12 @@ class TeletypePackage {

if (this.portalBindingManagerPromise) {
const manager = await this.portalBindingManagerPromise
await manager.dispose()
if (manager) await manager.dispose()
}
}

async sharePortal () {
await this.signInUsingSavedToken()
this.showPopover()

if (await this.isSignedIn()) {
Expand All @@ -80,6 +69,7 @@ class TeletypePackage {
}

async joinPortal (id) {
await this.signInUsingSavedToken()
this.showPopover()

if (await this.isSignedIn()) {
Expand All @@ -102,16 +92,17 @@ class TeletypePackage {
}

async consumeStatusBar (statusBar) {
const teletypeClient = await this.getClient()
const portalBindingManager = await this.getPortalBindingManager()
const authenticationProvider = await this.getAuthenticationProvider()
const getPortalBindingManager = async () => await this.getPortalBindingManager()
const getAuthenticationProvider = async () => await this.getAuthenticationProvider()
const isClientOutdated = () => this.isClientOutdated
const hasInitializationError = () => this.initializationError
if (!PortalStatusBarIndicator) PortalStatusBarIndicator = require('./portal-status-bar-indicator')
this.portalStatusBarIndicator = new PortalStatusBarIndicator({
statusBar,
teletypeClient,
portalBindingManager,
authenticationProvider,
isClientOutdated: this.isClientOutdated,
initializationError: this.initializationError,
getPortalBindingManager,
getAuthenticationProvider,
isClientOutdated,
hasInitializationError,
tooltipManager: this.tooltipManager,
commandRegistry: this.commandRegistry,
clipboard: this.clipboard,
Expand Down Expand Up @@ -157,7 +148,8 @@ class TeletypePackage {
async showJoinPortalPrompt () {
if (!this.portalStatusBarIndicator) return

const {popoverComponent} = this.portalStatusBarIndicator
let {popoverComponent} = this.portalStatusBarIndicator
if (!popoverComponent) popoverComponent = await this.portalStatusBarIndicator.initialOpenPromise
const {portalListComponent} = popoverComponent.refs
await portalListComponent.showJoinPortalPrompt()
}
Expand All @@ -172,16 +164,24 @@ class TeletypePackage {
}

getAuthenticationProvider () {
if (this.authenticationProvider) return Promise.resolve(this.authenticationProvider)

if (!this.authenticationProviderPromise) {
this.authenticationProviderPromise = new Promise(async (resolve, reject) => {
const client = await this.getClient()
if (client) {
resolve(new AuthenticationProvider({
if (!AuthenticationProvider) AuthenticationProvider = require('./authentication-provider')
if (!this.credentialCache) {
if (!CredentialCache) CredentialCache = require('./credential-cache')
this.credentialCache = new CredentialCache()
}
this.authenticationProvider = new AuthenticationProvider({
client,
credentialCache: this.credentialCache,
notificationManager: this.notificationManager,
workspace: this.workspace
}))
})
resolve(this.authenticationProvider)
} else {
this.authenticationProviderPromise = null
resolve(null)
Expand All @@ -193,15 +193,19 @@ class TeletypePackage {
}

getPortalBindingManager () {
if (this.portalBindingManager) return Promise.resolve(this.portalBindingManager)

if (!this.portalBindingManagerPromise) {
this.portalBindingManagerPromise = new Promise(async (resolve, reject) => {
const client = await this.getClient()
if (client) {
resolve(new PortalBindingManager({
if (!PortalBindingManager) PortalBindingManager = require('./portal-binding-manager')
this.portalBindingManager = new PortalBindingManager({
client,
workspace: this.workspace,
notificationManager: this.notificationManager
}))
})
resolve(this.portalBindingManager)
} else {
this.portalBindingManagerPromise = null
resolve(null)
Expand All @@ -217,6 +221,21 @@ class TeletypePackage {
if (this.isClientOutdated) return null

try {
if(!TeletypeClient) ({TeletypeClient, Errors} = require('@atom/teletype-client'))
if (this.client) {
await this.client.initialize()
return this.client
}

this.client = new TeletypeClient({
pusherKey: this.pusherKey,
pusherOptions: this.pusherOptions,
baseURL: this.baseURL,
pubSubGateway: this.pubSubGateway,
tetherDisconnectWindow: this.tetherDisconnectWindow
})
this.client.onConnectionError(this.handleConnectionError.bind(this))

await this.client.initialize()
return this.client
} catch (error) {
Expand Down
7 changes: 7 additions & 0 deletions test/teletype-package.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ suite('TeletypePackage', function () {
// Show popover when running the "Share Portal" command, but prevent sharing unless user is authenticated.
assert(!pack.portalStatusBarIndicator.isPopoverVisible())
assert(!await pack.sharePortal())
await pack.portalStatusBarIndicator.initialOpenPromise
assert(pack.portalStatusBarIndicator.isPopoverVisible())

// Show popover when running the "Join Portal" command, but prevent sharing unless user is authenticated.
Expand Down Expand Up @@ -863,6 +864,7 @@ suite('TeletypePackage', function () {

await pack.consumeStatusBar(new FakeStatusBar())
const {portalStatusBarIndicator} = pack
await portalStatusBarIndicator.handleInitialClick() // Initialize popover component
const {popoverComponent} = portalStatusBarIndicator
const {packageOutdatedComponent} = popoverComponent.refs

Expand Down Expand Up @@ -921,6 +923,7 @@ suite('TeletypePackage', function () {
}

await pack.consumeStatusBar(new FakeStatusBar())
await pack.portalStatusBarIndicator.handleInitialClick() // Initialize popover component

assert.equal(env.notifications.getNotifications().length, 1)
const {type, message, options} = env.notifications.getNotifications()[0]
Expand All @@ -943,6 +946,7 @@ suite('TeletypePackage', function () {
throw new Error('some error')
}

await pack.portalStatusBarIndicator.handleInitialClick() // Initialize popover component
const {popoverComponent} = pack.portalStatusBarIndicator
popoverComponent.refs.signInComponent.refs.editor.setText('some-token')
await popoverComponent.refs.signInComponent.signIn()
Expand Down Expand Up @@ -988,6 +992,9 @@ suite('TeletypePackage', function () {
if (options.signIn == null || options.signIn) {
await credentialCache.set('oauth-token', 'token-' + nextTokenId++)
await pack.signInUsingSavedToken()
} else {
// We still need to activate the client for some tests
await pack.getClient()
}
packages.push(pack)
return pack
Expand Down