Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image upload #18

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 13 additions & 24 deletions main/create-window.js → main/actions/create-window.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
const { app, BrowserWindow } = require('electron')
const { BrowserWindow } = require('electron')
const { resolve } = require('app-root-path')
const dev = require('electron-is-dev')

const startServer = require('./server')
const setMenu = require('./menu')
const setIPCEvents = require('./ipc-events')

async function createWindow () {
let server

try {
// when starting the window run the server
server = await startServer()
} catch (error) {
console.error(error)
app.exit(error)
}
const setMenu = require('../menu')

async function createWindow (_windows) {
// after the server starts create the electron browser window
global.win = new BrowserWindow({
let win = new BrowserWindow({
title: 'Pulse',
backgroundColor: '#058ecd',
height: 768,
Expand All @@ -32,32 +20,33 @@ async function createWindow () {
textAreasAreResizable: false
}
})
const id = win.id

// open our server URL or the build directory in production
global.win.loadURL(dev ? 'http://localhost:8000' : `file://${resolve('./build')}/index.html`)
win.loadURL(dev ? 'http://localhost:8000' : `file://${resolve('./build')}/index.html`)

// in development open devtools
if (dev) {
global.win.webContents.openDevTools()
win.webContents.openDevTools()
}

global.win.once('ready-to-show', () => {
global.win.show()
win.once('ready-to-show', () => {
win.show()
})

global.win.on('close', () => {
global.win = null
if (server) server.close()
win.on('closed', () => {
_windows.delete(id)
})

setIPCEvents()
setMenu()

// TODO: implement a way to get the Markdown data
// protocol.registerHttpProtocol('pulse', (request, callback) => {
// const url = request.url.substr(8)
// console.log(url)
// })
_windows.set(id, win)
return win
}

module.exports = createWindow
Binary file modified main/assets/icon.icns
Binary file not shown.
Binary file modified main/assets/icon.ico
Binary file not shown.
Binary file modified main/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 35 additions & 7 deletions main/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
const WindowManager = require('./window-manager')
const { app } = require('electron')

const createWindow = require('./create-window')
const dev = require('electron-is-dev')
const startServer = require('./server')
const setIPCEvents = require('./ipc-events')

app.on('ready', createWindow)
class Main {
constructor () {
this.server = null
this._windowManager = new WindowManager()
}
get windowManager () {
return this._windowManager
}

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
async onReady () {
if (dev) {
try {
this.server = await startServer()
} catch (error) {
console.error(error)
app.exit(error)
}
}
this._windowManager.createNewWindow()
}

onWindowAllClosed () {
app.quit()
}
}
const main = new Main()

app.once('ready', () => {
main.onReady()
setIPCEvents()
})

app.on('activate', () => {
if (!global.win) {
createWindow()
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
main.onWindowAllClosed()
}
if (this.server) this.server.close()
})
12 changes: 11 additions & 1 deletion main/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ const template = [
}
}
},
{
label: 'New window',
accelerator: 'CmdOrCtrl+Alt+N',
click () {
const webContent = webContents.getFocusedWebContents()
if (webContent) {
webContent.send('shortcut-press')
}
}
},
{
label: 'Open...',
accelerator: 'CmdOrCtrl+O',
Expand All @@ -29,7 +39,7 @@ const template = [
{
label: 'Save file',
accelerator: 'CmdOrCtrl+S',
click() {
click () {
const webContent = webContents.getFocusedWebContents()
if (webContent) {
webContent.send('trying-to-save')
Expand Down
27 changes: 27 additions & 0 deletions main/window-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { ipcMain, BrowserWindow } = require('electron')
const createWindow = require('./actions/create-window')

class WindowManager {
constructor () {
this._windows = new Map()
ipcMain.on('create-new-window', this._onRequestCreateNewWindow.bind(this))
}

reload () {
const w = BrowserWindow.getFocusedWindow()
if (w) {
w.reload()
}
}

createNewWindow (value = '', fileName = undefined) {
createWindow(this._windows, value, fileName)
}

_onRequestCreateNewWindow (event) {
this.createNewWindow()
event.sender.send('created-new-window')
}
}

module.exports = WindowManager
57 changes: 57 additions & 0 deletions renderer/components/image-drop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// validate file format with a list of format supports imgur
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole file is not a component, is a lib, move it to another directory.

let validateFile = (file) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

let imageFormat = ['jpeg', 'png', 'gif', 'peg', 'apng', 'tiff', 'pdf', 'xcf']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

return imageFormat.filter((kind) => {
let res = new RegExp("\\b(" + kind + ")\\b")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

return res.test(file.type)
})
}

// send file via XMLHTTP
let sendData = (_this, file) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

let fd = new FormData()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

Be explicit, use formData not fd, fd doesn't say anything about what's inside

fd.append('image', file)
let xhttp = new XMLHttpRequest()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

Use Fetch API not XMLHttpRequest

xhttp.open('POST', 'https://api.imgur.com/3/image', true)
xhttp.setRequestHeader('Authorization', `Client-ID e3f6a51d5c12580`)
xhttp.onreadystatechange = function () {
let response = ''
let event = {}
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 300) {
try {
response = JSON.parse(this.responseText)
} catch (err) {
response = this.responseText;
}
event.target = {
value: `${_this.editor.domField.value} ![${file.name}](${response.data.link})`
}
// write response on editor
_this.editor.writeValue(event)
} else {
throw new Error(this.status + " - " + this.statusText)
}
}
}
xhttp.send(fd)
xhttp = null
}

let imageDrop = (e, _this) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

// without 'preventDefault', when you drop the image, change the whole editor view
e.preventDefault()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be explicit, use event not e, it doesn't say anything about what is inside

let event = {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

let file = e.dataTransfer.files[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

let valido = validateFile(file)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use const, only use let if you realize you need to change this variable later (tip: never do it, use immutable code)

Code in english

if (!!valido && valido.length !== 0) {
sendData(_this, file)
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use else, just return inside the if

event.target = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid mutations

value: `${_this.editor.domField.value} ![Problem with the format file](url)`
}
// if file format doesn't support by imgur, advice the user
_this.editor.writeValue(event)
}
}
export default imageDrop
48 changes: 48 additions & 0 deletions renderer/components/window-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { Component } from 'react'
import { Base } from 'pulse-editor/buttons'
import { ipcRenderer } from 'electron'
import { func } from 'prop-types'
import isMac from 'pulse-editor/built/utils/is-mac'
import Icon from 'react-icons/lib/fa/plus-circle'

export default class CreateButton extends Component {
static contextTypes = {
setShortcut: func.isRequired,
removeShortcut: func.isRequired,
writeValue: func.isRequired,
setFileName: func.isRequired
}

componentDidMount () {
ipcRenderer.on('shortcut-press', this.createWindow)
this.context.setShortcut({
ctrlKey: !isMac(),
metaKey: isMac(),
altKey: true,
shiftKey: false,
keyName: 'n',
updater: selected => selected,
handler: event => {
this.createWindow()
return event.selection
}
})
}

componentWillUnmount () {
this.context.removeShortcut({ keyName: 'n' })
ipcRenderer.removeListener('shortcut-press', this.createWindow)
}

createWindow = () => ipcRenderer.send('create-new-window')

handleClick = () => this.createWindow()

render = () => (
<Base onClick={this.handleClick} name='open'>
<span title='New Window [CMD+ALT+N]'>
<Icon /> New Window
</span>
</Base>
)
}
8 changes: 5 additions & 3 deletions renderer/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import Save from '../components/save-button'
import Open from '../components/open-button'
import New from '../components/new-button'
import Export from '../components/export-button'
import Create from '../components/window-button'
import imageDrop from '../components/image-drop'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside of that file not being a component it's only used inside this page so it doesn't need to be externalized


import BoldIcon from 'react-icons/lib/fa/bold'
import ItalicIcon from 'react-icons/lib/fa/italic'
Expand Down Expand Up @@ -50,12 +52,11 @@ export default class extends Component {
setFileName: this.setFileName
}
}

componentDidMount () {
this.$preview = document.querySelector('.PulseEditor-preview')
this.$preview.addEventListener('click', this.handlePreviewLinkClick)
}

componentWillUnmount () {
this.$preview.removeEventListener('click', this.handlePreviewLinkClick)
}
Expand All @@ -70,7 +71,7 @@ export default class extends Component {
)
}

handleDrop = event => event.preventDefault()
handleDrop = e => imageDrop(e, this)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do this, be explicit, e could be event or error or whatever.


handleChange= event => {
if (event.markdown && this.state.fileName) {
Expand Down Expand Up @@ -149,6 +150,7 @@ export default class extends Component {
</ButtonGroup>

<ButtonGroup>
<Create />
<New />
<Open />
<Save />
Expand Down