feat: switch origin

This commit is contained in:
lencx
2022-12-12 01:32:41 +08:00
parent 3eac43541e
commit 78f8daab86
9 changed files with 150 additions and 29 deletions

View File

@@ -14,11 +14,11 @@ rust-version = "1.57"
tauri-build = {version = "1.2.1", features = [] } tauri-build = {version = "1.2.1", features = [] }
[dependencies] [dependencies]
anyhow = "1.0.66"
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2.1", features = ["api-all", "devtools", "system-tray", "updater"] } tauri = { version = "1.2.2", features = ["api-all", "devtools", "system-tray", "updater"] }
tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] } tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] }
anyhow = "1.0.66"
[features] [features]
# by default Tauri runs in production mode # by default Tauri runs in production mode

View File

@@ -33,3 +33,30 @@ pub fn open_link(app: AppHandle, url: String) {
pub fn get_chat_conf() -> ChatConfJson { pub fn get_chat_conf() -> ChatConfJson {
ChatConfJson::get_chat_conf() ChatConfJson::get_chat_conf()
} }
#[command]
pub fn form_confirm(app: AppHandle, data: serde_json::Value) {
ChatConfJson::amend(&serde_json::json!(data)).unwrap();
tauri::api::process::restart(&app.env());
}
#[command]
pub fn form_cancel(app: AppHandle, label: &str, title: &str, msg: &str) {
let win = app.app_handle().get_window(label).unwrap();
tauri::api::dialog::ask(
app.app_handle().get_window(label).as_ref(),
title,
msg,
move |is_cancel| {
if is_cancel {
win.close().unwrap();
}
},
);
}
#[command]
pub fn form_msg(app: AppHandle, label: &str, title: &str, msg: &str) {
let win = app.app_handle().get_window(label);
tauri::api::dialog::message(win.as_ref(), title, msg);
}

View File

@@ -10,7 +10,8 @@ use tauri::{
use tauri_plugin_positioner::{on_tray_event, Position, WindowExt}; use tauri_plugin_positioner::{on_tray_event, Position, WindowExt};
// --- Menu // --- Menu
pub fn init(chat_conf: &conf::ChatConfJson, context: &Context<EmbeddedAssets>) -> Menu { pub fn init(context: &Context<EmbeddedAssets>) -> Menu {
let chat_conf = ChatConfJson::get_chat_conf();
let name = &context.package_info().name; let name = &context.package_info().name;
let app_menu = Submenu::new( let app_menu = Submenu::new(
name, name,

View File

@@ -5,10 +5,8 @@ use crate::{
}; };
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, Manager}; use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, Manager};
pub fn init( pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
app: &mut App, let chat_conf = ChatConfJson::get_chat_conf();
chat_conf: ChatConfJson,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
let url = chat_conf.origin.to_string(); let url = chat_conf.origin.to_string();
let theme = ChatConfJson::theme(); let theme = ChatConfJson::theme();
window::mini_window(&app.app_handle()); window::mini_window(&app.app_handle());

View File

@@ -25,14 +25,17 @@ pub fn mini_window(handle: &tauri::AppHandle) {
} }
pub fn origin_window(handle: &tauri::AppHandle) { pub fn origin_window(handle: &tauri::AppHandle) {
let theme = conf::ChatConfJson::theme(); let chat_conf = conf::ChatConfJson::get_chat_conf();
// tauri://localhost/origin
WindowBuilder::new(handle, "main", WindowUrl::External("/".parse().unwrap())) // let url = chat_conf.origin;
WindowBuilder::new(handle, "origin", WindowUrl::App(chat_conf.origin.into()))
.resizable(false) .resizable(false)
.fullscreen(false) .fullscreen(false)
.inner_size(400.0, 300.0) .inner_size(400.0, 300.0)
.always_on_top(true) .always_on_top(true)
.theme(theme) .decorations(false)
.initialization_script(include_str!("../assets/core.js"))
.initialization_script(include_str!("../assets/origin.js"))
.build() .build()
.unwrap(); .unwrap();
} }

View File

@@ -2,6 +2,7 @@
// @ref: https://github.com/liady/ChatGPT-pdf/blob/main/src/content_script.js // @ref: https://github.com/liady/ChatGPT-pdf/blob/main/src/content_script.js
async function init() { async function init() {
const chatConf = await invoke('get_chat_conf') || {};
if (window.buttonsInterval) { if (window.buttonsInterval) {
clearInterval(window.buttonsInterval); clearInterval(window.buttonsInterval);
} }
@@ -16,7 +17,7 @@ async function init() {
}); });
if (hasTryAgainButton && buttons.length === 1) { if (hasTryAgainButton && buttons.length === 1) {
const TryAgainButton = actionsArea.querySelector("button"); const TryAgainButton = actionsArea.querySelector("button");
addActionsButtons(actionsArea, TryAgainButton); addActionsButtons(actionsArea, TryAgainButton, chatConf);
} else if (!hasTryAgainButton) { } else if (!hasTryAgainButton) {
removeButtons(); removeButtons();
} }
@@ -28,7 +29,7 @@ const Format = {
PDF: "pdf", PDF: "pdf",
}; };
function addActionsButtons(actionsArea, TryAgainButton) { function addActionsButtons(actionsArea, TryAgainButton, chatConf) {
const downloadButton = TryAgainButton.cloneNode(true); const downloadButton = TryAgainButton.cloneNode(true);
downloadButton.id = "download-png-button"; downloadButton.id = "download-png-button";
downloadButton.innerText = "Generate PNG"; downloadButton.innerText = "Generate PNG";
@@ -36,6 +37,7 @@ function addActionsButtons(actionsArea, TryAgainButton) {
downloadThread(); downloadThread();
}; };
actionsArea.appendChild(downloadButton); actionsArea.appendChild(downloadButton);
const downloadPdfButton = TryAgainButton.cloneNode(true); const downloadPdfButton = TryAgainButton.cloneNode(true);
downloadPdfButton.id = "download-pdf-button"; downloadPdfButton.id = "download-pdf-button";
downloadPdfButton.innerText = "Download PDF"; downloadPdfButton.innerText = "Download PDF";
@@ -43,13 +45,16 @@ function addActionsButtons(actionsArea, TryAgainButton) {
downloadThread({ as: Format.PDF }); downloadThread({ as: Format.PDF });
}; };
actionsArea.appendChild(downloadPdfButton); actionsArea.appendChild(downloadPdfButton);
const exportHtml = TryAgainButton.cloneNode(true);
exportHtml.id = "download-html-button"; if (new RegExp('//chat.openai.com').test(chatConf.origin)) {
exportHtml.innerText = "Share Link"; const exportHtml = TryAgainButton.cloneNode(true);
exportHtml.onclick = () => { exportHtml.id = "download-html-button";
sendRequest(); exportHtml.innerText = "Share Link";
}; exportHtml.onclick = () => {
actionsArea.appendChild(exportHtml); sendRequest();
};
actionsArea.appendChild(exportHtml);
}
} }
function removeButtons() { function removeButtons() {

View File

@@ -0,0 +1,71 @@
function init() {
document.body.innerHTML = `<style>
body {
height: 100vh;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: Söhne,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,Helvetica Neue,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
}
input {
all: unset;
width: 280px;
height: 30px;
margin-bottom: 10px;
padding: 0 5px;
border: solid 2px #d8d8d8;
}
button {
all: unset;
height: 30px;
font-size: 16px;
padding: 0 10px;
line-height: 30px;
margin: 0 5px;
color: #fff;
border-radius: 5px;
cursor: pointer;
}
#cancel {
background-color: #999;
}
#confirm {
background-color: #10a37f;
}
</style>
<h3>Switch Origin</h3>
<input id="input" type="text" />
<div class="btns">
<button id="cancel">Cancel</button>
<button id="confirm">Confirm</button>
</div>`;
const srcipt = document.createElement('script');
srcipt.innerHTML = `const input = document.getElementById('input');
const cancelBtn = document.getElementById('cancel');
const confirmBtn = document.getElementById('confirm');
cancelBtn.addEventListener('click', () => {
window.invoke('form_cancel', { label: 'origin', title: 'Switch Origin', msg: 'Sure you want to give up the switch?' });
})
confirmBtn.addEventListener('click', () => {
if (/^https?:\\/\\//.test(input.value)) {
window.invoke('form_confirm', { data: { origin: input.value } });
} else {
window.invoke('form_msg', { label: 'origin', title: 'Switch Origin', msg: 'Invalid URL!' });
}
})`;
document.head.appendChild(srcipt);
}
// run init
if (
document.readyState === "complete" ||
document.readyState === "interactive"
) {
init();
} else {
document.addEventListener("DOMContentLoaded", init);
}

View File

@@ -12,7 +12,8 @@ pub const DEFAULT_CHAT_CONF: &str = r#"{
"always_on_top": false, "always_on_top": false,
"theme": "Light", "theme": "Light",
"titlebar": true, "titlebar": true,
"origin": "https://chat.openai.com/" "default_origin": "https://chat.openai.com",
"origin": "https://chat.openai.com"
}"#; }"#;
pub struct ChatState { pub struct ChatState {
@@ -32,6 +33,7 @@ pub struct ChatConfJson {
pub always_on_top: bool, pub always_on_top: bool,
pub theme: String, pub theme: String,
pub titlebar: bool, pub titlebar: bool,
pub default_origin: String,
pub origin: String, pub origin: String,
} }
@@ -42,10 +44,22 @@ impl ChatConfJson {
let conf_file = ChatConfJson::conf_path(); let conf_file = ChatConfJson::conf_path();
if !exists(&conf_file) { if !exists(&conf_file) {
create_file(&conf_file).unwrap(); create_file(&conf_file).unwrap();
fs::write(&conf_file, DEFAULT_CHAT_CONF).unwrap();
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
ChatConfJson::amend(&serde_json::json!({ "titlebar": false })).unwrap(); fs::write(
&conf_file,
r#"{
"always_on_top": false,
"theme": "Light",
"titlebar": false,
"default_origin": "https://chat.openai.com",
"origin": "https://chat.openai.com"
}"#,
)
.unwrap();
#[cfg(not(target_os = "macos"))]
fs::write(&conf_file, DEFAULT_CHAT_CONF).unwrap();
} }
conf_file conf_file
} }

