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

Commit 6bae0f4

Browse files
author
Antonio Scandurra
authored
Merge pull request #323 from atom/fuzzy-finder-support
Allow guests to use fuzzy-finder to open any remote editor shared by the host
2 parents 8ecb6cf + 153b577 commit 6bae0f4

23 files changed

+373
-304
lines changed

lib/editor-binding.js

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
const path = require('path')
44
const {Range, Emitter, Disposable, CompositeDisposable} = require('atom')
5-
const normalizeURI = require('./normalize-uri')
5+
const getPathWithNativeSeparators = require('./get-path-with-native-separators')
6+
const getEditorURI = require('./get-editor-uri')
67
const {FollowState} = require('@atom/teletype-client')
78

89
module.exports =
@@ -32,17 +33,12 @@ class EditorBinding {
3233

3334
this.emitter.emit('did-dispose')
3435
this.emitter.dispose()
35-
36-
if (!this.isHost) this.editor.destroy()
3736
}
3837

3938
setEditorProxy (editorProxy) {
4039
this.editorProxy = editorProxy
41-
if (this.isHost) {
42-
this.editor.onDidDestroy(() => this.editorProxy.dispose())
43-
} else {
40+
if (!this.isHost) {
4441
this.monkeyPatchEditorMethods(this.editor, this.editorProxy)
45-
this.editor.onDidDestroy(() => this.dispose())
4642
}
4743

4844
this.localCursorLayerDecoration = this.editor.decorateMarkerLayer(
@@ -63,20 +59,20 @@ class EditorBinding {
6359

6460
monkeyPatchEditorMethods (editor, editorProxy) {
6561
const buffer = editor.getBuffer()
66-
const bufferProxy = editorProxy.bufferProxy
62+
const {bufferProxy} = editorProxy
6763
const hostIdentity = this.portal.getSiteIdentity(1)
68-
const uriPrefix = hostIdentity ? `@${hostIdentity.login}` : 'remote'
64+
const prefix = hostIdentity ? `@${hostIdentity.login}` : 'remote'
65+
const bufferURI = getPathWithNativeSeparators(bufferProxy.uri)
6966

70-
const bufferURI = normalizeURI(bufferProxy.uri)
71-
editor.getTitle = () => `${uriPrefix}: ${path.basename(bufferURI)}`
72-
editor.getURI = () => ''
67+
editor.getTitle = () => `${prefix}: ${path.basename(bufferURI)}`
68+
editor.getURI = () => getEditorURI(this.portal.id, editorProxy.id)
7369
editor.copy = () => null
7470
editor.serialize = () => null
7571
editor.isRemote = true
7672

7773
let remoteEditorCountForBuffer = buffer.remoteEditorCount || 0
7874
buffer.remoteEditorCount = ++remoteEditorCountForBuffer
79-
buffer.getPath = () => `${uriPrefix}:${bufferURI}`
75+
buffer.getPath = () => `${prefix}:${bufferURI}`
8076
buffer.save = () => { bufferProxy.requestSave() }
8177
buffer.isModified = () => false
8278

lib/empty-portal-pane-item.js

Lines changed: 0 additions & 43 deletions
This file was deleted.

lib/get-editor-uri.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function getEditorURI (portalId, editorProxyId) {
2+
return 'atom://teletype/portal/' + portalId + '/editor/' + editorProxyId
3+
}

lib/normalize-uri.js renamed to lib/get-path-with-native-separators.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const WINDOWS_PATH_SEP_SEARCH_PATTERN = /\\/g
44
const POSIX_PATH_SEP_SEARCH_PATTERN = /\//g
55

66
module.exports =
7-
function normalizeURI (uri, targetPathSeparator = path.sep) {
7+
function getPathWithNativeSeparators (uri, targetPathSeparator = path.sep) {
88
const PATH_SEP_SEARCH_PATTERN = (targetPathSeparator === '/') ? WINDOWS_PATH_SEP_SEARCH_PATTERN : POSIX_PATH_SEP_SEARCH_PATTERN
99
return uri.replace(PATH_SEP_SEARCH_PATTERN, targetPathSeparator)
1010
}

lib/guest-portal-binding.js

Lines changed: 51 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ const {CompositeDisposable, Emitter, TextEditor, TextBuffer} = require('atom')
22
const {Errors, FollowState} = require('@atom/teletype-client')
33
const BufferBinding = require('./buffer-binding')
44
const EditorBinding = require('./editor-binding')
5-
const EmptyPortalPaneItem = require('./empty-portal-pane-item')
65
const SitePositionsController = require('./site-positions-controller')
6+
const getPathWithNativeSeparators = require('./get-path-with-native-separators')
7+
const getEditorURI = require('./get-editor-uri')
78
const NOOP = () => {}
89

910
module.exports =
@@ -15,14 +16,14 @@ class GuestPortalBinding {
1516
this.notificationManager = notificationManager
1617
this.emitDidDispose = didDispose || NOOP
1718
this.lastActivePaneItem = null
18-
this.editorBindingsByEditorProxy = new Map()
19-
this.bufferBindingsByBufferProxy = new Map()
19+
this.editorBindingsByEditorProxyId = new Map()
20+
this.bufferBindingsByBufferProxyId = new Map()
2021
this.editorProxiesByEditor = new WeakMap()
22+
this.editorProxiesMetadataById = new Map()
2123
this.emitter = new Emitter()
2224
this.subscriptions = new CompositeDisposable()
2325
this.lastEditorProxyChangePromise = Promise.resolve()
2426
this.shouldRelayActiveEditorChanges = true
25-
this.lastDestroyedEditor = null
2627
}
2728

2829
async initialize () {
@@ -32,10 +33,8 @@ class GuestPortalBinding {
3233

3334
this.sitePositionsController = new SitePositionsController({portal: this.portal, workspace: this.workspace})
3435
this.subscriptions.add(this.workspace.onDidChangeActivePaneItem(this.didChangeActivePaneItem.bind(this)))
35-
this.subscriptions.add(this.workspace.onDidDestroyPaneItem(this.didDestroyPaneItem.bind(this)))
3636

3737
await this.portal.setDelegate(this)
38-
await this.toggleEmptyPortalPaneItem()
3938

4039
return true
4140
} catch (error) {
@@ -47,7 +46,6 @@ class GuestPortalBinding {
4746
dispose () {
4847
this.subscriptions.dispose()
4948
this.sitePositionsController.destroy()
50-
if (this.emptyPortalItem) this.emptyPortalItem.destroy()
5149

5250
this.emitDidDispose()
5351
}
@@ -66,28 +64,36 @@ class GuestPortalBinding {
6664
this.emitter.emit('did-change')
6765
}
6866

69-
addEditorProxy (editorProxy) {
70-
// TODO Implement in order to allow guests to open any editor that's in the host's workspace
71-
}
67+
didChangeEditorProxies () {}
7268

73-
removeEditorProxy (editorProxy) {
74-
this.lastEditorProxyChangePromise = this.lastEditorProxyChangePromise.then(async () => {
75-
const editorBinding = this.editorBindingsByEditorProxy.get(editorProxy)
76-
if (editorBinding) {
77-
const isRetracted = this.portal.resolveFollowState() === FollowState.RETRACTED
78-
this.shouldRelayActiveEditorChanges = !isRetracted
79-
editorBinding.dispose()
80-
this.shouldRelayActiveEditorChanges = true
69+
getRemoteEditors () {
70+
const hostIdentity = this.portal.getSiteIdentity(1)
71+
const bufferProxyIds = new Set()
72+
const remoteEditors = []
73+
const editorProxiesMetadata = this.portal.getEditorProxiesMetadata()
8174

82-
if (this.editorBindingsByEditorProxy.size === 0) {
83-
this.portal.follow(1)
84-
}
75+
for (let i = 0; i < editorProxiesMetadata.length; i++) {
76+
const {id, bufferProxyId, bufferProxyURI} = editorProxiesMetadata[i]
77+
if (bufferProxyIds.has(bufferProxyId)) continue
8578

86-
await this.toggleEmptyPortalPaneItem()
87-
}
88-
})
79+
remoteEditors.push({
80+
hostGitHubUsername: hostIdentity.login,
81+
uri: getEditorURI(this.portal.id, id),
82+
path: getPathWithNativeSeparators(bufferProxyURI)
83+
})
84+
bufferProxyIds.add(bufferProxyId)
85+
}
8986

90-
return this.lastEditorProxyChangePromise
87+
return remoteEditors
88+
}
89+
90+
async getRemoteEditor (editorProxyId) {
91+
const editorProxy = await this.portal.findOrFetchEditorProxy(editorProxyId)
92+
if (editorProxy) {
93+
return this.findOrCreateEditorForEditorProxy(editorProxy)
94+
} else {
95+
return null
96+
}
9197
}
9298

9399
updateActivePositions (positionsBySiteId) {
@@ -111,12 +117,11 @@ class GuestPortalBinding {
111117
this.shouldRelayActiveEditorChanges = false
112118
await this.openPaneItem(editor)
113119
this.shouldRelayActiveEditorChanges = true
114-
await this.toggleEmptyPortalPaneItem()
115120
} else {
116-
this.editorBindingsByEditorProxy.forEach((b) => b.updateTether(followState))
121+
this.editorBindingsByEditorProxyId.forEach((b) => b.updateTether(followState))
117122
}
118123

119-
const editorBinding = this.editorBindingsByEditorProxy.get(editorProxy)
124+
const editorBinding = this.editorBindingsByEditorProxyId.get(editorProxy.id)
120125
if (editorBinding && position) {
121126
editorBinding.updateTether(followState, position)
122127
}
@@ -125,7 +130,7 @@ class GuestPortalBinding {
125130
// Private
126131
findOrCreateEditorForEditorProxy (editorProxy) {
127132
let editor
128-
let editorBinding = this.editorBindingsByEditorProxy.get(editorProxy)
133+
let editorBinding = this.editorBindingsByEditorProxyId.get(editorProxy.id)
129134
if (editorBinding) {
130135
editor = editorBinding.editor
131136
} else {
@@ -140,12 +145,20 @@ class GuestPortalBinding {
140145
editorBinding.setEditorProxy(editorProxy)
141146
editorProxy.setDelegate(editorBinding)
142147

143-
this.editorBindingsByEditorProxy.set(editorProxy, editorBinding)
148+
this.editorBindingsByEditorProxyId.set(editorProxy.id, editorBinding)
144149
this.editorProxiesByEditor.set(editor, editorProxy)
150+
151+
const didDestroyEditorSubscription = editor.onDidDestroy(() => editorBinding.dispose())
145152
editorBinding.onDidDispose(() => {
146-
this.lastDestroyedEditor = editor
153+
didDestroyEditorSubscription.dispose()
154+
155+
const isRetracted = this.portal.resolveFollowState() === FollowState.RETRACTED
156+
this.shouldRelayActiveEditorChanges = !isRetracted
157+
editor.destroy()
158+
this.shouldRelayActiveEditorChanges = true
159+
147160
this.editorProxiesByEditor.delete(editor)
148-
this.editorBindingsByEditorProxy.delete(editorProxy)
161+
this.editorBindingsByEditorProxyId.delete(editorProxy.id)
149162
})
150163

151164
this.sitePositionsController.addEditorBinding(editorBinding)
@@ -156,34 +169,23 @@ class GuestPortalBinding {
156169
// Private
157170
findOrCreateBufferForBufferProxy (bufferProxy) {
158171
let buffer
159-
let bufferBinding = this.bufferBindingsByBufferProxy.get(bufferProxy)
172+
let bufferBinding = this.bufferBindingsByBufferProxyId.get(bufferProxy.id)
160173
if (bufferBinding) {
161174
buffer = bufferBinding.buffer
162175
} else {
163176
buffer = new TextBuffer()
164177
bufferBinding = new BufferBinding({
165178
buffer,
166179
isHost: false,
167-
didDispose: () => this.bufferBindingsByBufferProxy.delete(bufferProxy)
180+
didDispose: () => this.bufferBindingsByBufferProxyId.delete(bufferProxy.id)
168181
})
169182
bufferBinding.setBufferProxy(bufferProxy)
170183
bufferProxy.setDelegate(bufferBinding)
171-
this.bufferBindingsByBufferProxy.set(bufferProxy, bufferBinding)
184+
this.bufferBindingsByBufferProxyId.set(bufferProxy.id, bufferBinding)
172185
}
173186
return buffer
174187
}
175188

176-
// Private
177-
async toggleEmptyPortalPaneItem () {
178-
const emptyPortalItem = this.getEmptyPortalPaneItem()
179-
const pane = this.workspace.paneForItem(emptyPortalItem)
180-
if (this.editorBindingsByEditorProxy.size === 0) {
181-
if (!pane) await this.openPaneItem(emptyPortalItem)
182-
} else {
183-
if (pane) emptyPortalItem.destroy()
184-
}
185-
}
186-
187189
activate () {
188190
const paneItem = this.lastActivePaneItem
189191
const pane = this.workspace.paneForItem(paneItem)
@@ -241,48 +243,25 @@ class GuestPortalBinding {
241243
didChangeActivePaneItem (paneItem) {
242244
const editorProxy = this.editorProxiesByEditor.get(paneItem)
243245

244-
if (editorProxy || paneItem === this.getEmptyPortalPaneItem()) {
246+
if (editorProxy) {
245247
this.sitePositionsController.show(paneItem.element)
246248
} else {
247249
this.sitePositionsController.hide()
248250
}
249251

250-
if (this.shouldRelayActiveEditorChanges && paneItem !== this.getEmptyPortalPaneItem()) {
252+
if (this.shouldRelayActiveEditorChanges) {
251253
this.portal.activateEditorProxy(editorProxy)
252254
}
253255
}
254256

255-
didDestroyPaneItem ({item}) {
256-
const emptyPortalItem = this.getEmptyPortalPaneItem()
257-
const hasNoPortalPaneItem = this.workspace.getPaneItems().every((item) => (
258-
item !== emptyPortalItem && !this.editorProxiesByEditor.has(item)
259-
))
260-
const lastDestroyedEditorWasClosedManually = this.lastDestroyedEditor !== item
261-
if (hasNoPortalPaneItem && lastDestroyedEditorWasClosedManually) {
262-
this.leave()
263-
}
264-
}
265-
266257
hasPaneItem (paneItem) {
267-
return (
268-
paneItem === this.getEmptyPortalPaneItem() ||
269-
this.editorProxiesByEditor.has(paneItem)
270-
)
258+
return this.editorProxiesByEditor.has(paneItem)
271259
}
272260

273261
getActivePaneItem () {
274262
return this.newActivePaneItem || this.workspace.getActivePaneItem()
275263
}
276264

277-
getEmptyPortalPaneItem () {
278-
if (this.emptyPortalItem == null) {
279-
this.emptyPortalItem = new EmptyPortalPaneItem({
280-
hostIdentity: this.portal.getSiteIdentity(1)
281-
})
282-
}
283-
return this.emptyPortalItem
284-
}
285-
286265
onDidChange (callback) {
287266
return this.emitter.on('did-change', callback)
288267
}

lib/host-portal-binding.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class HostPortalBinding {
2929

3030
this.portal.setDelegate(this)
3131
this.disposables.add(
32-
this.workspace.observeActiveTextEditor(this.didChangeActiveTextEditor.bind(this)),
33-
this.workspace.onDidDestroyPaneItem(this.didDestroyPaneItem.bind(this))
32+
this.workspace.observeTextEditors(this.didAddTextEditor.bind(this)),
33+
this.workspace.observeActiveTextEditor(this.didChangeActiveTextEditor.bind(this))
3434
)
3535

3636
this.workspace.getElement().classList.add('teletype-Host')
@@ -108,11 +108,8 @@ class HostPortalBinding {
108108
}
109109
}
110110

111-
didDestroyPaneItem ({item}) {
112-
const editorBinding = this.editorBindingsByEditor.get(item)
113-
if (editorBinding) {
114-
this.portal.removeEditorProxy(editorBinding.editorProxy)
115-
}
111+
didAddTextEditor (editor) {
112+
if (!editor.isRemote) this.findOrCreateEditorProxyForEditor(editor)
116113
}
117114

118115
findOrCreateEditorProxyForEditor (editor) {
@@ -128,7 +125,10 @@ class HostPortalBinding {
128125

129126
this.editorBindingsByEditor.set(editor, editorBinding)
130127
this.editorBindingsByEditorProxy.set(editorProxy, editorBinding)
128+
129+
const didDestroyEditorSubscription = editor.onDidDestroy(() => editorProxy.dispose())
131130
editorBinding.onDidDispose(() => {
131+
didDestroyEditorSubscription.dispose()
132132
this.editorBindingsByEditorProxy.delete(editorProxy)
133133
})
134134

lib/is-uuid.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/
2+
module.exports = function isUUID (string) {
3+
return UUID_REGEXP.test(string)
4+
}

0 commit comments

Comments
 (0)