diff --git a/README.md b/README.md index 2e0ee82a..e4a4ed01 100644 --- a/README.md +++ b/README.md @@ -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) + diff --git a/components/InstallModal.js b/components/InstallModal.js index cc2f9369..58834f5f 100644 --- a/components/InstallModal.js +++ b/components/InstallModal.js @@ -1,3 +1,5 @@ +import selectText from '../lib/select-text' + export default class extends React.Component { componentDidUpdate(prevProps) { if (prevProps.isOpen === this.props.isOpen) { @@ -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') } @@ -26,7 +29,13 @@ export default class extends React.Component { Use the hyper command, bundled with your Hyper app, to install {this.props.name} by entering the following into Hyper:

-
hyper i {this.props.name}
+
 {
+              this.installCode = pre
+            }}
+          >
+            hyper i {this.props.name}
+          
diff --git a/components/PluginInfo.js b/components/PluginInfo.js index 27c4b5eb..70e8623d 100644 --- a/components/PluginInfo.js +++ b/components/PluginInfo.js @@ -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 }) => ( +
+ {children} + + +
+) + +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({ @@ -38,47 +77,98 @@ export default class extends React.Component { render() { const { plugin } = this.props + if (this.state && (!this.state.plugin || !this.state.plugin.collected)) { + return ( + + + + + {this.state.isPluginLoading ? ( + Loading plugin information... + ) : ( + + We can't currently find information for this extension 😰 + + )} +   + +
View source code + + + Install + + + + + + ) + } + return ( -
+
- {plugin.collected.metadata.publisher.username} + + {this.state.plugin.collected.metadata.publisher.username} +
- {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 - {plugin.collected.metadata.links.repository && ( + {this.state.plugin.collected.metadata.links.repository && ( )} View source code
- Version {plugin.collected.metadata.version} + Version {this.state.plugin.collected.metadata.version}
@@ -86,21 +176,6 @@ export default class extends React.Component { -
+
) } diff --git a/lib/get-plugin.js b/lib/get-plugin.js index 76b505aa..6c528984 100644 --- a/lib/get-plugin.js +++ b/lib/get-plugin.js @@ -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, diff --git a/lib/gtag.js b/lib/gtag.js index ab22eb7d..a0180d11 100644 --- a/lib/gtag.js +++ b/lib/gtag.js @@ -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, diff --git a/lib/select-text.js b/lib/select-text.js new file mode 100644 index 00000000..40e7024d --- /dev/null +++ b/lib/select-text.js @@ -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() +} diff --git a/package.json b/package.json index bd8081f4..2650cf52 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pages/plugin.js b/pages/plugin.js index 4aeae809..f60029f4 100644 --- a/pages/plugin.js +++ b/pages/plugin.js @@ -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() { @@ -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 ( @@ -62,11 +55,8 @@ export default class extends React.Component { {typeof window === 'object' ? ( ) : null} - - + +
diff --git a/pages/source.js b/pages/source.js index cf8f9144..50309464 100644 --- a/pages/source.js +++ b/pages/source.js @@ -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`, {}, diff --git a/plugins.json b/plugins.json index c8f9571a..ad94322a 100644 --- a/plugins.json +++ b/plugins.json @@ -267,6 +267,28 @@ ], "dateAdded": "1524007869655" }, + { + "name": "hyper-oceanic-next", + "description": "Oceanic Next theme for Hyper", + "type": "theme", + "preview": "https://user-images.githubusercontent.com/2156395/39155663-d2a2c972-474a-11e8-9dc4-59e52ab0365f.png", + "colors": [ + "#ec5f67", + "#99c794", + "#fac863", + "#6699cc", + "#c594c5", + "#5fb3b3" + ], + "dateAdded": "1524521526149" + }, + { + "name": "hyper-savetext", + "description": "Save text from your Hyper terminal to a file", + "type": "plugin", + "preview": "https://raw.githubusercontent.com/neil-orans/hyper-savetext/master/screenshots/hyperstore-bg-image.png", + "dateAdded": "1524611024916" + }, { "name": "hyper-relaxed", "description": "A theme to take a more relaxed view of things.",