Skip to content

Commit a0353be

Browse files
authored
Add status bar to bottom of screen during develop (#14874)
* Add status bar to bottom of screen during develop This is a simple start but we'll be adding more things to the status bar over the next few days. * Remove commented out code * Comments and tweaks * Add comment * Make stage name more explicit & don't clear screen for now
1 parent 8457e70 commit a0353be

File tree

4 files changed

+111
-2
lines changed

4 files changed

+111
-2
lines changed

packages/gatsby-cli/src/reporter/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ const reporter: Reporter = {
179179
span,
180180
}
181181
},
182+
// Make private as we'll probably remove this in a future refactor.
183+
_setStage(stage) {
184+
if (reporterInstance.setStage) {
185+
reporterInstance.setStage(stage)
186+
}
187+
},
182188
}
183189

184190
console.log = (...args) => reporter.log(util.format(...args))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React, { useContext, useState, useEffect, useRef } from "react"
2+
import { Box, Color, StdoutContext } from "ink"
3+
4+
// Handy hook from https://overreacted.io/making-setinterval-declarative-with-react-hooks/
5+
function useInterval(callback, delay) {
6+
const savedCallback = useRef()
7+
8+
// Remember the latest callback.
9+
useEffect(() => {
10+
savedCallback.current = callback
11+
}, [callback])
12+
13+
// Set up the interval.
14+
useEffect(() => {
15+
function tick() {
16+
savedCallback.current()
17+
}
18+
if (delay !== null) {
19+
let id = setInterval(tick, delay)
20+
return () => clearInterval(id)
21+
}
22+
23+
return null
24+
}, [delay])
25+
}
26+
27+
// Track the width and height of the terminal. Responsive app design baby!
28+
const useTerminalResize = () => {
29+
const { stdout } = useContext(StdoutContext)
30+
const [sizes, setSizes] = useState([stdout.columns, stdout.rows])
31+
useEffect(() => {
32+
stdout.on(`resize`, () => {
33+
setSizes([stdout.columns, stdout.rows])
34+
})
35+
return () => {
36+
stdout.off(`resize`)
37+
}
38+
}, [stdout])
39+
40+
return sizes
41+
}
42+
43+
// Query the site's graphql instance for the latest count.
44+
const fetchPageQueryCount = url =>
45+
fetch(`${url}___graphql`, {
46+
method: `post`,
47+
body: JSON.stringify({
48+
query: `query MyQuery {
49+
allSitePage {
50+
totalCount
51+
}
52+
}`,
53+
}),
54+
headers: { "Content-Type": `application/json` },
55+
})
56+
.then(res => res.json())
57+
.then(json => json.data.allSitePage.totalCount)
58+
59+
const Develop = props => {
60+
const [pagesCount, setPagesCount] = useState(0)
61+
62+
fetchPageQueryCount(props.stage.context.url).then(count =>
63+
setPagesCount(count)
64+
)
65+
// Query for latest page count every second.
66+
// Built-in subscriptions would be nice.
67+
useInterval(() => {
68+
// POST to get pages count.
69+
fetchPageQueryCount(props.stage.context.url).then(count =>
70+
setPagesCount(count)
71+
)
72+
}, 1000)
73+
74+
const [width] = useTerminalResize()
75+
76+
return (
77+
<Box flexDirection="column" marginTop={2}>
78+
<Box textWrap={`truncate`}>{`—`.repeat(width)}</Box>
79+
<Box height={1} flexDirection="row">
80+
<Color>{pagesCount} pages</Color>
81+
<Box flexGrow={1} />
82+
<Color>{props.stage.context.appName}</Color>
83+
</Box>
84+
</Box>
85+
)
86+
}
87+
88+
export default Develop

packages/gatsby-cli/src/reporter/reporters/ink/reporter.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Static, Box } from "ink"
33
import chalk from "chalk"
44
import Spinner from "./components/spinner"
55
import ProgressBar from "./components/progress-bar"
6+
import Develop from "./components/develop"
67
import { Message } from "./components/messages"
78
import isTTY from "../../../util/is-tty"
89
import calcElapsedTime from "../../../util/calc-elapsed-time"
@@ -32,10 +33,15 @@ export default class GatsbyReporter extends React.Component {
3233
verbose: false,
3334
messages: [],
3435
activities: {},
36+
stage: { stage: `init`, context: {} },
3537
}
3638

3739
format = chalk
3840

41+
setStage = stage => {
42+
this.setState({ stage })
43+
}
44+
3945
createActivity = ({ id, ...options }) => {
4046
this.setState(state => {
4147
return {
@@ -122,7 +128,7 @@ export default class GatsbyReporter extends React.Component {
122128
}
123129

124130
render() {
125-
const { activities, messages, disableColors } = this.state
131+
const { activities, messages, disableColors, stage } = this.state
126132

127133
const spinners = []
128134
const progressBars = []
@@ -165,6 +171,9 @@ export default class GatsbyReporter extends React.Component {
165171
/>
166172
))}
167173
</Box>
174+
{stage.stage === `DevelopBootstrapFinished` && (
175+
<Develop stage={stage} />
176+
)}
168177
</Box>
169178
)
170179
}

packages/gatsby/src/commands/develop.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,13 @@ module.exports = async (program: any) => {
428428
}
429429

430430
function printInstructions(appName, urls, useYarn) {
431-
console.log()
431+
report._setStage({
432+
stage: `DevelopBootstrapFinished`,
433+
context: {
434+
url: urls.localUrlForBrowser,
435+
appName,
436+
},
437+
})
432438
console.log(`You can now view ${chalk.bold(appName)} in the browser.`)
433439
console.log()
434440

0 commit comments

Comments
 (0)