Skip to content

Commit 852e4ac

Browse files
committed
Fix: "Loading..." is no longer stuck as the website title
1 parent 5e0d7a1 commit 852e4ac

3 files changed

Lines changed: 93 additions & 21 deletions

File tree

app/src/extraResources/inject.ts

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ import * as htmlToImage from 'html-to-image'
1212
import fs from 'fs/promises'
1313
import path from 'path'
1414

15+
interface Data {
16+
title: string
17+
favicon: string
18+
}
19+
20+
let data: Data = {
21+
title: '',
22+
favicon: '',
23+
}
24+
1525
if (import.meta.env.MODE === 'development') {
1626
// Ensure that all modules are loaded
1727
console.log('Development mode')
@@ -37,25 +47,87 @@ if (import.meta.env.MODE === 'development') {
3747
* Collect and send back information from the document context
3848
* Only done during the initial bridging
3949
*/
40-
document.addEventListener('DOMContentLoaded', initiateBridge)
50+
document.addEventListener('DOMContentLoaded', init)
51+
// document.addEventListener('load', initiateBridge)
4152

42-
function initiateBridge() {
43-
const data = {
44-
title: document.title,
45-
favicon:
46-
'https://www.google.com/s2/favicons?domain=' + window.location.href,
47-
}
53+
async function init() {
54+
// Communicate back to the Electron app
55+
await initiateBridge()
56+
}
57+
58+
async function getPageData() {
59+
data.title = await getPageTitle()
60+
console.log('Title:', data.title)
4861

62+
data.favicon =
63+
'https://www.google.com/s2/favicons?domain=' + window.location.href
64+
console.log('Favicon:', data.favicon)
65+
}
66+
67+
function getPageTitle(): Promise<string> {
68+
return new Promise(async (resolve, reject) => {
69+
let title: string | undefined = document.title
70+
71+
if (title) {
72+
resolve(title)
73+
} else {
74+
console.log('Waiting for <title> to be added')
75+
76+
// If no title after 15s, just return as empty
77+
const timer = setTimeout(() => {
78+
reject('No title found')
79+
}, 2500)
80+
81+
// Wait for a <title> to be added
82+
const observer = new MutationObserver((mutations) => {
83+
mutations.forEach((mutation) => {
84+
if (!mutation.addedNodes) return
85+
86+
for (let i = 0; i < mutation.addedNodes.length; i++) {
87+
let node = mutation.addedNodes[i]
88+
if (node.nodeName !== 'TITLE') continue
89+
// Only look for <title> node
90+
if (node.nodeName === 'TITLE') {
91+
// Title set!
92+
title = document.title
93+
94+
// Cancel the timer
95+
clearTimeout(timer)
96+
97+
// Kill the observer
98+
observer.disconnect()
99+
100+
// Return the final title
101+
resolve(title)
102+
}
103+
}
104+
})
105+
})
106+
107+
// Watch the <head> for the <title> to be added
108+
observer.observe(document.head, {
109+
childList: true,
110+
subtree: true,
111+
characterData: true,
112+
})
113+
}
114+
})
115+
}
116+
117+
async function initiateBridge() {
49118
// Listen for initial connection to the frame
50-
ipcRenderer.once('bridgeToFrame', (event, args) => {
119+
ipcRenderer.on('bridgeToFrame', async (event, args) => {
51120
// We get the ID of the artboard we're connected to
52121
console.log('Passed from parent:', args)
53122
const { id, syncFns } = args
54123
state.id = id
55124

125+
// Get the page title and favicon
126+
await getPageData()
127+
56128
// Respond to the parent component
57129
ipcRenderer.sendToHost('initiateBridge', data)
58-
document.removeEventListener('DOMContentLoaded', initiateBridge)
130+
// document.removeEventListener('DOMContentLoaded', initiateBridge)
59131

60132
// Run our functions
61133
startSync()

app/src/renderer/components/Screens/WebPage.vue

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
<template>
2-
<webview
3-
ref="frame"
4-
class="frame"
5-
:preload="injectScriptPath"
6-
v-bind="webviewOptions"
7-
:electronConfig="webpreferences"
8-
/>
2+
<webview ref="frame" class="frame" :preload="injectScriptPath" v-bind="webviewOptions"
3+
:electronConfig="webpreferences" />
94
</template>
105

116
<script lang="ts">
@@ -302,8 +297,6 @@ export default {
302297
this.$emit('loadstart') // Show loading spinner
303298
304299
// Change the title to Loading...
305-
// TODO Add a VueX action for this?
306-
307300
const history = useHistoryStore()
308301
history.changeSiteData({
309302
title: 'Loading...',
@@ -347,7 +340,6 @@ export default {
347340
const title = returnedData.title
348341
const favicon = returnedData.favicon
349342
350-
// TODO Add to VueX Action
351343
const history = useHistoryStore()
352344
history.changeSiteData({
353345
title,
@@ -364,6 +356,11 @@ export default {
364356
const frame = this.$refs.frame
365357
this.$emit('loadend') // Hide loading spinner
366358
359+
// Get the final <title> after the page finished loading
360+
frame.send('bridgeToFrame', {
361+
id: this.id,
362+
})
363+
367364
// History
368365
// TODO: webContents.history is no longer around https://github.com/electron/electron/issues/26727
369366
// how should we track the page history?

app/src/renderer/store/history.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ export const useHistoryStore = defineStore('history', {
6666
// This function may be called just to trigger a new URL navigation
6767
// but it can also be called from an <artboard> once it has access to the new URL
6868

69-
// @TODO: Throttle this fn, as it will be called by
70-
// each <webview> when it loads, and doesn't need to keep changing
69+
// TODO: Only log in dev
70+
console.log('Changing site data', val)
7171

72+
// TODO: Each artboard will call this fn right now
73+
// But really we should only update the title once
74+
// We could use a throttle fn, or a debounce fn, but this is also a bit hacky
7275
if (val.title && val.title !== this.currentPage.title) {
7376
this.currentPage.title = val.title
7477
}

0 commit comments

Comments
 (0)