diff --git a/src-tauri/src/app/cmd.rs b/src-tauri/src/app/cmd.rs index 1da751b..45d077a 100644 --- a/src-tauri/src/app/cmd.rs +++ b/src-tauri/src/app/cmd.rs @@ -1,4 +1,7 @@ -use crate::{conf::ChatConfJson, utils::{self, exists}}; +use crate::{ + conf::ChatConfJson, + utils::{self, exists}, +}; use std::{collections::HashMap, fs, path::PathBuf}; use tauri::{api, command, AppHandle, Manager}; @@ -152,10 +155,15 @@ pub fn sync_prompts(app: AppHandle, data: String, time: u64) { let chatgpt_prompts = chat_root().join("cache_model").join("chatgpt_prompts.json"); if !exists(&model) { - fs::write(&model, serde_json::json!({ - "name": "ChatGPT Model", - "link": "https://github.com/lencx/ChatGPT" - }).to_string()).unwrap(); + fs::write( + &model, + serde_json::json!({ + "name": "ChatGPT Model", + "link": "https://github.com/lencx/ChatGPT" + }) + .to_string(), + ) + .unwrap(); } // chatgpt_prompts.json diff --git a/src-tauri/src/app/setup.rs b/src-tauri/src/app/setup.rs index 7d342a4..8c3eae6 100644 --- a/src-tauri/src/app/setup.rs +++ b/src-tauri/src/app/setup.rs @@ -1,5 +1,5 @@ use crate::{app::window, conf::ChatConfJson, utils}; -use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, Manager}; +use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, GlobalShortcutManager, Manager}; pub fn init(app: &mut App) -> std::result::Result<(), Box> { let chat_conf = ChatConfJson::get_chat_conf(); @@ -11,6 +11,27 @@ pub fn init(app: &mut App) -> std::result::Result<(), Box window::tray_window(&handle); }); + { + let handle = app.app_handle(); + let mut shortcut = app.global_shortcut_manager(); + let is_mini_key = shortcut.is_registered("CmdOrCtrl+Shift+O"); + + if !is_mini_key.unwrap() { + shortcut + .register("CmdOrCtrl+Shift+O", move || { + if let Some(w) = handle.get_window("core") { + if w.is_visible().unwrap() { + w.hide().unwrap(); + } else { + w.show().unwrap(); + w.set_focus().unwrap(); + } + } + }) + .unwrap(); + }; + } + if chat_conf.hide_dock_icon { #[cfg(target_os = "macos")] app.set_activation_policy(tauri::ActivationPolicy::Accessory); diff --git a/src-tauri/src/app/window.rs b/src-tauri/src/app/window.rs index 0ec5a81..64e90cc 100644 --- a/src-tauri/src/app/window.rs +++ b/src-tauri/src/app/window.rs @@ -16,10 +16,7 @@ pub fn tray_window(handle: &tauri::AppHandle) { .always_on_top(true) .theme(theme) .initialization_script(&utils::user_script()) - .initialization_script(include_str!("../assets/html2canvas.js")) - .initialization_script(include_str!("../assets/jspdf.js")) .initialization_script(include_str!("../assets/core.js")) - .initialization_script(include_str!("../assets/export.js")) .initialization_script(include_str!("../assets/cmd.js")) .user_agent(&chat_conf.ua_tray) .build() diff --git a/src-tauri/src/assets/cmd.js b/src-tauri/src/assets/cmd.js index 97164d7..bd7dd14 100644 --- a/src-tauri/src/assets/cmd.js +++ b/src-tauri/src/assets/cmd.js @@ -28,6 +28,9 @@ function init() { .chat-model-cmd-list .cmd-item:last-child { border-bottom: none; } + .chat-model-cmd-list .cmd-item.selected { + background: #fea; + } .chat-model-cmd-list .cmd-item b { display: inline-block; width: 100px; @@ -46,7 +49,16 @@ function init() { white-space: nowrap; text-align: right; color: #888; - }`; + } + .chatappico { + width: 20px; + height: 20px; + } + .chatappico.pdf { + width: 2px; + height: 24px; + } + `; document.head.append(styleDom); if (window.formInterval) { @@ -70,11 +82,24 @@ async function cmdTip() { // fix: tray window if (__TAURI_METADATA__.__currentWindow.label === 'tray') { - modelDom.style.bottom = '40px'; + modelDom.style.bottom = '54px'; } document.querySelector('form').appendChild(modelDom); - const itemDom = (v) => `
/${v.cmd}${v.act}
`; + const itemDom = (v) => `
/${v.cmd}${v.act}
`; + const renderList = (v) => { + modelDom.innerHTML = `
${v.map(itemDom).join('')}
`; + window.__CHAT_MODEL_CMD_PROMPT__ = v[0]?.prompt.trim(); + window.__CHAT_MODEL_CMD__ = v[0]?.cmd.trim(); + window.__list = modelDom.querySelectorAll('.cmd-item'); + window.__index = 0; + window.__list[window.__index].classList.add('selected'); + }; + const setPrompt = (v = '') => { + if (v.trim()) { + window.__CHAT_MODEL_CMD_PROMPT__ = window.__CHAT_MODEL_CMD_PROMPT__?.replace(/\{([^{}]*)\}/, `{${v.trim()}}`); + } + } const searchInput = document.querySelector('form textarea'); // Enter a command starting with `/` and press a space to automatically fill `chatgpt prompt`. @@ -84,6 +109,35 @@ async function cmdTip() { return; } + // ------------------ Keyboard scrolling (ArrowUp | ArrowDown) -------------------------- + if (event.keyCode === 38 && window.__index > 0) { // ArrowUp + window.__list[window.__index].classList.remove('selected'); + window.__index = window.__index - 1; + window.__list[window.__index].classList.add('selected'); + window.__CHAT_MODEL_CMD_PROMPT__ = decodeURIComponent(window.__list[window.__index].getAttribute('data-prompt')); + searchInput.value = `/${window.__list[window.__index].getAttribute('data-cmd')}`; + event.preventDefault(); + } + + if (event.keyCode === 40 && window.__index < window.__list.length - 1) { // ArrowDown + window.__list[window.__index].classList.remove('selected'); + window.__index = window.__index + 1; + window.__list[window.__index].classList.add('selected'); + window.__CHAT_MODEL_CMD_PROMPT__ = decodeURIComponent(window.__list[window.__index].getAttribute('data-prompt')); + searchInput.value = `/${window.__list[window.__index].getAttribute('data-cmd')}`; + event.preventDefault(); + } + + const containerHeight = modelDom.offsetHeight; + const itemHeight = window.__list[0].offsetHeight + 1; + + const itemTop = window.__list[window.__index].offsetTop; + const itemBottom = itemTop + itemHeight; + if (itemTop < modelDom.scrollTop || itemBottom > modelDom.scrollTop + containerHeight) { + modelDom.scrollTop = itemTop; + } + + // ------------------ TAB key replaces `{q}` tag content ------------------------------- // feat: https://github.com/lencx/ChatGPT/issues/54 if (event.keyCode === 9 && !window.__CHAT_MODEL_STATUS__) { const strGroup = window.__CHAT_MODEL_CMD_PROMPT__.match(/\{([^{}]*)\}/) || []; @@ -95,36 +149,37 @@ async function cmdTip() { event.preventDefault(); } - if (window.__CHAT_MODEL_STATUS__ === 1 && event.keyCode === 9) { + if (window.__CHAT_MODEL_STATUS__ === 1 && event.keyCode === 9) { // TAB const data = searchInput.value.split('|->'); if (data[1]?.trim()) { - window.__CHAT_MODEL_CMD_PROMPT__ = window.__CHAT_MODEL_CMD_PROMPT__?.replace(/\{([^{}]*)\}/, `{${data[1]?.trim()}}`); + setPrompt(data[1]); window.__CHAT_MODEL_STATUS__ = 2; } event.preventDefault(); } // input text - if (window.__CHAT_MODEL_STATUS__ === 2 && event.keyCode === 9) { + if (window.__CHAT_MODEL_STATUS__ === 2 && event.keyCode === 9) { // TAB searchInput.value = window.__CHAT_MODEL_CMD_PROMPT__; modelDom.innerHTML = ''; delete window.__CHAT_MODEL_STATUS__; event.preventDefault(); } - // type in a space to complete the fill + // ------------------ type in a space to complete the fill ------------------------------------ if (event.keyCode === 32) { searchInput.value = window.__CHAT_MODEL_CMD_PROMPT__; modelDom.innerHTML = ''; delete window.__CHAT_MODEL_CMD_PROMPT__; } - // send - if (event.keyCode === 13 && window.__CHAT_MODEL_CMD_PROMPT__) { + console.log('«174» /src/assets/cmd.js ~> ', window.__CHAT_MODEL_CMD_PROMPT__); + + + // ------------------ send -------------------------------------------------------------------- + if (event.keyCode === 13 && window.__CHAT_MODEL_CMD_PROMPT__) { // Enter const data = searchInput.value.split('|->'); - if (data[1]?.trim()) { - window.__CHAT_MODEL_CMD_PROMPT__ = window.__CHAT_MODEL_CMD_PROMPT__?.replace(/\{([^{}]*)\}/, `{${data[1]?.trim()}}`); - } + setPrompt(data[1]); searchInput.value = window.__CHAT_MODEL_CMD_PROMPT__; modelDom.innerHTML = ''; @@ -135,7 +190,7 @@ async function cmdTip() { } }); - searchInput.addEventListener('input', (event) => { + searchInput.addEventListener('input', () => { if (searchInput.value === '') { delete window.__CHAT_MODEL_CMD_PROMPT__; delete window.__CHAT_MODEL_CMD__; @@ -152,17 +207,13 @@ async function cmdTip() { // all cmd result if (query === '/') { - modelDom.innerHTML = `
${data.map(itemDom).join('')}
`; - window.__CHAT_MODEL_CMD_PROMPT__ = data[0]?.prompt.trim(); - window.__CHAT_MODEL_CMD__ = data[0]?.cmd.trim(); + renderList(data); return; } const result = data.filter(i => new RegExp(query.substring(1)).test(i.cmd)); if (result.length > 0) { - modelDom.innerHTML = `
${result.map(itemDom).join('')}
`; - window.__CHAT_MODEL_CMD_PROMPT__ = result[0]?.prompt.trim(); - window.__CHAT_MODEL_CMD__ = result[0]?.cmd.trim(); + renderList(result); } else { modelDom.innerHTML = ''; delete window.__CHAT_MODEL_CMD_PROMPT__; diff --git a/src-tauri/src/assets/core.js b/src-tauri/src/assets/core.js index 35715b6..a3b5d72 100644 --- a/src-tauri/src/assets/core.js +++ b/src-tauri/src/assets/core.js @@ -91,8 +91,6 @@ async function init() { const res = await fetch('https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv'); if (res.ok) { const data = await res.text(); - console.log('«94» /src/assets/core.js ~> ', data); - await invoke('sync_prompts', { data, time: Date.now() }); } else { invoke('messageDialog', { diff --git a/src-tauri/src/assets/export.js b/src-tauri/src/assets/export.js index f90a389..f2351e7 100644 --- a/src-tauri/src/assets/export.js +++ b/src-tauri/src/assets/export.js @@ -3,6 +3,7 @@ const buttonOuterHTMLFallback = ``; async function init() { + if (window.innerWidth < 767) return; const chatConf = await invoke('get_chat_conf') || {}; if (window.buttonsInterval) { clearInterval(window.buttonsInterval); @@ -88,7 +89,9 @@ function addActionsButtons(actionsArea, TryAgainButton) { const downloadButton = TryAgainButton.cloneNode(true); downloadButton.id = "download-png-button"; downloadButton.setAttribute("share-ext", "true"); - downloadButton.innerText = "Generate PNG"; + // downloadButton.innerText = "Generate PNG"; + downloadButton.title = "Generate PNG"; + downloadButton.innerHTML = setIcon('png'); downloadButton.onclick = () => { downloadThread(); }; @@ -96,7 +99,9 @@ function addActionsButtons(actionsArea, TryAgainButton) { const downloadPdfButton = TryAgainButton.cloneNode(true); downloadPdfButton.id = "download-pdf-button"; downloadButton.setAttribute("share-ext", "true"); - downloadPdfButton.innerText = "Download PDF"; + // downloadPdfButton.innerText = "Download PDF"; + downloadPdfButton.title = "Download PDF"; + downloadPdfButton.innerHTML = setIcon('pdf'); downloadPdfButton.onclick = () => { downloadThread({ as: Format.PDF }); }; @@ -104,7 +109,9 @@ function addActionsButtons(actionsArea, TryAgainButton) { const exportHtml = TryAgainButton.cloneNode(true); exportHtml.id = "download-html-button"; downloadButton.setAttribute("share-ext", "true"); - exportHtml.innerText = "Share Link"; + // exportHtml.innerText = "Share Link"; + exportHtml.title = "Share Link"; + exportHtml.innerHTML = setIcon('link'); exportHtml.onclick = () => { sendRequest(); }; @@ -269,4 +276,12 @@ if ( init(); } else { document.addEventListener("DOMContentLoaded", init); -} \ No newline at end of file +} + +function setIcon(type) { + return { + link: ``, + png: ``, + pdf: `` + }[type]; +}