-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: allow apps to add a menubar via puter.js
* Begin work on menubar and dropdowns * Improve menubar * Fix pointer event behavior * Fix labels * Fix active button * Eliminate flicker * Update _default.js --------- Co-authored-by: Nariman Jelveh <n.jelveh@gmail.com>
- Loading branch information
1 parent
ec31007
commit 331d9e7
Showing
9 changed files
with
361 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/** | ||
* This module provides a simple RPC mechanism for cross-document | ||
* (iframe / window.postMessage) communication. | ||
*/ | ||
|
||
// Since `Symbol` is not clonable, we use a UUID to identify RPCs. | ||
const $SCOPE = '9a9c83a4-7897-43a0-93b9-53217b84fde6'; | ||
|
||
/** | ||
* The CallbackManager is used to manage callbacks for RPCs. | ||
* It is used by the dehydrator and hydrator to store and retrieve | ||
* the functions that are being called remotely. | ||
*/ | ||
export class CallbackManager { | ||
#messageId = 0; | ||
|
||
constructor () { | ||
this.callbacks = new Map(); | ||
} | ||
|
||
register_callback (callback) { | ||
const id = this.#messageId++; | ||
this.callbacks.set(id, callback); | ||
return id; | ||
} | ||
|
||
attach_to_source (source) { | ||
source.addEventListener('message', event => { | ||
const { data } = event; | ||
console.log( | ||
'test-app got message from window', | ||
data, | ||
); | ||
debugger; | ||
if (data && typeof data === 'object' && data.$SCOPE === $SCOPE) { | ||
const { id, args } = data; | ||
const callback = this.callbacks.get(id); | ||
if (callback) { | ||
callback(...args); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* The dehydrator replaces functions in an object with identifiers, | ||
* so that hydrate() can be called on the other side of the frame | ||
* to bind RPC stubs. The original functions are stored in a map | ||
* so that they can be called when the RPC is invoked. | ||
*/ | ||
export class Dehydrator { | ||
constructor ({ callbackManager }) { | ||
this.callbackManager = callbackManager; | ||
} | ||
dehydrate (value) { | ||
return this.dehydrate_value_(value); | ||
} | ||
dehydrate_value_ (value) { | ||
if (typeof value === 'function') { | ||
const id = this.callbackManager.register_callback(value); | ||
return { $SCOPE, id }; | ||
} else if (Array.isArray(value)) { | ||
return value.map(this.dehydrate_value_.bind(this)); | ||
} else if (typeof value === 'object' && value !== null) { | ||
const result = {}; | ||
for (const key in value) { | ||
result[key] = this.dehydrate_value_(value[key]); | ||
} | ||
return result; | ||
} else { | ||
return value; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* The hydrator binds RPC stubs to the functions that were | ||
* previously dehydrated. This allows the RPC to be invoked | ||
* on the other side of the frame. | ||
*/ | ||
export class Hydrator { | ||
constructor ({ target }) { | ||
this.target = target; | ||
} | ||
hydrate (value) { | ||
return this.hydrate_value_(value); | ||
} | ||
hydrate_value_ (value) { | ||
if ( | ||
value && typeof value === 'object' && | ||
value.$SCOPE === $SCOPE | ||
) { | ||
const { id } = value; | ||
return (...args) => { | ||
console.log('sending message', { $SCOPE, id, args }); | ||
console.log('target', this.target); | ||
this.target.postMessage({ $SCOPE, id, args }, '*'); | ||
}; | ||
} else if (Array.isArray(value)) { | ||
return value.map(this.hydrate_value_.bind(this)); | ||
} else if (typeof value === 'object' && value !== null) { | ||
const result = {}; | ||
for (const key in value) { | ||
result[key] = this.hydrate_value_(value[key]); | ||
} | ||
return result; | ||
} | ||
return value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { CallbackManager, Dehydrator, Hydrator } from "../lib/xdrpc"; | ||
|
||
/** | ||
* The Util module exposes utilities within puter.js itself. | ||
* These utilities may be used internally by other modules. | ||
*/ | ||
export default class Util { | ||
constructor () { | ||
// This is in `puter.util.rpc` instead of `puter.rpc` because | ||
// `puter.rpc` is reserved for an app-to-app RPC interface. | ||
// This is a lower-level RPC interface used to communicate | ||
// with iframes. | ||
this.rpc = new UtilRPC(); | ||
} | ||
} | ||
|
||
class UtilRPC { | ||
constructor () { | ||
this.callbackManager = new CallbackManager(); | ||
this.callbackManager.attach_to_source(window); | ||
} | ||
|
||
getDehydrator () { | ||
return new Dehydrator({ callbackManager: this.callbackManager }); | ||
} | ||
|
||
getHydrator ({ target }) { | ||
return new Hydrator({ target }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.