Skip to content
This repository has been archived by the owner on Oct 26, 2019. It is now read-only.

Commit

Permalink
Give the ability to update the currently installed plugins.
Browse files Browse the repository at this point in the history
  • Loading branch information
Blaine Schmeisser committed Jul 31, 2016
1 parent 3dda1b1 commit 139a3b4
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 44 deletions.
3 changes: 2 additions & 1 deletion app/blocks/external/serviceScript.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const ExternalBlock = require('../externalBlock')
const freshRequire = require('../../lib/freshRequire.js')

const path = require('path')

Expand All @@ -14,7 +15,7 @@ class ServiceScript extends ExternalBlock {
this.interval = 100
}
try {
const plugin = require(path.join(this.cwd, data.script))
const plugin = freshRequire(path.join(this.cwd, data.script))
const electron = require('electron')
this.script = plugin({
console: this.logger,
Expand Down
3 changes: 2 additions & 1 deletion app/blocks/input/prefixScript.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const InputBlock = require('../inputBlock')
const freshRequire = require('../../lib/freshRequire.js')

const path = require('path')

Expand All @@ -9,7 +10,7 @@ class PrefixScript extends InputBlock {
this.space = data.space
this.args = data.args
try {
const plugin = require(path.join(data.cwd, data.script))
const plugin = freshRequire(path.join(data.cwd, data.script))
const electron = require('electron')
this.script = plugin({
console: this.logger,
Expand Down
3 changes: 2 additions & 1 deletion app/blocks/input/rootScript.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const InputBlock = require('../inputBlock')
const freshRequire = require('../../lib/freshRequire.js')

const path = require('path')

class RootScript extends InputBlock {
constructor (data) {
super(data)
try {
const plugin = require(path.join(data.cwd, data.script))
const plugin = freshRequire(path.join(data.cwd, data.script))
const electron = require('electron')
this.script = plugin({
console: this.logger,
Expand Down
3 changes: 2 additions & 1 deletion app/blocks/output/userScript.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const Block = require('../block')
const freshRequire = require('../../lib/freshRequire.js')

const path = require('path')

class UserScript extends Block {
constructor (data) {
super(data)
try {
const plugin = require(path.join(data.cwd, data.script))
const plugin = freshRequire(path.join(data.cwd, data.script))
const electron = require('electron')
this.script = plugin({
console: this.logger,
Expand Down
8 changes: 7 additions & 1 deletion app/helpers/menu_template.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,18 @@ const trayTemplate = [
},
{ type: 'separator' },
{
label: 'Check for updates...',
label: 'Check for Zazu Updates',
click: () => {
const update = new Update()
update.check(true)
},
},
{
label: 'Update installed Plugins',
click: () => {
globalEmitter.emit('updatePlugins')
},
},
{ type: 'separator' },
{
label: 'Quit',
Expand Down
4 changes: 4 additions & 0 deletions app/lib/freshRequire.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = (path) => {
delete require.cache[path]
return require(path)
}
38 changes: 38 additions & 0 deletions app/lib/git.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const exec = require('child_process').execFile
const which = require('which')

const git = (args, options) => {
return new Promise((resolve, reject) => {
which('git', (err, resolvedPath) => {
if (err) return reject('GIT was not found on your system')
exec(resolvedPath, args, options || {}, (err) => {
err && reject(err) || resolve()
})
})
})
}

const pull = (packagePath) => {
return git(['pull'], { cwd: packagePath }).catch((err) => {
if (err.message.match(/ENOENT/i)) {
throw new Error('Package "' + name + '" is not cloneed')
} else {
throw err
}
})
}

const clone = (name, packagePath) => {
const packageUrl = '[email protected]:' + name + '.git'
return git(['clone', packageUrl, packagePath]).catch((err) => {
if (err.message.match(/already exists/i)) {
return // futher promises will resolve
} else if (err.message.match(/Repository not found/i)) {
throw new Error('Package "' + name + '" does not exist on github')
} else {
throw err
}
})
}

module.exports = { clone, pull, git }
25 changes: 14 additions & 11 deletions app/package.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const clone = require('git-clone')
const { clone, pull } = require('./lib/git')
const path = require('path')
const jetpack = require('fs-jetpack')

Expand All @@ -9,6 +9,7 @@ class Package {
this.path = path.join(configuration.pluginDir, url)
this.url = url
this.clone = clone
this.pull = pull
}

load () {
Expand All @@ -22,17 +23,19 @@ class Package {
})
}

update () {
if (!jetpack.exists(this.path)) {
return Promise.reject('Package' + this.url + ' does not exist')
}
return this.pull(this.path)
}

download () {
return new Promise((resolve, reject) => {
if (jetpack.exists(this.path)) {
return resolve('exists')
}
this.clone('https://github.com/' + this.url, this.path, { shallow: true }, (error) => {
if (error) {
reject(`Package '${this.url}' failed to load.`)
}
resolve('downloaded')
})
if (jetpack.exists(this.path)) {
return Promise.resolve('exists')
}
return this.clone(this.url, this.path).then(() => {
return 'downloaded'
})
}
}
Expand Down
21 changes: 18 additions & 3 deletions app/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,28 @@ class Plugin extends Package {
})
}

update () {
return super.update().then((action) => {
if (action === 'downloaded') {
return npmInstall(this.path)
} else {
return Promise.resolve()
}
})
}

download () {
return super.download().then((action) => {
if (action === 'downloaded') {
return new Promise((resolve, reject) => {
npmInstall(this.path).then(resolve)
})
return npmInstall(this.path)
} else {
return Promise.resolve()
}
}).catch((error) => {
notification.push({
title: 'Plugin failed to download',
message: error.message,
})
})
}

Expand Down
83 changes: 75 additions & 8 deletions app/store/pluginStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,87 @@ const EventEmitter = require('events')

const configuration = require('../configuration')
const Plugin = require('../plugin')
const Theme = require('../theme')
const track = require('../lib/track')
const globalEmitter = require('../lib/globalEmitter')
const notification = require('../lib/notification')

const CHANGE_RESULTS_EVENT = 'results_change'
const CHANGE_QUERY_EVENT = 'query_change'
const CHANGE_THEME_EVENT = 'theme_change'

class PluginStore extends EventEmitter {
constructor () {
super()
this.query = ''
this.results = []
this.plugins = []
globalEmitter.on('updatePlugins', () => {
this.update().then(() => {
return this.load()
})
})
this.load()
}

load () {
configuration.load()
this.plugins = configuration.plugins.map((plugin) => {
this.loadTheme().then(() => {
return this.loadPlugins()
}).then(() => {
notification.push({
title: 'Plugins loaded',
message: 'Your plugins have been loaded',
})
})
}

loadTheme () {
this.theme = new Theme(configuration.theme, configuration.pluginDir)
return this.theme.load().then((theme) => {
track.addPageAction('loadedPackage', {
packageType: 'theme',
packageName: configuration.theme,
})
this.emitThemeChange(theme)
})
}

loadPlugins () {
this.plugins = []
return Promise.all(configuration.plugins.map((plugin) => {
let pluginObj
if (typeof plugin === 'object') {
pluginObj = new Plugin(plugin.name, plugin.variables)
} else {
pluginObj = new Plugin(plugin)
}
pluginObj.load()
return pluginObj
this.plugins.push(pluginObj)
return pluginObj.load().then(() => {
track.addPageAction('loadedPackage', {
packageType: 'plugin',
packageName: pluginObj.id,
})
})
}))
}

update () {
return this.updateTheme().then(() => {
return this.updatePlugins()
})
}

updateTheme () {
return this.theme.update()
}

updatePlugins () {
return Promise.all(this.plugins.map((plugin) => {
return plugin.update()
}))
}

setQuery (query) {
this.query = query
this.emitQueryChange()
Expand All @@ -54,7 +108,7 @@ class PluginStore extends EventEmitter {
this.clearResults()
}
this.results = this.results.concat(results)
this.emitChange()
this.emitResultChange()
}
})
})
Expand All @@ -72,11 +126,23 @@ class PluginStore extends EventEmitter {

clearResults () {
this.results = []
this.emitChange()
this.emitResultChange()
}

emitThemeChange (css) {
this.emit(CHANGE_THEME_EVENT, css)
}

addThemeListener (callback) {
this.on(CHANGE_THEME_EVENT, callback)
}

removeThemeListener (callback) {
this.removeListener(CHANGE_THEME_EVENT, callback)
}

emitQueryChange () {
this.emit(CHANGE_QUERY_EVENT)
this.emit(CHANGE_QUERY_EVENT, this.query)
}

addQueryListener (callback) {
Expand All @@ -87,8 +153,8 @@ class PluginStore extends EventEmitter {
this.removeListener(CHANGE_QUERY_EVENT, callback)
}

emitChange () {
this.emit(CHANGE_RESULTS_EVENT)
emitResultChange () {
this.emit(CHANGE_RESULTS_EVENT, this.results)
}

addResultListener (callback) {
Expand All @@ -101,4 +167,5 @@ class PluginStore extends EventEmitter {
}

var pluginStore = new PluginStore()

module.exports = pluginStore
26 changes: 10 additions & 16 deletions app/zazu.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
const React = require('react')

const Theme = require('./theme')
const configuration = require('./configuration')
const Style = require('./components/style')
const Search = require('./components/search')
const Results = require('./components/results')
const PluginStore = require('./store/pluginStore')
const globalEmitter = require('./lib/globalEmitter')
const ResultSorter = require('./lib/resultSorter')
const track = require('./lib/track')

const Zazu = React.createClass({

Expand All @@ -21,17 +18,7 @@ const Zazu = React.createClass({
},

componentDidMount () {
configuration.load()
track.setAttribute('zazuTheme', configuration.theme)
const theme = new Theme(configuration.theme, configuration.pluginDir)
theme.load().then((theme) => {
this.setState({
theme,
})
})

PluginStore.load()

PluginStore.addThemeListener(this.updateTheme)
PluginStore.addResultListener(this.updateResults)

globalEmitter.on('showWindow', () => {
Expand All @@ -45,11 +32,18 @@ const Zazu = React.createClass({

componentWillUnmount () {
PluginStore.removeResultListener(this.updateResults)
PluginStore.removeThemeListener(this.updateTheme)
},

updateTheme (theme) {
this.setState({
theme,
})
},

updateResults () {
updateResults (results) {
this.setState({
results: new ResultSorter(PluginStore.results).sort(),
results: new ResultSorter(results).sort(),
})
},

Expand Down
Loading

0 comments on commit 139a3b4

Please sign in to comment.