View File

@@ -8,26 +8,28 @@ mod conf;
mod utils; mod utils;
use app::{cmd, menu, setup}; use app::{cmd, menu, setup};
use conf::ChatConfJson; use conf::{ChatConfJson, ChatState};
fn main() { fn main() {
ChatConfJson::init(); ChatConfJson::init();
let context = tauri::generate_context!();
let chat_conf = ChatConfJson::get_chat_conf(); let chat_conf = ChatConfJson::get_chat_conf();
let chat_conf2 = chat_conf.clone(); let context = tauri::generate_context!();
tauri::Builder::default() tauri::Builder::default()
.manage(conf::ChatState::default(chat_conf.clone())) .manage(ChatState::default(chat_conf))
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
cmd::drag_window, cmd::drag_window,
cmd::fullscreen, cmd::fullscreen,
cmd::download, cmd::download,
cmd::open_link, cmd::open_link,
cmd::get_chat_conf, cmd::get_chat_conf,
cmd::form_cancel,
cmd::form_confirm,
cmd::form_msg,
]) ])
.setup(|app| setup::init(app, chat_conf2)) .setup(setup::init)
.plugin(tauri_plugin_positioner::init()) .plugin(tauri_plugin_positioner::init())
.menu(menu::init(&chat_conf, &context)) .menu(menu::init(&context))
.system_tray(menu::tray_menu()) .system_tray(menu::tray_menu())
.on_menu_event(menu::menu_handler) .on_menu_event(menu::menu_handler)
.on_system_tray_event(menu::tray_handler) .on_system_tray_event(menu::tray_handler)