Skip to content

Commit

Permalink
feat: 除导出功能外基本完成
Browse files Browse the repository at this point in the history
  • Loading branch information
LeafYeeXYZ committed Aug 27, 2024
1 parent b17ea8d commit 8cc77b5
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 23 deletions.
62 changes: 62 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Build and Release

on:
push:
tags:
# Match any new tag
- '*'

env:
# Necessary for most environments as build failure can occur due to OOM issues
NODE_OPTIONS: "--max-old-space-size=4096"

jobs:
build:
permissions:
contents: write
strategy:
# Failure in one platform build won't impact the others
fail-fast: false
matrix:
build:
# - name: 'windows-amd64'
# platform: 'windows/amd64'
# os: 'windows-latest'
# - name: 'windows-arm64'
# platform: 'windows/arm64'
# os: 'windows-latest'
# - name: 'mac-amd64'
# platform: 'darwin/amd64'
# os: 'macos-latest'
- name: 'Build'
platform: 'darwin/arm64'
os: 'macos-latest'

runs-on: ${{ matrix.build.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '22'

- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: 'latest'

- name: Build
run: bun run build:both

- name: Create Release
uses: softprops/action-gh-release@v2
with:
# 不上传 .yml .yaml .blockmap
files: |
dist/* !dist/*.yml !dist/*.yaml !dist/*.blockmap
draft: false
prerelease: true
53 changes: 49 additions & 4 deletions src/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { app, shell, BrowserWindow, ipcMain } from 'electron'
import { app, shell, BrowserWindow, ipcMain, dialog } from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
import fs from 'node:fs/promises'
import path from 'node:path'

function createWindow(): void {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 900,
width: 1000,
height: 670,
minWidth: 768,
minHeight: 512,
Expand Down Expand Up @@ -51,8 +53,51 @@ app.whenReady().then(() => {
optimizer.watchWindowShortcuts(window)
})

// IPC test
ipcMain.on('ping', () => console.log('pong'))
// IPC
ipcMain.handle('openBrowser', async (_, url: string) => {
await shell.openExternal(url)
})
ipcMain.handle('newPaper', async (): Promise<{ filepath: string; filename: string }> => {
// 弹出文件选择框
const { filePath, canceled } = await dialog.showSaveDialog({
title: '新建文档',
filters: [{ name: 'Markdown 文件', extensions: ['md'] }],
showsTagField: false,
properties: ['createDirectory']
})
if (canceled) {
return { filepath: '', filename: '' }
} else {
const filepath = path.dirname(filePath)
const filename = path.basename(filePath)
await fs.writeFile(filePath, '', 'utf-8')
return { filepath, filename }
}
})
ipcMain.handle(
'openPaper',
async (): Promise<{ filepath: string; filename: string; content: string }> => {
// 弹出文件选择框
const { filePaths, canceled } = await dialog.showOpenDialog({
title: '打开文档',
filters: [{ name: 'Markdown 文件', extensions: ['md'] }]
})
if (canceled) {
return { filepath: '', filename: '', content: '' }
} else {
const filepath = path.dirname(filePaths[0])
const filename = path.basename(filePaths[0])
const content = await fs.readFile(filePaths[0], 'utf-8')
return { filepath, filename, content }
}
}
)
ipcMain.handle(
'savePaper',
async (_, filepath: string, filename: string, content: string): Promise<void> => {
await fs.writeFile(path.resolve(filepath, filename), content, 'utf-8')
}
)

createWindow()

Expand Down
7 changes: 6 additions & 1 deletion src/preload/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { ElectronAPI } from '@electron-toolkit/preload'
declare global {
interface Window {
electron: ElectronAPI
api: unknown
api: {
openBrowser: (url: string) => Promise<void>
newPaper: () => Promise<{ filepath: string; filename: string }>
openPaper: () => Promise<{ filepath: string; filename: string; content: string }>
savePaper: (filepath: string, filename: string, content: string) => Promise<void>
}
}
}
15 changes: 14 additions & 1 deletion src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@ import { contextBridge } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'

// Custom APIs for renderer
const api = {}
const api = {
openBrowser: async (url: string): Promise<void> => {
await electronAPI.ipcRenderer.invoke('openBrowser', url)
},
newPaper: async (): Promise<{ filepath: string; filename: string }> => {
return await electronAPI.ipcRenderer.invoke('newPaper')
},
openPaper: async (): Promise<{ filepath: string; filename: string; content: string }> => {
return await electronAPI.ipcRenderer.invoke('openPaper')
},
savePaper: async (filepath: string, filename: string, content: string): Promise<void> => {
await electronAPI.ipcRenderer.invoke('savePaper', filepath, filename, content)
}
}

// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
Expand Down
12 changes: 9 additions & 3 deletions src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import Editor from './components/Editor'
import Preview from './components/Preview'
import Toolbar from './components/Toolbar'
import { ConfigProvider } from 'antd'
import { ConfigProvider, message } from 'antd'
import { useStore } from './lib/useStore'
import { useEffect } from 'react'

function App(): JSX.Element {
// const ipcHandle = (): void => window.electron.ipcRenderer.send('ping')

const [messageApi, contextHolder] = message.useMessage()
const { setMessageApi } = useStore()
useEffect(() => {
setMessageApi(messageApi)
}, [messageApi, setMessageApi])
return (
<main className="w-dvw h-dvh absolute grid grid-rows-[3rem,1fr] overflow-hidden">
<ConfigProvider
Expand All @@ -23,6 +28,7 @@ function App(): JSX.Element {
<Preview />
<Editor />
</div>
{contextHolder}
</ConfigProvider>
</main>
)
Expand Down
16 changes: 14 additions & 2 deletions src/renderer/src/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ import { Input } from 'antd'
import { useStore } from '../lib/useStore'

export default function Editor(): JSX.Element {
const { setMarkdown } = useStore()
const { setMarkdown, filepath, filename, markdown } = useStore()
return (
<div className="p-2 pl-1 pt-0 w-full h-full overflow-hidden">
<div
className="border w-full h-full rounded-md shadow-md overflow-auto"
className="border w-full h-full p-2 rounded-md shadow-md overflow-auto"
style={{ scrollbarWidth: 'none' }}
>
<div className="w-full h-8 p-2 mb-2 border rounded-md shadow-sm bg-gray-50 text-xs text-gray-500 text-ellipsis overflow-hidden text-nowrap">
<span className="font-bold">
当前文件: <span className="font-normal">{filename || '...'}</span>
</span>
</div>
<div className="w-full h-8 p-2 mb-2 border rounded-md shadow-sm bg-gray-50 text-xs text-gray-500 text-ellipsis overflow-hidden text-nowrap">
<span className="font-bold">
存放位置: <span className="font-normal">{filepath || '...'}</span>
</span>
</div>
<Input.TextArea
className="h-full w-full"
placeholder="在这里输入论文内容"
Expand All @@ -18,6 +28,8 @@ export default function Editor(): JSX.Element {
autoCapitalize="off"
spellCheck={false}
onChange={(e) => setMarkdown(e.target.value)}
disabled={filepath === '' || filename === ''}
value={markdown}
/>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/components/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function Preview(): JSX.Element {
style={{ scrollbarWidth: 'none' }}
>
{markdown ? (
<iframe className="w-full h-full p-8" srcDoc={html} />
<iframe className="w-full h-full p-8" srcDoc={html} sandbox="" />
) : (
<span className="text-xs text-gray-300 block p-2">内容预览</span>
)}
Expand Down
50 changes: 40 additions & 10 deletions src/renderer/src/components/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,66 @@ import {
FileTextOutlined,
FileWordOutlined
} from '@ant-design/icons'
import { useStore } from '../lib/useStore'

export default function Toolbar(): JSX.Element {
const { filepath, filename, setFilename, setFilepath, setMarkdown, messageApi, markdown } =
useStore()
return (
<div className="h-full w-full flex justify-start items-center gap-2 px-2">
<Button>
<Button
type={filepath && filename ? 'default' : 'primary'}
onClick={async () => {
const { filename, filepath } = await window.api.newPaper()
setFilename(filename)
setFilepath(filepath)
}}
>
<FileAddOutlined /> 新建
</Button>
<Button>
<Button
type={filepath && filename ? 'default' : 'primary'}
onClick={async () => {
const { filename, filepath, content } = await window.api.openPaper()
setFilename(filename)
setFilepath(filepath)
setMarkdown(content)
}}
>
<FolderOpenOutlined /> 打开
</Button>
<Button>
<Button
disabled={!filepath || !filename || !markdown.length || !messageApi}
onClick={async () => {
await window.api
.savePaper(filepath, filename, markdown)
.then(() => messageApi!.success('保存成功'))
.catch(() => messageApi!.error('保存失败'))
}}
>
<SaveOutlined /> 保存
</Button>
<Button>
<Button
onClick={() => {
window.api.openBrowser('https://github.com/LeafYeeXYZ/EasyPaper')
}}
>
<QuestionCircleOutlined /> 帮助
</Button>
<p className="text-sm px-1 text-nowrap">导出为:</p>
<Button>
<p className="text-xs px-1 font-bold text-nowrap text-gray-600">导出:</p>
<Button disabled>
<FileMarkdownOutlined /> Markdown
</Button>
<Button>
<Button disabled>
<FilePdfOutlined /> PDF
</Button>
<Button>
<Button disabled>
<FileTextOutlined /> HTML
</Button>
<Button>
<Button disabled>
<FileWordOutlined /> Word
</Button>
<p className="text-sm px-1 text-nowrap">论文格式:</p>
<p className="text-xs px-1 font-bold text-nowrap text-gray-600">论文格式:</p>
<Select defaultValue="aps">
<Select.Option value="aps">心理学报</Select.Option>
</Select>
Expand Down
15 changes: 14 additions & 1 deletion src/renderer/src/lib/useStore.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { create } from 'zustand'
import { MarkdownPaperTheme, APS } from '../../../../resources/lib/theme'
import type { MessageInstance } from 'antd/es/message/interface'

interface State {
disabled: boolean
Expand All @@ -8,6 +9,12 @@ interface State {
setTheme: (theme: MarkdownPaperTheme) => void
markdown: string
setMarkdown: (markdown: string) => void
filepath: string
setFilepath: (filepath: string) => void
filename: string
setFilename: (filename: string) => void
messageApi: MessageInstance | null
setMessageApi: (messageApi: MessageInstance) => void
}

export const useStore = create<State>()((set) => ({
Expand All @@ -16,5 +23,11 @@ export const useStore = create<State>()((set) => ({
theme: APS,
setTheme: (theme): void => set({ theme }),
markdown: '',
setMarkdown: (markdown): void => set({ markdown })
setMarkdown: (markdown): void => set({ markdown }),
filepath: '',
setFilepath: (filepath): void => set({ filepath }),
filename: '',
setFilename: (filename): void => set({ filename }),
messageApi: null,
setMessageApi: (messageApi): void => set({ messageApi })
}))

0 comments on commit 8cc77b5

Please sign in to comment.