Skip to content
This repository has been archived by the owner on Mar 23, 2023. It is now read-only.

Commit

Permalink
feat: expose save/open dialogs to plugins (#1793)
Browse files Browse the repository at this point in the history
  • Loading branch information
dated authored Mar 8, 2020
1 parent b6e927a commit 898c72b
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 12 deletions.
1 change: 1 addition & 0 deletions config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ exports.PLUGINS = {
officialAuthor: 'ARK Ecosystem',
path: path.resolve(os.homedir(), '.ark-desktop/plugins'),
reportUrl: 'https://ark.io/contact',
sharePath: path.resolve(os.homedir(), '.ark-desktop/share'),
updateInterval: {
value: 1,
unit: 'day'
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/assets/svg/arrow-sent-received.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 42 additions & 9 deletions src/renderer/mixins/electron.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
import electron from 'electron'
import { readFileSync, writeFileSync } from 'fs'
import path from 'path'
import os from 'os'

const validatePath = (parentPath, filePath) => {
const relative = path.relative(parentPath, filePath)
return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
}

const parseFilters = filters => {
if (typeof filters === 'string') {
filters = [filters]
}

if (Array.isArray(filters) && filters.length) {
if (filters.every(filter => typeof filter === 'string')) {
return filters.map(filter => ({
name: filter.toUpperCase(), extensions: [filter]
}))
}
}

return filters || [
{ name: 'JSON', extensions: ['json'] },
{ name: 'All Files', extensions: ['*'] }
]
}

export default {
methods: {
Expand All @@ -13,32 +39,39 @@ export default {
},

async electron_writeFile (raw, defaultPath, options = {}) {
const filters = parseFilters(options.filters)

const { filePath } = await electron.remote.dialog.showSaveDialog({
defaultPath,
filters: options.filters || [
{ name: 'JSON', extensions: ['json'] },
{ name: 'All Files', extensions: ['*'] }
]
filters
})

if (!filePath) return

if (options.restrictToPath && !validatePath(options.restrictToPath, filePath)) {
throw new Error(`Path "${filePath}" not allowed`)
}

writeFileSync(filePath, raw, 'utf8')

return filePath
},

async electron_readFile (options = {}) {
async electron_readFile (defaultPath, options = {}) {
const filters = parseFilters(options.filters)

const { filePaths } = await electron.remote.dialog.showOpenDialog({
defaultPath: defaultPath || os.homedir(),
properties: ['openFile'],
filters: options.filters || [
{ name: 'JSON', extensions: ['json'] },
{ name: 'All Files', extensions: ['*'] }
]
filters
})

if (!filePaths) return

if (options.restrictToPath && !validatePath(options.restrictToPath, filePaths[0])) {
throw new Error(`Path "${filePaths[0]}" not allowed`)
}

return readFileSync(filePaths[0], 'utf8')
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/pages/Contact/ContactAll.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</div>

<button
class="ContactAll__CreateButton justify-end"
class="ContactAll__CreateButton ml-12 justify-end"
@click="createContact"
>
<span class="ContactAll__CreateButton__icon">
Expand Down Expand Up @@ -237,7 +237,7 @@ export default {
}
.ContactAll__CreateButton {
transition: all .1s ease-in;
@apply .flex .items-center .font-semibold .bg-theme-button .rounded .cursor-pointer .text-theme-button-text .ml-12;
@apply .flex .items-center .font-semibold .bg-theme-button .rounded .cursor-pointer .text-theme-button-text;
}
.ContactAll__CreateButton:hover {
@apply .bg-blue .text-white;
Expand Down
1 change: 1 addition & 0 deletions src/renderer/services/plugin-manager/plugin-permission.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const ALERTS = new Permission({ name: 'ALERTS' })
export const AUDIO = new Permission({ name: 'AUDIO' })
export const AVATARS = new Permission({ name: 'AVATARS' })
export const COMPONENTS = new Permission({ name: 'COMPONENTS' })
export const DIALOGS = new Permission({ name: 'DIALOGS' })
export const EVENTS = new Permission({ name: 'EVENTS' })
export const HTTP = new Permission({ name: 'HTTP' })
export const MENU_ITEMS = new Permission({ name: 'MENU_ITEMS' })
Expand Down
5 changes: 4 additions & 1 deletion src/renderer/services/plugin-manager/plugin-sandbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
AUDIO,
EVENTS,
ALERTS,
UTILS
UTILS,
DIALOGS
} from './plugin-permission'
import * as HttpSandbox from './sandbox/http-sandbox'
import * as MessagingSandbox from './sandbox/messaging-sandbox'
Expand All @@ -32,6 +33,7 @@ import * as EventsSandbox from './sandbox/events-sandbox'
import * as AlertsSandbox from './sandbox/alerts-sandbox'
import * as BigNumberSandbox from './sandbox/big-number-sandbox'
import * as DatetimeSandbox from './sandbox/datetime-sandbox'
import * as DialogSandbox from './sandbox/dialogs-sandbox'

export class PluginSandbox {
constructor ({
Expand Down Expand Up @@ -118,6 +120,7 @@ export class PluginSandbox {
return {
[ALERTS.name]: AlertsSandbox.create(this.walletApi, this.app),
[AUDIO.name]: AudioSandbox.create(this.sandbox),
[DIALOGS.name]: DialogSandbox.create(this.walletApi),
[EVENTS.name]: EventsSandbox.create(this.walletApi, this.app),
[HTTP.name]: HttpSandbox.create(this.walletApi, this.plugin),
[MESSAGING.name]: MessagingSandbox.create(this.walletApi, this.app),
Expand Down
23 changes: 23 additions & 0 deletions src/renderer/services/plugin-manager/sandbox/dialogs-sandbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { PLUGINS } from '@config'
import electron from '@/mixins/electron'
import { ensureDirSync } from 'fs-extra'
import path from 'path'

export function create (walletApi) {
return () => {
walletApi.dialogs = {
save: async (raw, filename, filters) => {
ensureDirSync(PLUGINS.sharePath)

return electron.methods.electron_writeFile(raw, path.resolve(PLUGINS.sharePath, filename), {
restrictToPath: PLUGINS.sharePath,
filters
})
},

open: async (filters) => {
return electron.methods.electron_readFile(PLUGINS.sharePath, { filters })
}
}
}
}

0 comments on commit 898c72b

Please sign in to comment.