添加(initShow?): 新增initShow参数到OptionsType接口

🔧 更新(connect.ts): 将数据库文件路径更改为'autoMate.db'
🔧 更新(ipc.ts): 添加selectDatabaseDirectory处理程序
🔧 更新(index.ts): 调用registerAppGlobShortCut()注册全局快捷键
🔧 更新(shortCut.ts): 修改registerAppGlobShortCut()逻辑
🔧 更新(windows.ts): 添加新的code选项和配置项
🔧 更新(index.d.ts): 添加selectDatabaseDirectory全局声明
🔵 更新(index.ts): 导出selectDatabaseDirectory方法
🔧 更新(index.tsx): 更新快捷键注册逻辑
🔧 更新(index.tsx): 添加点击选择数据库目录的处理逻辑
🔧 更新(index.tsx): 添加config和setConfig到store中
🔧 更新(useStore.ts): 新增config和setConfig状态
⚙️ 更新(types.d.ts): 添加code到WindowNameType类型
This commit is contained in:
ruotongyu 2024-06-23 20:34:09 +08:00
parent 13d6e00a88
commit ec1bdbd39d
15 changed files with 102 additions and 40 deletions

View File

@ -7,6 +7,7 @@ import url from 'node:url'
export interface OptionsType extends Partial<BrowserWindowConstructorOptions>{
openDevTools?: boolean,
hash?: string
initShow?: boolean
}
export function createWindow(options: OptionsType): BrowserWindow { // Create the browser window.
const win = new BrowserWindow(Object.assign({
@ -27,7 +28,7 @@ export function createWindow(options: OptionsType): BrowserWindow { // Create t
// 如果是在开发环境下并且选项是打开开发者工具
if (is.dev && options.openDevTools) win.webContents.openDevTools()
win.on('ready-to-show', () => {
win.show()
options.initShow && win.show()
})
win.webContents.setWindowOpenHandler((details) => {

View File

@ -1,7 +1,7 @@
import Database, * as BetterSqlite3 from 'better-sqlite3';
import { app } from 'electron';
import {resolve} from 'node:path'
const file = resolve(app.getPath('home'), "Desktop", 'hd.db')
const file = resolve(app.getPath('home'), 'autoMate.db')
const db: BetterSqlite3.Database = new Database(file, {});
db.pragma('journal_mode = WAL');
export {db};

View File

@ -1,5 +1,14 @@
import { IpcMainInvokeEvent, ipcMain } from "electron";
import { IpcMainInvokeEvent, dialog, ipcMain } from "electron";
import * as query from './query'
ipcMain.handle('sql', (_event: IpcMainInvokeEvent, sql: string, type: SqlActionType, params={}) => {
return query[type](sql, params)
})
ipcMain.handle('selectDatabaseDirectory', async () => {
const ret = await dialog.showOpenDialog({
title: "选择目录",
properties: ['openDirectory', 'createDirectory']
})
return ret.canceled?'' : ret.filePaths[0]
})

View File

@ -4,12 +4,13 @@ import "./db"
import "./windows"
import "./ipc"
import "./shortCut"
import { registerAppGlobShortCut } from "./shortCut"
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
registerAppGlobShortCut()
// Set app user model id for windows
electronApp.setAppUserModelId('com.electron')

View File

@ -1,6 +1,7 @@
import { IpcMainInvokeEvent } from "electron"
import { IpcMainInvokeEvent, dialog } from "electron"
import { ipcMain } from "electron"
import { getWindowByName } from "./windows"
import { config } from "./db/query"
const { app, globalShortcut } = require('electron')
ipcMain.handle("shortCut", (_event: IpcMainInvokeEvent, shortCut: string) => {
@ -11,11 +12,15 @@ ipcMain.handle("shortCut", (_event: IpcMainInvokeEvent, shortCut: string) => {
function registerSearchShortCut(shortCut: string){
globalShortcut.unregisterAll()
// const ret = findOne(`select * from config where id=1`) as {content: string}
// const shortCut = JSON.parse(ret.content).shortCut as string
if (globalShortcut.isRegistered(shortCut)){
if (shortCut && globalShortcut.isRegistered(shortCut)){
dialog.showErrorBox('提示', '快捷键注册失败,请更换')
return false
}
const win = getWindowByName('search')
const res = globalShortcut.register(shortCut, () => {
win.isVisible() ? win.hide() : win.show()
@ -25,4 +30,9 @@ function registerSearchShortCut(shortCut: string){
app.on('will-quit', () => {
// Unregister all shortcuts.
globalShortcut.unregisterAll()
})
})
export const registerAppGlobShortCut =()=>{
const configData = config() as {shortCut: string}
registerSearchShortCut(configData.shortCut)
}

View File

@ -5,15 +5,29 @@ export const config = {
search: {
id: 0,
options: {
initShow: true,
hash: '',
openDevTools: true,
}
},
code: {
id: 0,
options: {
initShow: false,
width: 1300,
height: 700,
openDevTools: true,
frame: true,
transparent: false,
hash: '/#config/category/contentList'
}
},
config: {
id: 0,
options: {
width: 1300,
height: 600,
initShow: false,
width: 600,
height: 400,
openDevTools: true,
frame: true,
transparent: false,

View File

@ -10,6 +10,7 @@ declare global {
sql: <T>(sql: string, type: SqlActionType, params?: Record<string, any>) => Promise<T>
openWindow: (name: WindowNameType) => void,
closeWindow: (name: WindowNameType) => void,
selectDatabaseDirectory: () => Promise<string>
}
}
}

View File

@ -21,6 +21,9 @@ const api = {
closeWindow: (name: WindowNameType) =>{
ipcRenderer.send("closeWindow", name)
},
selectDatabaseDirectory: () => {
return ipcRenderer.invoke("selectDatabaseDirectory")
}
}

View File

@ -21,7 +21,7 @@ export default function Search(): JSX.Element {
fill="#34495e"
strokeWidth={4}
className="cursor-pointer"
onClick={()=>window.api.openWindow('config')
onClick={()=>window.api.openWindow('code')
}
/>
<Input
@ -31,7 +31,10 @@ export default function Search(): JSX.Element {
autoFocus
/>
</section>
<section className="text-center text-slate-600 text-xs mt-2">autoMate</section>
<section className="text-center text-slate-600 text-xs mt-2 nodrag">
autoMate
<span className="text-blue-600" onClick={()=>window.api.openWindow('config')}></span>
</section>
</main>
)
}

View File

@ -1,15 +1,16 @@
import { useStore } from "@renderer/store/useStore"
// import { useStore } from "@renderer/store/useStore"
export default() => {
const setError = useStore(state => state.setError)
const register = async ()=>{
const ret = (await window.api.sql('', 'config')) as Record<string, string>
const isBind = await window.api.shortCut(ret.shortCut)
isBind || setError("注册失败")
// const setError = useStore(state => state.setError)
// const register = async ()=>{
// const ret = (await window.api.sql('', 'config')) as Record<string, string>
// const isBind = await window.api.shortCut(ret.shortCut)
// isBind || setError("注册失败")
}
return {
register
}
// }
// return {
// register
// }
return {}
}

View File

@ -1,23 +1,23 @@
import Result from "@renderer/components/Result"
import Search from "@renderer/components/Search"
import { CodeProvider } from "@renderer/context/CodeContext"
import useShortCut from "@renderer/hooks/useShortCut"
import Error from "@renderer/components/Error"
import { MutableRefObject, useEffect, useRef } from "react"
import useIgnoreMouseEvents from "@renderer/hooks/useIgnoreMouseEvents"
import { useStore } from "@renderer/store/useStore"
function Home(): JSX.Element {
const mainRef = useRef<HTMLDivElement>(null)
const {setIgnoreMouseEvents} = useIgnoreMouseEvents()
const config = useStore(state => state.config)
window.api.shortCut(config.shortCut)
useEffect(()=>{
setIgnoreMouseEvents(mainRef as MutableRefObject<HTMLDivElement>)
// //为开发方便,临时代码
// window.api.openConfigWindow()
}, [])
// // 注册快捷键
const {register} = useShortCut()
register()
return (
<CodeProvider>
<main className="relative" ref={mainRef}>

View File

@ -1,11 +1,13 @@
import { Form, useLoaderData, useSubmit } from 'react-router-dom'
import { Form, useLoaderData } from 'react-router-dom'
import styles from './styles.module.scss'
import { useState } from 'react'
import { useStore } from '@renderer/store/useStore'
export const Setting = () => {
const config = useLoaderData() as ConfigDataType
const submit = useSubmit()
// const config = useLoaderData() as ConfigDataType
const [keys, setKeys] = useState<string[]>([])
const config = useStore(state => state.config)
const setConfig = useStore(state => state.setConfig)
return (
<Form method="POST">
<main className={styles.settingPage}>
@ -19,23 +21,38 @@ export const Setting = () => {
readOnly
onKeyDown={(e) => {
if (e.metaKey || e.ctrlKey || e.altKey) {
keys.push(e.code.replace(/Left|Right|Key|Digit/, ''))
const code = e.code.replace(/Left|Right|Key|Digit/, '')
if (keys.includes(code)) return
keys.push(code)
setKeys(keys)
e.currentTarget.value = keys.join('+')
// 如果以数字或字母或者空格结尾
if (code.match(/^(\w|\s)$/gi)) {
e.currentTarget.value = keys.join('+')
setKeys([])
setConfig({...config, shortCut: e.currentTarget.value})
window.api.shortCut(e.currentTarget.value)
}
}
}}
onKeyUp={(e) => {
setKeys([])
console.log("keys", e.currentTarget.value)
submit(e.currentTarget.form, {method: 'POST'})
}}
/>
</section>
<section>
<h5></h5>
<input type="text" name="databaseDirectory" defaultValue={config.databaseDirectory} />
<input
type="text"
name="databaseDirectory"
readOnly
defaultValue={config.databaseDirectory}
onClick={
async (e)=>{
const path = await window.api.selectDatabaseDirectory()
setConfig({...config, databaseDirectory: path})
e.currentTarget.value = path
}
}
/>
</section>
</main>
</Form>

View File

@ -26,8 +26,6 @@ const router = createHashRouter([
children: [
{
index: true,
loader: SettingLoader,
action: SettingAction,
element: <Setting/>
},
{

View File

@ -1,6 +1,8 @@
import { DataType } from "@renderer/data";
import { create } from "zustand";
interface StateProps{
config: ConfigDataType,
setConfig: (config: ConfigDataType) => void,
data: DataType[],
setData: (data: DataType[]) => void,
search: string,
@ -13,6 +15,8 @@ interface StateProps{
setEditCategoryId: (id: number) => void
}
export const useStore = create<StateProps>((set) => ({
config: {shortCut: "", databaseDirectory: ""},
setConfig: (config) => set({config}),
data: [],
setData: (data) => set({data}),
search: "",

View File

@ -15,7 +15,7 @@ type ContentType = {
}
type WindowNameType = 'search' | 'config'
type WindowNameType = 'search' | 'config' | 'code'
type ConfigType = {
id: number