Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
* master:
  Add hyper-savetext to Hyper store (vercel#29)
  Update readme
  Fix bug when trying to access props instead of state
  Add hyper-oceanic-next theme (vercel#44)
  Auto select install code iwhen InstallModal opens (vercel#38)
  1.2.0
  Fix install modal
  Only try to load plugin data from npms where needed
  Fix content not displaying if npms.io is down

# Conflicts:
#	plugins.json
  • Loading branch information
mischah committed Apr 25, 2018
2 parents 4a33788 + 318c5b2 commit f5fe087
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 58 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,22 @@
[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/hyper)

The official website for the Hyper terminal

## Contribution

Want to submit a plugin or theme to the Hyper Store? Follow [this wiki guide](https://github.com/zeit/hyper-site/wiki/Submitting-a-new-plugin-or-theme-to-Hyper-Store).

To submit a feature, bug fix, or enhancement to the Hyper website proceed as follows:

1. Clone this repo
2. Within your terminal, run `yarn` to install the dependencies
3. Once the dependencies are installed, run `yarn dev` to start the dev server on `localhost:3000`

We really appreciate any contribution

## Related Repositories

- [Hyper](https://github.com/zeit/hyper)
- [Sample Plugin](https://github.com/zeit/hyperpower)
- [Sample Theme](https://github.com/zeit/hyperyellow)

11 changes: 10 additions & 1 deletion components/InstallModal.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import selectText from '../lib/select-text'

export default class extends React.Component {
componentDidUpdate(prevProps) {
if (prevProps.isOpen === this.props.isOpen) {
Expand All @@ -8,6 +10,7 @@ export default class extends React.Component {

if (this.props.isOpen === true) {
body.classList.add('has-modal-open')
selectText(this.installCode)
} else {
body.classList.remove('has-modal-open')
}
Expand All @@ -26,7 +29,13 @@ export default class extends React.Component {
Use the <code>hyper</code> command, bundled with your Hyper app, to
install {this.props.name} by entering the following into Hyper:
</p>
<pre>hyper i {this.props.name}</pre>
<pre
ref={pre => {
this.installCode = pre
}}
>
hyper i {this.props.name}
</pre>
<a
href="https://github.com/zeit/hyper-plugins/wiki/Security-and-Hyper-plugins"
target="_blank"
Expand Down
6 changes: 0 additions & 6 deletions components/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class Layout extends React.Component {

componentWillReceiveProps(nextProps) {
const { router } = nextProps
console.log(router.asPath)
if (!/^\/search/.exec(router.asPath)) {
this.setState({
searchQuery: null,
Expand Down Expand Up @@ -64,11 +63,6 @@ class Layout extends React.Component {
}

render() {
console.log(
this.state && this.state.searchQuery,
this.props.query,
this.props.router
)
return (
<div className="main">
<Meta />
Expand Down
135 changes: 105 additions & 30 deletions components/PluginInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,65 @@ import Gravatar from 'react-gravatar'
import Link from 'next/link'
import InstallModal from './InstallModal'
import GithubIcon from '../static/github-icon.svg'
import getPluginInfo from '../lib/get-plugin.js'
import * as gtag from '../lib/gtag'

export default class extends React.Component {
export const PluginInfoBar = ({ children }) => (
<div className="plugin-info">
{children}

<style jsx>{`
.plugin-info {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
max-width: 980px;
width: 100%;
background: black;
height: 6.4rem;
display: flex;
align-items: center;
font-size: 1.2rem;
padding: 0 40px;
}
`}</style>
</div>
)

export default class PluginInfo extends React.Component {
constructor() {
super()

this.state = {
isModalOpen: false
isModalOpen: false,
isPluginLoading: true
}

this.openInstallModal = this.openInstallModal.bind(this)
this.closeInstallModal = this.closeInstallModal.bind(this)
}

async componentDidMount() {
const plugin = await getPluginInfo(this.props.plugin.name)

if (plugin !== undefined) {
await this.setState({
plugin
})
}

this.setState({
isPluginLoading: false
})
}

openInstallModal() {
gtag.event({
action: 'Opened install modal',
category: 'plugin',
label: 'open_install_modal',
value: this.props.plugin.meta.name
value: this.props.plugin.name
})

this.setState({
Expand All @@ -38,69 +77,105 @@ export default class extends React.Component {
render() {
const { plugin } = this.props

if (this.state && (!this.state.plugin || !this.state.plugin.collected)) {
return (
<React.Fragment>
<InstallModal
name={plugin.name}
isOpen={this.state.isModalOpen}
closeModal={this.closeInstallModal}
/>

<PluginInfoBar>
{this.state.isPluginLoading ? (
<span>Loading plugin information...</span>
) : (
<span>
We can't currently find information for this extension 😰
</span>
)}
&nbsp;
<Link
href={`/source?id=${plugin.name}`}
as={`/plugins/${plugin.name}/source`}
>
<a className="plugin-info__link">View source code</a>
</Link>
<a className="plugin-info__install" onClick={this.openInstallModal}>
Install
</a>
</PluginInfoBar>

<style jsx>{`
.plugin-info__install {
cursor: pointer;
border-radius: 2px;
background: white;
color: black;
padding: 0 16px;
margin-left: auto;
opacity: 1;
transition: opacity 0.2s ease;
}
.plugin-info__install:hover {
opacity: 0.9;
}
`}</style>
</React.Fragment>
)
}

return (
<React.Fragment>
<InstallModal
name={plugin.meta.name}
name={plugin.name}
isOpen={this.state.isModalOpen}
closeModal={this.closeInstallModal}
/>

<div className="plugin-info">
<PluginInfoBar>
<div className="plugin-info__author border-followed">
<Gravatar
className="plugin-info__avatar"
email={plugin.collected.metadata.publisher.email}
email={this.state.plugin.collected.metadata.publisher.email}
/>
<span>{plugin.collected.metadata.publisher.username}</span>
<span>
{this.state.plugin.collected.metadata.publisher.username}
</span>
</div>

<span className="plugin-info__downloads border-followed">
{plugin.collected.npm.downloads[2].count.toLocaleString()} downloads
in the last month
{this.state.plugin.collected.npm.downloads[2].count.toLocaleString()}{' '}
downloads in the last month
</span>

{plugin.collected.metadata.links.repository && (
{this.state.plugin.collected.metadata.links.repository && (
<a
className="plugin-info__github-link"
target="_blank"
href={plugin.collected.metadata.links.repository}
href={this.state.plugin.collected.metadata.links.repository}
>
<GithubIcon />
</a>
)}

<Link
href={`/source?id=${plugin.collected.metadata.name}`}
as={`/plugins/${plugin.collected.metadata.name}/source`}
href={`/source?id=${this.state.plugin.collected.metadata.name}`}
as={`/plugins/${this.state.plugin.collected.metadata.name}/source`}
>
<a className="plugin-info__link">View source code</a>
</Link>

<div className="plugin-info__version">
Version {plugin.collected.metadata.version}
Version {this.state.plugin.collected.metadata.version}
</div>

<a className="plugin-info__install" onClick={this.openInstallModal}>
Install
</a>

<style jsx>{`
.plugin-info {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
max-width: 980px;
width: 100%;
background: black;
height: 6.4rem;
display: flex;
align-items: center;
font-size: 1.2rem;
padding: 0 40px;
}
.plugin-info__author {
display: flex;
align-items: center;
Expand Down Expand Up @@ -213,7 +288,7 @@ export default class extends React.Component {
}
}
`}</style>
</div>
</PluginInfoBar>
</React.Fragment>
)
}
Expand Down
12 changes: 10 additions & 2 deletions lib/get-plugin.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import cachedFetch from './cached-json-fetch'
import plugins from '../plugins.json'

export default async name => {
const result = await cachedFetch(`https://api.npms.io/v2/package/${name}`)
export default async (name, { meta = false } = { meta }) => {
const plugin = plugins.find(plugin => plugin.name === name)
let result = {}

if (!meta) {
try {
result = await cachedFetch(`https://api.npms.io/v2/package/${name}`)
} catch (err) {
console.error('Failed to recieve package information from npms.io', err)
}
}

return {
...result,
Expand Down
1 change: 0 additions & 1 deletion lib/gtag.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const pageview = url => {
}

export const event = ({ action, category, label, value }) => {
console.log(action, category, label, value)
window.gtag('event', action, {
event_category: category,
event_label: label,
Expand Down
18 changes: 18 additions & 0 deletions lib/select-text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function selectText(element) {
let range
let selection
if (document.body.createTextRange) {
//ms
range = document.body.createTextRange()
range.moveToElementText(element)
range.select()
} else if (window.getSelection) {
//all others
selection = window.getSelection()
range = document.createRange()
range.selectNodeContents(element)
selection.removeAllRanges()
selection.addRange(range)
}
return selection.toString() || range.toString()
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hyper-site",
"private": true,
"version": "1.1.2",
"version": "1.2.0",
"description": "The official website for the Hyper terminal",
"repository": "zeit/hyper-site",
"license": "MIT",
Expand Down
22 changes: 6 additions & 16 deletions pages/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@ export default class extends React.Component {
static async getInitialProps({ query: { id } }) {
let plugin

try {
plugin = await getPluginInfo(id)
} catch (err) {
console.error(err)
}
plugin = await getPluginInfo(id, { meta: true })

if (!plugin.meta || (plugin.code && plugin.code === 'NOT_FOUND')) {
if (!plugin.meta) {
return {}
}

return { plugin }
return { plugin: plugin.meta }
}

render() {
Expand All @@ -45,10 +41,7 @@ export default class extends React.Component {
)
}

const pluginInfo =
this.props.plugin && this.props.plugin.meta
? this.props.plugin.meta
: null
const pluginInfo = this.props.plugin

return (
<Layout>
Expand All @@ -62,11 +55,8 @@ export default class extends React.Component {
{typeof window === 'object' ? (
<meta property="og:url" content={window.location.href} />
) : null}
<meta property="og:image" content={this.props.plugin.meta.preview} />
<meta
property="og:description"
content={this.props.plugin.meta.description}
/>
<meta property="og:image" content={pluginInfo.preview} />
<meta property="og:description" content={pluginInfo.description} />
<meta property="og:site_name" content="Hyper Store" />
</Head>
<div className="plugin">
Expand Down
2 changes: 1 addition & 1 deletion pages/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default class extends React.Component {
let plugin, pluginContents

try {
plugin = await getPackageInfo(id)
plugin = await getPackageInfo(id, { meta: true })
pluginContents = await cachedFetch(
`https://unpkg.com/${id}@latest/?meta`,
{},
Expand Down
Loading

0 comments on commit f5fe087

Please sign in to comment.