Merge pull request #1135 from h3poteto/iss-901
refs #901 Use ipc, shell and clipboard from preload.js
This commit is contained in:
commit
21f9d90443
|
@ -6385,7 +6385,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.1.7",
|
"version": "1.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
"resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||||
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
|
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
|
@ -9448,18 +9448,18 @@
|
||||||
"integrity": "sha512-v+Af5W5z99ehhaLOfE9eTSXUwjzh2wFlQjz51dvkZ6ZIrET6OB/zAZPvsuwT6tm3t5x+M1r+Ed3U3xtPZYAyuQ=="
|
"integrity": "sha512-v+Af5W5z99ehhaLOfE9eTSXUwjzh2wFlQjz51dvkZ6ZIrET6OB/zAZPvsuwT6tm3t5x+M1r+Ed3U3xtPZYAyuQ=="
|
||||||
},
|
},
|
||||||
"electron-mock-ipc": {
|
"electron-mock-ipc": {
|
||||||
"version": "0.1.3",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/electron-mock-ipc/-/electron-mock-ipc-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/electron-mock-ipc/-/electron-mock-ipc-0.2.0.tgz",
|
||||||
"integrity": "sha512-+x5v+hmZZYUi8SMJNBtcq1o2p3aUJfT3aJCEKIoajSa/6rV9EdmFOd/rHLVEH85GSlWQCf+i1yV4r4bDnfEXHw==",
|
"integrity": "sha512-oEW4kS0W5ioQi5XprKXkBbD1zRINZk6AkGXsZD/mhgXaqTZuA0Qtsw1QoMWxykqnURVRl9plpmbHIvkYedsvNQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"typescript": "^3.5.2"
|
"typescript": "^3.5.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "3.5.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz",
|
||||||
"integrity": "sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==",
|
"integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16507,7 +16507,7 @@
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -16522,7 +16522,7 @@
|
||||||
},
|
},
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
|
|
@ -248,7 +248,7 @@
|
||||||
"electron-builder": "^21.2.0",
|
"electron-builder": "^21.2.0",
|
||||||
"electron-debug": "^3.0.1",
|
"electron-debug": "^3.0.1",
|
||||||
"electron-devtools-installer": "^2.2.4",
|
"electron-devtools-installer": "^2.2.4",
|
||||||
"electron-mock-ipc": "^0.1.3",
|
"electron-mock-ipc": "^0.2.0",
|
||||||
"electron-packager": "^14.0.5",
|
"electron-packager": "^14.0.5",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
"eslint-config-prettier": "^4.1.0",
|
"eslint-config-prettier": "^4.1.0",
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import createIPCMock from 'electron-mock-ipc'
|
import createIPCMock from 'electron-mock-ipc'
|
||||||
|
import { IpcRenderer, IpcMain } from 'electron'
|
||||||
|
|
||||||
const mocked = createIPCMock()
|
const mocked = createIPCMock()
|
||||||
const ipcMain = mocked.ipcMain
|
const ipcMain = mocked.ipcMain as IpcMain
|
||||||
const ipcRenderer = mocked.ipcRenderer
|
const ipcRenderer = mocked.ipcRenderer as IpcRenderer
|
||||||
|
|
||||||
export { ipcMain, ipcRenderer }
|
export { ipcMain, ipcRenderer }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { createLocalVue } from '@vue/test-utils'
|
import { createLocalVue } from '@vue/test-utils'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import { ipcMain } from '~/spec/mock/electron'
|
import { ipcMain, ipcRenderer } from '~/spec/mock/electron'
|
||||||
import App from '@/store/App'
|
import App from '@/store/App'
|
||||||
import DisplayStyle from '~/src/constants/displayStyle'
|
import DisplayStyle from '~/src/constants/displayStyle'
|
||||||
import { LightTheme, DarkTheme } from '~/src/constants/themeColor'
|
import { LightTheme, DarkTheme } from '~/src/constants/themeColor'
|
||||||
|
@ -8,6 +8,7 @@ import Theme from '~/src/constants/theme'
|
||||||
import TimeFormat from '~/src/constants/timeFormat'
|
import TimeFormat from '~/src/constants/timeFormat'
|
||||||
import Language from '~/src/constants/language'
|
import Language from '~/src/constants/language'
|
||||||
import DefaultFonts from '@/utils/fonts'
|
import DefaultFonts from '@/utils/fonts'
|
||||||
|
import { MyWindow } from '~/src/types/global'
|
||||||
|
|
||||||
const state = () => {
|
const state = () => {
|
||||||
return {
|
return {
|
||||||
|
@ -43,6 +44,7 @@ describe('App', () => {
|
||||||
let localVue
|
let localVue
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
;(<MyWindow>window).ipcRenderer = ipcRenderer
|
||||||
localVue = createLocalVue()
|
localVue = createLocalVue()
|
||||||
localVue.use(Vuex)
|
localVue.use(Vuex)
|
||||||
store = new Vuex.Store({
|
store = new Vuex.Store({
|
||||||
|
@ -58,8 +60,7 @@ describe('App', () => {
|
||||||
ipcMain.once('get-preferences', (event: any, _) => {
|
ipcMain.once('get-preferences', (event: any, _) => {
|
||||||
event.sender.send('error-get-preferences', new Error())
|
event.sender.send('error-get-preferences', new Error())
|
||||||
})
|
})
|
||||||
await store.dispatch('App/loadPreferences')
|
await store.dispatch('App/loadPreferences').catch(err => {
|
||||||
.catch((err) => {
|
|
||||||
expect(err instanceof Error).toEqual(true)
|
expect(err instanceof Error).toEqual(true)
|
||||||
expect(store.state.App.theme).toEqual(LightTheme)
|
expect(store.state.App.theme).toEqual(LightTheme)
|
||||||
})
|
})
|
||||||
|
|
|
@ -255,7 +255,9 @@ async function createWindow() {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
// It is required to use ipcRenderer in renderer process.
|
// It is required to use ipcRenderer in renderer process.
|
||||||
// But it is not secure, so if you want to disable this option, please use preload script.
|
// But it is not secure, so if you want to disable this option, please use preload script.
|
||||||
nodeIntegration: true
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false,
|
||||||
|
preload: path.resolve(__dirname, './preload.js')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
const electron = require('electron')
|
||||||
|
global.ipcRenderer = electron.ipcRenderer
|
||||||
|
global.shell = electron.shell
|
||||||
|
global.clipboard = electron.clipboard
|
||||||
|
global.process = process
|
|
@ -1,11 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="account_profile"
|
<div
|
||||||
|
id="account_profile"
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:element-loading-text="$t('message.loading')"
|
:element-loading-text="$t('message.loading')"
|
||||||
element-loading-spinner="el-icon-loading"
|
element-loading-spinner="el-icon-loading"
|
||||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||||
role="article"
|
role="article"
|
||||||
aria-label="account profile">
|
aria-label="account profile"
|
||||||
|
>
|
||||||
<div class="header-background" v-bind:style="{ backgroundImage: 'url(' + account.header + ')' }">
|
<div class="header-background" v-bind:style="{ backgroundImage: 'url(' + account.header + ')' }">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="follow-follower" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
<div class="follow-follower" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
||||||
|
@ -16,7 +18,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="more" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
<div class="more" v-if="relationship !== null && relationship !== '' && !isOwnProfile">
|
||||||
<popper trigger="click" :options="{placement: 'bottom'}" ref="popper">
|
<popper trigger="click" :options="{ placement: 'bottom' }" ref="popper">
|
||||||
<div class="popper">
|
<div class="popper">
|
||||||
<ul class="menu-list">
|
<ul class="menu-list">
|
||||||
<li role="button" @click="openBrowser(account)">
|
<li role="button" @click="openBrowser(account)">
|
||||||
|
@ -63,9 +65,7 @@
|
||||||
<div class="username">
|
<div class="username">
|
||||||
<bdi v-html="username(account)"></bdi>
|
<bdi v-html="username(account)"></bdi>
|
||||||
</div>
|
</div>
|
||||||
<div class="account">
|
<div class="account">@{{ account.acct }}</div>
|
||||||
@{{ account.acct }}
|
|
||||||
</div>
|
|
||||||
<div class="note" v-html="note(account)" @click.capture.prevent="noteClick"></div>
|
<div class="note" v-html="note(account)" @click.capture.prevent="noteClick"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,8 +74,7 @@
|
||||||
<dt>
|
<dt>
|
||||||
{{ data.name }}
|
{{ data.name }}
|
||||||
</dt>
|
</dt>
|
||||||
<dd v-html="data.value" @click.capture.prevent="metadataClick">
|
<dd v-html="data.value" @click.capture.prevent="metadataClick"></dd>
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<el-row class="basic-info">
|
<el-row class="basic-info">
|
||||||
|
@ -103,12 +102,11 @@
|
||||||
<follows :account="account" v-if="activeTab === 2"></follows>
|
<follows :account="account" v-if="activeTab === 2"></follows>
|
||||||
<followers :account="account" v-if="activeTab === 3"></followers>
|
<followers :account="account" v-if="activeTab === 3"></followers>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
import { shell } from 'electron'
|
|
||||||
import { findLink } from '~/src/renderer/utils/tootParser'
|
import { findLink } from '~/src/renderer/utils/tootParser'
|
||||||
import emojify from '~/src/renderer/utils/emojify'
|
import emojify from '~/src/renderer/utils/emojify'
|
||||||
import Timeline from './AccountProfile/Timeline'
|
import Timeline from './AccountProfile/Timeline'
|
||||||
|
@ -124,14 +122,14 @@ export default {
|
||||||
Followers,
|
Followers,
|
||||||
FailoverImg
|
FailoverImg
|
||||||
},
|
},
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {
|
||||||
activeTab: 1
|
activeTab: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
theme: (state) => {
|
theme: state => {
|
||||||
return {
|
return {
|
||||||
'--theme-mask-color': state.App.theme.wrapper_mask_color,
|
'--theme-mask-color': state.App.theme.wrapper_mask_color,
|
||||||
'--theme-border-color': state.App.theme.border_color,
|
'--theme-border-color': state.App.theme.border_color,
|
||||||
|
@ -149,31 +147,31 @@ export default {
|
||||||
...mapGetters('TimelineSpace/Contents/SideBar/AccountProfile', ['isOwnProfile'])
|
...mapGetters('TimelineSpace/Contents/SideBar/AccountProfile', ['isOwnProfile'])
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
account: function () {
|
account: function() {
|
||||||
this.activeTab = 1
|
this.activeTab = 1
|
||||||
},
|
},
|
||||||
loading: function (newState, _oldState) {
|
loading: function(newState, _oldState) {
|
||||||
this.$emit('change-loading', newState)
|
this.$emit('change-loading', newState)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
username (account) {
|
username(account) {
|
||||||
if (account.display_name !== '') {
|
if (account.display_name !== '') {
|
||||||
return emojify(account.display_name, account.emojis)
|
return emojify(account.display_name, account.emojis)
|
||||||
} else {
|
} else {
|
||||||
return account.username
|
return account.username
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
note (account) {
|
note(account) {
|
||||||
return emojify(account.note, account.emojis)
|
return emojify(account.note, account.emojis)
|
||||||
},
|
},
|
||||||
noteClick (e) {
|
noteClick(e) {
|
||||||
const link = findLink(e.target, 'note')
|
const link = findLink(e.target, 'note')
|
||||||
if (link !== null) {
|
if (link !== null) {
|
||||||
shell.openExternal(link)
|
window.shell.openExternal(link)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
follow (account) {
|
follow(account) {
|
||||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||||
try {
|
try {
|
||||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
|
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/follow', account)
|
||||||
|
@ -186,7 +184,7 @@ export default {
|
||||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
unfollow (account) {
|
unfollow(account) {
|
||||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', true)
|
||||||
try {
|
try {
|
||||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
|
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unfollow', account)
|
||||||
|
@ -199,39 +197,39 @@ export default {
|
||||||
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/changeLoading', false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeTab (index) {
|
changeTab(index) {
|
||||||
this.activeTab = index
|
this.activeTab = index
|
||||||
},
|
},
|
||||||
openBrowser (account) {
|
openBrowser(account) {
|
||||||
shell.openExternal(account.url)
|
window.shell.openExternal(account.url)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
addToList (account) {
|
addToList(account) {
|
||||||
this.$store.dispatch('TimelineSpace/Modals/ListMembership/setAccount', account)
|
this.$store.dispatch('TimelineSpace/Modals/ListMembership/setAccount', account)
|
||||||
this.$store.dispatch('TimelineSpace/Modals/ListMembership/changeModal', true)
|
this.$store.dispatch('TimelineSpace/Modals/ListMembership/changeModal', true)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
confirmMute (account) {
|
confirmMute(account) {
|
||||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeAccount', account)
|
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeAccount', account)
|
||||||
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeModal', true)
|
this.$store.dispatch('TimelineSpace/Modals/MuteConfirm/changeModal', true)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
unmute (account) {
|
unmute(account) {
|
||||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unmute', account)
|
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unmute', account)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
block (account) {
|
block(account) {
|
||||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/block', account)
|
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/block', account)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
unblock (account) {
|
unblock(account) {
|
||||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unblock', account)
|
this.$store.dispatch('TimelineSpace/Contents/SideBar/AccountProfile/unblock', account)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
metadataClick (e) {
|
metadataClick(e) {
|
||||||
const link = findLink(e.target, 'metadata')
|
const link = findLink(e.target, 'metadata')
|
||||||
if (link !== null) {
|
if (link !== null) {
|
||||||
return shell.openExternal(link)
|
return window.shell.openExternal(link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
import { clipboard } from 'electron'
|
|
||||||
import Visibility from '~/src/constants/visibility'
|
import Visibility from '~/src/constants/visibility'
|
||||||
import Status from './NewToot/Status'
|
import Status from './NewToot/Status'
|
||||||
import Poll from './NewToot/Poll'
|
import Poll from './NewToot/Poll'
|
||||||
|
@ -295,12 +294,12 @@ export default {
|
||||||
this.updateImage(file)
|
this.updateImage(file)
|
||||||
},
|
},
|
||||||
onPaste(e) {
|
onPaste(e) {
|
||||||
const mimeTypes = clipboard.availableFormats().filter(type => type.startsWith('image'))
|
const mimeTypes = window.clipboard.availableFormats().filter(type => type.startsWith('image'))
|
||||||
if (mimeTypes.length === 0) {
|
if (mimeTypes.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const image = clipboard.readImage()
|
const image = window.clipboard.readImage()
|
||||||
let data
|
let data
|
||||||
if (/^image\/jpe?g$/.test(mimeTypes[0])) {
|
if (/^image\/jpe?g$/.test(mimeTypes[0])) {
|
||||||
data = image.toJPEG(100)
|
data = image.toJPEG(100)
|
||||||
|
|
|
@ -133,7 +133,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import { shell } from 'electron'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'side-menu',
|
name: 'side-menu',
|
||||||
|
@ -178,7 +177,7 @@ export default {
|
||||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
this.$store.dispatch('TimelineSpace/Contents/SideBar/openAccountComponent')
|
||||||
break
|
break
|
||||||
case 'edit':
|
case 'edit':
|
||||||
shell.openExternal(this.account.baseURL + '/settings/profile')
|
window.shell.openExternal(this.account.baseURL + '/settings/profile')
|
||||||
break
|
break
|
||||||
case 'settings':
|
case 'settings':
|
||||||
const url = `/${this.id()}/settings`
|
const url = `/${this.id()}/settings`
|
||||||
|
|
|
@ -101,7 +101,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { shell } from 'electron'
|
|
||||||
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
|
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
|
||||||
import emojify from '~/src/renderer/utils/emojify'
|
import emojify from '~/src/renderer/utils/emojify'
|
||||||
import TimeFormat from '~/src/constants/timeFormat'
|
import TimeFormat from '~/src/constants/timeFormat'
|
||||||
|
@ -209,7 +208,7 @@ export default {
|
||||||
openLink(e) {
|
openLink(e) {
|
||||||
const link = findLink(e.target, 'favourite')
|
const link = findLink(e.target, 'favourite')
|
||||||
if (link !== null) {
|
if (link !== null) {
|
||||||
return shell.openExternal(link)
|
return window.shell.openExternal(link)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openUser(account) {
|
openUser(account) {
|
||||||
|
|
|
@ -103,7 +103,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { shell } from 'electron'
|
|
||||||
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
|
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
|
||||||
import emojify from '~/src/renderer/utils/emojify'
|
import emojify from '~/src/renderer/utils/emojify'
|
||||||
import TimeFormat from '~/src/constants/timeFormat'
|
import TimeFormat from '~/src/constants/timeFormat'
|
||||||
|
@ -209,7 +208,7 @@ export default {
|
||||||
openLink(e) {
|
openLink(e) {
|
||||||
const link = findLink(e.target, 'reblog')
|
const link = findLink(e.target, 'reblog')
|
||||||
if (link !== null) {
|
if (link !== null) {
|
||||||
return shell.openExternal(link)
|
return window.shell.openExternal(link)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openUser(account) {
|
openUser(account) {
|
||||||
|
|
|
@ -178,7 +178,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { shell, clipboard } from 'electron'
|
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
|
import { findAccount, findLink, findTag } from '~/src/renderer/utils/tootParser'
|
||||||
import DisplayStyle from '~/src/constants/displayStyle'
|
import DisplayStyle from '~/src/constants/displayStyle'
|
||||||
|
@ -391,7 +390,7 @@ export default {
|
||||||
openLink(e) {
|
openLink(e) {
|
||||||
const link = findLink(e.target, 'toot')
|
const link = findLink(e.target, 'toot')
|
||||||
if (link !== null) {
|
if (link !== null) {
|
||||||
return shell.openExternal(link)
|
return window.shell.openExternal(link)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openReply() {
|
openReply() {
|
||||||
|
@ -404,11 +403,11 @@ export default {
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
openBrowser(message) {
|
openBrowser(message) {
|
||||||
shell.openExternal(message.url)
|
window.shell.openExternal(message.url)
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
copyLink(message) {
|
copyLink(message) {
|
||||||
clipboard.writeText(message.url, 'toot-link')
|
window.clipboard.writeText(message.url, 'toot-link')
|
||||||
this.$refs.popper.doClose()
|
this.$refs.popper.doClose()
|
||||||
},
|
},
|
||||||
reportUser() {
|
reportUser() {
|
||||||
|
|
|
@ -16,15 +16,6 @@ import router from '@/router'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import i18next from '~/src/config/i18n'
|
import i18next from '~/src/config/i18n'
|
||||||
|
|
||||||
declare function require(x: string): any
|
|
||||||
|
|
||||||
declare var process: {
|
|
||||||
env: {
|
|
||||||
NODE_ENV: string,
|
|
||||||
IS_WEB: boolean
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vue.use(ElementUI, { locale })
|
Vue.use(ElementUI, { locale })
|
||||||
Vue.use(shortkey)
|
Vue.use(shortkey)
|
||||||
Vue.use(VueI18Next)
|
Vue.use(VueI18Next)
|
||||||
|
@ -33,7 +24,6 @@ Vue.component('popper', Popper)
|
||||||
|
|
||||||
sync(store, router)
|
sync(store, router)
|
||||||
|
|
||||||
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
const i18n: VueI18Next = new VueI18Next(i18next)
|
const i18n: VueI18Next = new VueI18Next(i18next)
|
||||||
|
|
|
@ -1,6 +1,34 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Router from 'vue-router'
|
import Router from 'vue-router'
|
||||||
|
|
||||||
|
import Login from '@/components/Login.vue'
|
||||||
|
import Authorize from '@/components/Authorize.vue'
|
||||||
|
import Preferences from '@/components/Preferences.vue'
|
||||||
|
import PreferencesGeneral from '@/components/Preferences/General.vue'
|
||||||
|
import PreferencesAppearance from '@/components/Preferences/Appearance.vue'
|
||||||
|
import PreferencesNotification from '@/components/Preferences/Notification.vue'
|
||||||
|
import PreferencesAccount from '@/components/Preferences/Account.vue'
|
||||||
|
import PreferencesLanguage from '@/components/Preferences/Language.vue'
|
||||||
|
import GlobalHeader from '@/components/GlobalHeader.vue'
|
||||||
|
import Settings from '@/components/Settings.vue'
|
||||||
|
import SettingsGeneral from '@/components/Settings/General.vue'
|
||||||
|
import SettingsTimeline from '@/components/Settings/Timeline.vue'
|
||||||
|
import TimelineSpace from '@/components/TimelineSpace.vue'
|
||||||
|
import TimelineSpaceContentsHome from '@/components/TimelineSpace/Contents/Home.vue'
|
||||||
|
import TimelineSpaceContentsNotifications from '@/components/TimelineSpace/Contents/Notifications.vue'
|
||||||
|
import TimelineSpaceContentsMentions from '@/components/TimelineSpace/Contents/Mentions.vue'
|
||||||
|
import TimelineSpaceContentsFavourites from '@/components/TimelineSpace/Contents/Favourites.vue'
|
||||||
|
import TimelineSpaceContentsLocal from '@/components/TimelineSpace/Contents/Local.vue'
|
||||||
|
import TimelineSpaceContentsPublic from '@/components/TimelineSpace/Contents/Public.vue'
|
||||||
|
import TimelineSpaceContentsHashtag from '@/components/TimelineSpace/Contents/Hashtag.vue'
|
||||||
|
import TimelineSpaceContentsHashtagList from '@/components/TimelineSpace/Contents/Hashtag/List.vue'
|
||||||
|
import TimelineSpaceContentsHashtagTag from '@/components/TimelineSpace/Contents/Hashtag/Tag.vue'
|
||||||
|
import TimelineSpaceContentsSearch from '@/components/TimelineSpace/Contents/Search.vue'
|
||||||
|
import TimelineSpaceContentsDirectMessages from '@/components/TimelineSpace/Contents/DirectMessages.vue'
|
||||||
|
import TimelineSpaceContentsListsIndex from '@/components/TimelineSpace/Contents/Lists/Index.vue'
|
||||||
|
import TimelineSpaceContentsListsEdit from '@/components/TimelineSpace/Contents/Lists/Edit.vue'
|
||||||
|
import TimelineSpaceContentsListsShow from '@/components/TimelineSpace/Contents/Lists/Show.vue'
|
||||||
|
|
||||||
Vue.use(Router)
|
Vue.use(Router)
|
||||||
|
|
||||||
const router = new Router({
|
const router = new Router({
|
||||||
|
@ -8,38 +36,38 @@ const router = new Router({
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: require('@/components/Login').default
|
component: Login
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/authorize',
|
path: '/authorize',
|
||||||
name: 'authorize',
|
name: 'authorize',
|
||||||
component: require('@/components/Authorize').default,
|
component: Authorize,
|
||||||
props: route => ({ url: route.query.url })
|
props: route => ({ url: route.query.url })
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/preferences/',
|
path: '/preferences/',
|
||||||
name: 'preferences',
|
name: 'preferences',
|
||||||
component: require('@/components/Preferences').default,
|
component: Preferences,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'general',
|
path: 'general',
|
||||||
name: 'general',
|
name: 'general',
|
||||||
component: require('@/components/Preferences/General').default
|
component: PreferencesGeneral
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'appearance',
|
path: 'appearance',
|
||||||
name: 'appearance',
|
name: 'appearance',
|
||||||
component: require('@/components/Preferences/Appearance').default
|
component: PreferencesAppearance
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'notification',
|
path: 'notification',
|
||||||
name: 'notification',
|
name: 'notification',
|
||||||
component: require('@/components/Preferences/Notification').default
|
component: PreferencesNotification
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'account',
|
path: 'account',
|
||||||
name: 'account',
|
name: 'account',
|
||||||
component: require('@/components/Preferences/Account').default
|
component: PreferencesAccount
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'network',
|
path: 'network',
|
||||||
|
@ -49,48 +77,48 @@ const router = new Router({
|
||||||
{
|
{
|
||||||
path: 'language',
|
path: 'language',
|
||||||
name: 'language',
|
name: 'language',
|
||||||
component: require('@/components/Preferences/Language').default
|
component: PreferencesLanguage
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'global-header',
|
name: 'global-header',
|
||||||
component: require('@/components/GlobalHeader').default,
|
component: GlobalHeader,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: ':id/settings/',
|
path: ':id/settings/',
|
||||||
component: require('@/components/Settings').default,
|
component: Settings,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'general',
|
path: 'general',
|
||||||
component: require('@/components/Settings/General').default
|
component: SettingsGeneral
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'timeline',
|
path: 'timeline',
|
||||||
component: require('@/components/Settings/Timeline').default
|
component: SettingsTimeline
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ':id/',
|
path: ':id/',
|
||||||
name: 'timeline-space',
|
name: 'timeline-space',
|
||||||
component: require('@/components/TimelineSpace').default,
|
component: TimelineSpace,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'home',
|
path: 'home',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: require('@/components/TimelineSpace/Contents/Home').default
|
component: TimelineSpaceContentsHome
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'notifications',
|
path: 'notifications',
|
||||||
name: 'notifications',
|
name: 'notifications',
|
||||||
component: require('@/components/TimelineSpace/Contents/Notifications').default
|
component: TimelineSpaceContentsNotifications
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'mentions',
|
path: 'mentions',
|
||||||
name: 'mentions',
|
name: 'mentions',
|
||||||
component: require('@/components/TimelineSpace/Contents/Mentions').default
|
component: TimelineSpaceContentsMentions
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'follow-requests',
|
path: 'follow-requests',
|
||||||
|
@ -100,31 +128,31 @@ const router = new Router({
|
||||||
{
|
{
|
||||||
path: 'favourites',
|
path: 'favourites',
|
||||||
name: 'favourites',
|
name: 'favourites',
|
||||||
component: require('@/components/TimelineSpace/Contents/Favourites').default
|
component: TimelineSpaceContentsFavourites
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'local',
|
path: 'local',
|
||||||
name: 'local',
|
name: 'local',
|
||||||
component: require('@/components/TimelineSpace/Contents/Local').default
|
component: TimelineSpaceContentsLocal
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'public',
|
path: 'public',
|
||||||
name: 'public',
|
name: 'public',
|
||||||
component: require('@/components/TimelineSpace/Contents/Public').default
|
component: TimelineSpaceContentsPublic
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'hashtag/',
|
path: 'hashtag/',
|
||||||
component: require('@/components/TimelineSpace/Contents/Hashtag').default,
|
component: TimelineSpaceContentsHashtag,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
name: 'hashtag-list',
|
name: 'hashtag-list',
|
||||||
component: require('@/components/TimelineSpace/Contents/Hashtag/List').default
|
component: TimelineSpaceContentsHashtagList
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: ':tag',
|
path: ':tag',
|
||||||
name: 'tag',
|
name: 'tag',
|
||||||
component: require('@/components/TimelineSpace/Contents/Hashtag/Tag').default,
|
component: TimelineSpaceContentsHashtagTag,
|
||||||
props: true
|
props: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -132,28 +160,28 @@ const router = new Router({
|
||||||
{
|
{
|
||||||
path: 'search',
|
path: 'search',
|
||||||
name: 'search',
|
name: 'search',
|
||||||
component: require('@/components/TimelineSpace/Contents/Search').default
|
component: TimelineSpaceContentsSearch
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'direct-messages',
|
path: 'direct-messages',
|
||||||
name: 'direct-messages',
|
name: 'direct-messages',
|
||||||
component: require('@/components/TimelineSpace/Contents/DirectMessages').default
|
component: TimelineSpaceContentsDirectMessages
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lists',
|
path: 'lists',
|
||||||
name: 'lists',
|
name: 'lists',
|
||||||
component: require('@/components/TimelineSpace/Contents/Lists/Index').default
|
component: TimelineSpaceContentsListsIndex
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lists/:list_id/edit',
|
path: 'lists/:list_id/edit',
|
||||||
name: 'edit-list',
|
name: 'edit-list',
|
||||||
component: require('@/components/TimelineSpace/Contents/Lists/Edit').default,
|
component: TimelineSpaceContentsListsEdit,
|
||||||
props: true
|
props: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lists/:list_id',
|
path: 'lists/:list_id',
|
||||||
name: 'list',
|
name: 'list',
|
||||||
component: require('@/components/TimelineSpace/Contents/Lists/Show').default,
|
component: TimelineSpaceContentsListsShow,
|
||||||
props: true
|
props: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { ipcRenderer } from 'electron'
|
|
||||||
import { MutationTree, ActionTree, Module } from 'vuex'
|
import { MutationTree, ActionTree, Module } from 'vuex'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { LightTheme, DarkTheme, SolarizedLightTheme, SolarizedDarkTheme, KimbieDarkTheme, ThemeColorType } from '~/src/constants/themeColor'
|
import { LightTheme, DarkTheme, SolarizedLightTheme, SolarizedDarkTheme, KimbieDarkTheme, ThemeColorType } from '~/src/constants/themeColor'
|
||||||
|
@ -12,6 +11,9 @@ import { Notify } from '~/src/types/notify'
|
||||||
import { BaseConfig } from '~/src/types/preference'
|
import { BaseConfig } from '~/src/types/preference'
|
||||||
import { Appearance } from '~/src/types/appearance'
|
import { Appearance } from '~/src/types/appearance'
|
||||||
import { ProxyConfig } from 'megalodon'
|
import { ProxyConfig } from 'megalodon'
|
||||||
|
import { MyWindow } from '~/src/types/global'
|
||||||
|
|
||||||
|
const win = window as MyWindow
|
||||||
|
|
||||||
export type AppState = {
|
export type AppState = {
|
||||||
theme: ThemeColorType
|
theme: ThemeColorType
|
||||||
|
@ -107,22 +109,22 @@ const mutations: MutationTree<AppState> = {
|
||||||
|
|
||||||
const actions: ActionTree<AppState, RootState> = {
|
const actions: ActionTree<AppState, RootState> = {
|
||||||
watchShortcutsEvents: () => {
|
watchShortcutsEvents: () => {
|
||||||
ipcRenderer.on('open-preferences', () => {
|
win.ipcRenderer.on('open-preferences', () => {
|
||||||
router.push('/preferences/general')
|
router.push('/preferences/general')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
removeShortcutsEvents: () => {
|
removeShortcutsEvents: () => {
|
||||||
ipcRenderer.removeAllListeners('open-preferences')
|
win.ipcRenderer.removeAllListeners('open-preferences')
|
||||||
},
|
},
|
||||||
loadPreferences: ({ commit, dispatch }) => {
|
loadPreferences: ({ commit, dispatch }) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
ipcRenderer.send('get-preferences')
|
win.ipcRenderer.send('get-preferences')
|
||||||
ipcRenderer.once('error-get-preferences', (_, err: Error) => {
|
win.ipcRenderer.once('error-get-preferences', (_, err: Error) => {
|
||||||
ipcRenderer.removeAllListeners('response-get-preferences')
|
win.ipcRenderer.removeAllListeners('response-get-preferences')
|
||||||
reject(err)
|
reject(err)
|
||||||
})
|
})
|
||||||
ipcRenderer.once('response-get-preferences', (_, conf: BaseConfig) => {
|
win.ipcRenderer.once('response-get-preferences', (_, conf: BaseConfig) => {
|
||||||
ipcRenderer.removeAllListeners('error-get-preferences')
|
win.ipcRenderer.removeAllListeners('error-get-preferences')
|
||||||
dispatch('updateTheme', conf.appearance)
|
dispatch('updateTheme', conf.appearance)
|
||||||
commit(MUTATION_TYPES.UPDATE_DISPLAY_NAME_STYLE, conf.appearance.displayNameStyle)
|
commit(MUTATION_TYPES.UPDATE_DISPLAY_NAME_STYLE, conf.appearance.displayNameStyle)
|
||||||
commit(MUTATION_TYPES.UPDATE_FONT_SIZE, conf.appearance.fontSize)
|
commit(MUTATION_TYPES.UPDATE_FONT_SIZE, conf.appearance.fontSize)
|
||||||
|
@ -166,11 +168,11 @@ const actions: ActionTree<AppState, RootState> = {
|
||||||
},
|
},
|
||||||
loadProxy: ({ commit }) => {
|
loadProxy: ({ commit }) => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
ipcRenderer.once('response-get-proxy-configuration', (_, proxy: ProxyConfig | false) => {
|
win.ipcRenderer.once('response-get-proxy-configuration', (_, proxy: ProxyConfig | false) => {
|
||||||
commit(MUTATION_TYPES.UPDATE_PROXY_CONFIGURATION, proxy)
|
commit(MUTATION_TYPES.UPDATE_PROXY_CONFIGURATION, proxy)
|
||||||
resolve(proxy)
|
resolve(proxy)
|
||||||
})
|
})
|
||||||
ipcRenderer.send('get-proxy-configuration')
|
win.ipcRenderer.send('get-proxy-configuration')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,13 @@ import TimelineSpace, { TimelineSpaceModuleState } from './TimelineSpace'
|
||||||
import Preferences, { PreferencesModuleState } from './Preferences'
|
import Preferences, { PreferencesModuleState } from './Preferences'
|
||||||
import Settings, { SettingsModuleState } from './Settings'
|
import Settings, { SettingsModuleState } from './Settings'
|
||||||
import organisms, { OrganismsModuleState } from './organisms'
|
import organisms, { OrganismsModuleState } from './organisms'
|
||||||
|
import { MyWindow } from '~/src/types/global'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
export type RootState = {
|
const win = window as MyWindow
|
||||||
|
|
||||||
|
export interface RootState {
|
||||||
App: AppState
|
App: AppState
|
||||||
GlobalHeader: GlobalHeaderState
|
GlobalHeader: GlobalHeaderState
|
||||||
Login: LoginState
|
Login: LoginState
|
||||||
|
@ -27,8 +30,8 @@ export type RootState = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
strict: process.env.NODE_ENV !== 'production',
|
strict: win.process.env.NODE_ENV !== 'production',
|
||||||
plugins: process.env.NODE_ENV !== 'production' ? [createLogger({})] : [],
|
plugins: win.process.env.NODE_ENV !== 'production' ? [createLogger({})] : [],
|
||||||
modules: {
|
modules: {
|
||||||
App,
|
App,
|
||||||
GlobalHeader,
|
GlobalHeader,
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { Shell, IpcRenderer, Clipboard } from 'electron'
|
||||||
|
|
||||||
|
export interface MyWindow extends Window {
|
||||||
|
shell: Shell
|
||||||
|
ipcRenderer: IpcRenderer
|
||||||
|
clipboard: Clipboard
|
||||||
|
process: NodeJS.Process
|
||||||
|
}
|
Loading…
Reference in New Issue