Skip to content

Commit 95ee6e5

Browse files
committed
organized meteor loading code a little better based on update to lume.io, move the meteor login UI to the navbar and make it visible
1 parent ad0c042 commit 95ee6e5

File tree

5 files changed

+170
-76
lines changed

5 files changed

+170
-76
lines changed

_navbar.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,49 @@
33
- [Forum](//lume.community)
44
- [Chat](//discord.gg/PgeyevP)
55
- [Source Code](//github.com/lume/lume)
6+
- <blaze-component id="loginButtons" tmpl="loginButtons" data='{"align": "right"}' onclick="
7+
// Don't allow this menu item to have effect on Docsify's routing.
8+
event.stopImmediatePropagation()
9+
// Only handle clicks on the dropdown link.
10+
if (!event.target?.classList.contains('login-link-text')) return
11+
// This makes it so that clicking the dropdown link will close the popup if
12+
// it is already open.
13+
const close = document.querySelector('.login-close-text')
14+
if (close) close.click()
15+
"></blaze-component>
16+
17+
<style>
18+
#loginButtons {
19+
user-select: none;
20+
21+
.accounts-dialog {
22+
pointer-events: auto;
23+
text-transform: none;
24+
font-family: var(--base-font-family);
25+
text-align: left;
26+
letter-spacing: normal;
27+
text-decoration: none;
28+
29+
transform: translate(-16px, 30px);
30+
}
31+
32+
.accounts-dialog * {
33+
font-family: inherit;
34+
}
35+
36+
.login-link-text {
37+
text-decoration: none;
38+
}
39+
40+
.accounts-dialog > .login-close-text {
41+
display: none;
42+
}
43+
44+
.accounts-dialog .login-button-form-submit {
45+
margin-top: 12px;
46+
}
47+
.accounts-dialog .login-button {
48+
margin-bottom: 6px;
49+
}
50+
}
51+
</style>

importmap.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
const isDev = location.host.includes('localhost')
3-
const meteorRoot = isDev ? 'http://localhost:8765' : 'https://lume.io'
3+
const mainOrigin = (globalThis.mainOrigin = isDev ? 'http://localhost:8765' : 'https://lume.io')
44

55
const script = document.currentScript
66
// F.e. the "../../" in "src="../../importmap.js"
@@ -92,14 +92,17 @@
9292
'@solid-primitives/utils/immutable': './modules/@solid-primitives/utils/dist/immutable/index.js',
9393

9494
// Meteor
95-
'meteor/meteor': meteorRoot + '/meteor-packages.js',
96-
'meteor/tracker': meteorRoot + '/meteor-packages.js',
97-
'meteor/blaze': meteorRoot + '/meteor-packages.js',
98-
'meteor/templating': meteorRoot + '/meteor-packages.js',
99-
'meteor/mongo': meteorRoot + '/meteor-packages.js',
100-
'meteor/session': meteorRoot + '/meteor-packages.js',
101-
'meteor/reactive-var': meteorRoot + '/meteor-packages.js',
102-
'meteor/accounts-base': meteorRoot + '/meteor-packages.js',
95+
'meteor/meteor': mainOrigin + '/meteor-packages.js',
96+
'meteor/tracker': mainOrigin + '/meteor-packages.js',
97+
'meteor/blaze': mainOrigin + '/meteor-packages.js',
98+
'meteor/templating': mainOrigin + '/meteor-packages.js',
99+
'meteor/mongo': mainOrigin + '/meteor-packages.js',
100+
'meteor/session': mainOrigin + '/meteor-packages.js',
101+
'meteor/reactive-var': mainOrigin + '/meteor-packages.js',
102+
'meteor/accounts-base': mainOrigin + '/meteor-packages.js',
103+
104+
// For easily importing frontend files from the main site.
105+
'lume.io/': mainOrigin + '/',
103106
}
104107

105108
// Map relative imports to the base URL, so that examples in deeper folders work.

index.html

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,18 @@
5757

5858
<link rel="stylesheet" href="/styles/index.css" />
5959

60+
<script src="/importmap.js"></script>
61+
6062
<!-- Connect the static docs site to the lume.io's Meteor server. -->
61-
<script src="./load-meteor.js"></script>
63+
<script src="/load-meteor.js"></script>
6264
</head>
6365
<body class="line-numbers">
6466
<div id="app"></div>
6567

6668
<script src="/docsify.config.js"></script>
6769

68-
<!-- <script src="/modules/docsify/lib/docsify.min.js"></script> -->
69-
<script src="/modules/docsify/lib/docsify.js"></script>
70+
<script src="/modules/docsify/lib/docsify.min.js"></script>
71+
<!-- <script src="/modules/docsify/lib/docsify.js"></script> -->
7072
<!-- TODO FIXME emoji plugin doesn't seem to do anything. -->
7173
<!-- <script src="/modules/docsify/lib/plugins/emoji.min.js"></script> -->
7274
<script src="/modules/docsify/lib/plugins/search.min.js"></script>
@@ -88,21 +90,11 @@
8890
<script>
8991
document.write(/*html*/ `<base href="${location.origin}" />`)
9092
</script>
91-
<script src="./importmap.js"></script>
93+
9294
<script type="module">
9395
import 'lume'
9496
import '@lume/live-code'
97+
import 'lume.io/elements/BlazeComponent.js'
9598
</script>
96-
97-
<blaze-component id="loginButtons" tmpl="loginButtons" data='{"align": "right"}'></blaze-component>
98-
<style>
99-
blaze-component {
100-
display: block;
101-
position: absolute;
102-
top: 0;
103-
right: 0;
104-
z-index: 888;
105-
}
106-
</style>
10799
</body>
108100
</html>

load-meteor-auth.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import {Accounts} from 'meteor/accounts-base'
2+
3+
/** The main origin is where the Meteor server is hosted. */
4+
const mainOriginFrame = document.createElement('iframe')
5+
mainOriginFrame.style.display = 'none'
6+
mainOriginFrame.src = mainOrigin
7+
8+
async function getLoginCredentials() {
9+
document.body.append(mainOriginFrame)
10+
11+
const ctrl = new AbortController()
12+
let gotCredentials = false
13+
14+
// listen for credentials message
15+
window.addEventListener(
16+
'message',
17+
event => {
18+
if (event.data.type === 'loginCredentials') {
19+
gotCredentials = true
20+
ctrl.abort()
21+
if (!event.data.token) return
22+
localStorage.setItem('Meteor.loginToken', event.data.token)
23+
localStorage.setItem('Meteor.loginTokenExpires', event.data.expires)
24+
localStorage.setItem('Meteor.userId', event.data.userId)
25+
}
26+
},
27+
{signal: ctrl.signal},
28+
)
29+
30+
await new Promise(resolve => {
31+
mainOriginFrame.addEventListener(
32+
'load',
33+
async () => {
34+
while (!gotCredentials) {
35+
// Post a message to the iframe to get credentials.
36+
mainOriginFrame.contentWindow.postMessage({type: 'getLoginCredentials'}, {targetOrigin: '*'})
37+
await new Promise(resolve => setTimeout(resolve, 50))
38+
}
39+
40+
resolve()
41+
},
42+
{once: true},
43+
)
44+
})
45+
46+
mainOriginFrame.remove()
47+
}
48+
49+
async function setLoginCredentials(token) {
50+
document.body.append(mainOriginFrame)
51+
52+
const ctrl = new AbortController()
53+
let confirmed = false
54+
55+
window.addEventListener(
56+
'message',
57+
event => {
58+
if (event.data.type === 'confirmSetLoginCredentials') {
59+
console.log('############ login credentials were received by main origin')
60+
confirmed = true
61+
ctrl.abort()
62+
}
63+
},
64+
{signal: ctrl.signal},
65+
)
66+
67+
await new Promise(resolve => {
68+
mainOriginFrame.addEventListener(
69+
'load',
70+
async () => {
71+
while (!confirmed) {
72+
// Post a message to the iframe to set the login token.
73+
mainOriginFrame.contentWindow.postMessage({type: 'setLoginCredentials', token}, {targetOrigin: '*'})
74+
await new Promise(resolve => setTimeout(resolve, 50))
75+
}
76+
77+
resolve()
78+
},
79+
{once: true},
80+
)
81+
})
82+
83+
mainOriginFrame.remove()
84+
}
85+
86+
setInterval(async () => {
87+
if (!localStorage.getItem('Meteor.loginToken')) await getLoginCredentials()
88+
}, 3000)
89+
90+
// Ensure that if we log in here we set the login token in the main origin
91+
// so we're automatically logged in there too.
92+
Accounts.onLogin(async () => {
93+
const token = localStorage.getItem('Meteor.loginToken')
94+
if (!token) throw new Error('token missing')
95+
96+
await setLoginCredentials(token)
97+
})

load-meteor.js

Lines changed: 8 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,22 @@
1919
* using a script tag with type="module".
2020
* - When packages are added or removed from the server, follow these steps
2121
* again to ensure that the list of scripts and links here is up to date.
22-
* - Add postMessage code to communicate with the main origin (where the server
23-
* is hosted) via iframe to get the login credentials, and set them in
24-
* localStorage to log ourselves in on the newly attached client. Note, set CORS
25-
* headers in the meteor server for security to allow only your own domains to
26-
* access the main origin in an iframe, otherwise anyone can use an iframe to
27-
* get your credentials on any website you visit.
22+
* - Add postMessage code (load-meteor-auth.js) to communicate with the main
23+
* origin (where the server is hosted) via iframe to get the login credentials,
24+
* and set them in localStorage to log ourselves in on the newly attached
25+
* client. Note, set CORS headers in the meteor server for security to allow
26+
* only your own domains to access the main origin in an iframe, otherwise
27+
* anyone can use an iframe to get your credentials on any website you visit.
2828
*/
2929

3030
{
31-
const isDev = location.host.includes('localhost')
32-
const mainOrigin = isDev ? 'http://localhost:8765' : 'https://lume.io'
33-
3431
__meteor_runtime_config__ = JSON.parse(
3532
decodeURIComponent(
3633
'%7B%22meteorRelease%22%3A%22METEOR%403.1.2%22%2C%22gitCommitHash%22%3A%227d31a24753d18307d7bc7f56adc080a3fc86b3b5%22%2C%22meteorEnv%22%3A%7B%22NODE_ENV%22%3A%22production%22%2C%22TEST_METADATA%22%3A%22%7B%7D%22%7D%2C%22PUBLIC_SETTINGS%22%3A%7B%7D%2C%22debug%22%3Afalse%2C%22ROOT_URL%22%3A%22https%3A%2F%2Flume-io-20950.nodechef.com%2F%22%2C%22ROOT_URL_PATH_PREFIX%22%3A%22%22%2C%22reactFastRefreshEnabled%22%3Atrue%2C%22autoupdate%22%3A%7B%22versions%22%3A%7B%22web.browser%22%3A%7B%22version%22%3A%22465660ba89c48b54b5ea176a5beefeab8c2947e5%22%2C%22versionRefreshable%22%3A%221952018619999f014765d73c14db1f446971e849%22%2C%22versionNonRefreshable%22%3A%22465660ba89c48b54b5ea176a5beefeab8c2947e5%22%2C%22versionReplaceable%22%3A%221952018619999f014765d73c14db1f446971e849%22%7D%2C%22web.browser.legacy%22%3A%7B%22version%22%3A%227e45b3eb2b7c0bb2dba58ca7ed0a0b0d218bfced%22%2C%22versionRefreshable%22%3A%221952018619999f014765d73c14db1f446971e849%22%2C%22versionNonRefreshable%22%3A%227e45b3eb2b7c0bb2dba58ca7ed0a0b0d218bfced%22%2C%22versionReplaceable%22%3A%221952018619999f014765d73c14db1f446971e849%22%7D%7D%2C%22autoupdateVersion%22%3Anull%2C%22autoupdateVersionRefreshable%22%3Anull%2C%22autoupdateVersionCordova%22%3Anull%2C%22appId%22%3A%22q04iv5yj40nv1s0iw0f%22%7D%2C%22appId%22%3A%22q04iv5yj40nv1s0iw0f%22%2C%22isModern%22%3Atrue%7D',
3734
),
3835
)
3936

37+
// mainOrigin is defined in importmap.js
4038
__meteor_runtime_config__.DDP_DEFAULT_CONNECTION_URL = mainOrigin
4139
__meteor_runtime_config__.ROOT_URL = mainOrigin
4240

@@ -114,48 +112,6 @@
114112
<script type="text/javascript" src="${mainOrigin}/packages/launch-screen.js?hash=${cacheBust}"></script>
115113
<script type="text/javascript" src="${mainOrigin}/global-imports.js?hash=${cacheBust}"></script>
116114
117-
<script type="module">
118-
const mainOrigin = '${mainOrigin}'
119-
120-
if (!localStorage.getItem('Meteor.loginToken')) {
121-
const iframe = document.createElement('iframe')
122-
iframe.style.display = 'none'
123-
iframe.src = mainOrigin
124-
console.log('iframe src', iframe.src, mainOrigin)
125-
document.body.append(iframe)
126-
127-
// listen for credentials message
128-
window.addEventListener('message', event => {
129-
if (event.data.type === 'loginCredentials') {
130-
console.log('received credentials', event.data)
131-
localStorage.setItem('Meteor.loginToken', event.data.token)
132-
localStorage.setItem('Meteor.loginTokenExpires', event.data.expires)
133-
localStorage.setItem('Meteor.userId', event.data.userId)
134-
}
135-
})
136-
137-
await new Promise(resolve => {
138-
iframe.addEventListener('load', async () => {
139-
while (!localStorage.getItem('Meteor.loginToken')) {
140-
// Post a message to the iframe to get credentials.
141-
console.log('post message for credentials')
142-
//iframe.contentWindow.postMessage( { type: 'getLoginCredentials' }, {targetOrigin: mainOrigin})
143-
iframe.contentWindow.postMessage( { type: 'getLoginCredentials' }, {targetOrigin: '*'})
144-
//iframe.contentWindow.postMessage( { type: 'getLoginCredentials' } )
145-
await new Promise(resolve => setTimeout(resolve, 50))
146-
}
147-
148-
resolve()
149-
})
150-
})
151-
152-
iframe.src = ''
153-
iframe.remove()
154-
}
155-
156-
// This includes imports such as the <blaze-component> element.
157-
await import ('${mainOrigin}/entry.js')
158-
159-
</script>
115+
<script type="module" src="/load-meteor-auth.js"></script>
160116
`)
161117
}

0 commit comments

Comments
 (0)