add auto skip when outside of VRChat

This commit is contained in:
mii443
2024-09-27 21:13:38 +09:00
parent 8397c29187
commit 4e07a1ebf0
9 changed files with 48 additions and 21 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "vrclipboard-ime-gui", "name": "vrclipboard-ime-gui",
"private": true, "private": true,
"version": "1.8.0", "version": "1.9.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -1,5 +1,5 @@
{ {
"url": "https://r2-vrime.mii.dev/releases/vrclipboard-ime-gui_1.8.0_x64_ja-JP.msi.zip", "url": "https://r2-vrime.mii.dev/releases/vrclipboard-ime-gui_1.9.0_x64_ja-JP.msi.zip",
"version": "1.8.0", "version": "1.8.0",
"notes": "ログの出力を改善", "notes": "ログの出力を改善",
"pub_date": "2024-09-25T14:51:05+00:00", "pub_date": "2024-09-25T14:51:05+00:00",

2
src-tauri/Cargo.lock generated
View File

@ -3903,7 +3903,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "vrclipboard-ime-gui" name = "vrclipboard-ime-gui"
version = "1.8.0" version = "1.9.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"calc", "calc",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "vrclipboard-ime-gui" name = "vrclipboard-ime-gui"
version = "1.8.0" version = "1.9.0"
description = "VRClipboard IME" description = "VRClipboard IME"
authors = ["mii"] authors = ["mii"]
edition = "2021" edition = "2021"
@ -41,6 +41,7 @@ features = [
"Win32_UI_Input_Ime", "Win32_UI_Input_Ime",
"Win32_UI_TextServices", "Win32_UI_TextServices",
"Win32_UI_Input_KeyboardAndMouse", "Win32_UI_Input_KeyboardAndMouse",
"Win32_System_DataExchange",
"Win32_UI_WindowsAndMessaging" "Win32_UI_WindowsAndMessaging"
] ]

View File

@ -24,7 +24,9 @@ pub struct Config {
#[serde(default = "bool_true")] #[serde(default = "bool_true")]
pub skip_url: bool, pub skip_url: bool,
#[serde(default = "bool_false")] #[serde(default = "bool_false")]
pub use_tsf_reconvert: bool pub use_tsf_reconvert: bool,
#[serde(default = "bool_true")]
pub skip_on_out_of_vrc: bool,
} }
impl Default for Config { impl Default for Config {
@ -36,7 +38,8 @@ impl Default for Config {
ignore_prefix: true, ignore_prefix: true,
on_copy_mode: OnCopyMode::ReturnToChatbox, on_copy_mode: OnCopyMode::ReturnToChatbox,
skip_url: true, skip_url: true,
use_tsf_reconvert: false use_tsf_reconvert: false,
skip_on_out_of_vrc: true,
} }
} }
} }

View File

@ -6,6 +6,7 @@ use clipboard_master::{ClipboardHandler, CallbackResult};
use regex::Regex; use regex::Regex;
use rosc::{encoder, OscMessage, OscPacket, OscType}; use rosc::{encoder, OscMessage, OscPacket, OscType};
use tauri::{AppHandle, Manager}; use tauri::{AppHandle, Manager};
use windows::Win32::System::DataExchange::GetClipboardOwner;
use crate::{config::{Config, OnCopyMode}, conversion::Conversion, tsf_conversion::TsfConversion, Log, STATE}; use crate::{config::{Config, OnCopyMode}, conversion::Conversion, tsf_conversion::TsfConversion, Log, STATE};
use anyhow::Result; use anyhow::Result;
use tracing::{info, warn, error}; use tracing::{info, warn, error};
@ -34,6 +35,10 @@ impl ConversionHandler {
} }
impl ConversionHandler { impl ConversionHandler {
fn clipboard_has_owner(&mut self) -> bool {
unsafe { GetClipboardOwner() }.is_ok()
}
fn tsf_conversion(&mut self, contents: &str, config: &Config) -> Result<()> { fn tsf_conversion(&mut self, contents: &str, config: &Config) -> Result<()> {
if contents.chars().count() > 140 { if contents.chars().count() > 140 {
info!("Content exceeds 140 characters, skipping TSF conversion"); info!("Content exceeds 140 characters, skipping TSF conversion");
@ -126,6 +131,11 @@ impl ConversionHandler {
impl ClipboardHandler for ConversionHandler { impl ClipboardHandler for ConversionHandler {
fn on_clipboard_change(&mut self) -> CallbackResult { fn on_clipboard_change(&mut self) -> CallbackResult {
let config = self.get_config(); let config = self.get_config();
if config.skip_on_out_of_vrc && self.clipboard_has_owner() {
info!("Clipboard has owner (maybe from outside of VRChat), skipping conversion");
return CallbackResult::Next;
}
if let Ok(mut contents) = self.clipboard_ctx.get_contents() { if let Ok(mut contents) = self.clipboard_ctx.get_contents() {
if config.use_tsf_reconvert { if config.use_tsf_reconvert {
if let Err(e) = self.tsf_conversion(&contents, &config) { if let Err(e) = self.tsf_conversion(&contents, &config) {

View File

@ -7,7 +7,7 @@
}, },
"package": { "package": {
"productName": "vrclipboard-ime-gui", "productName": "vrclipboard-ime-gui",
"version": "1.8.0" "version": "1.9.0"
}, },
"tauri": { "tauri": {
"updater": { "updater": {

View File

@ -10,6 +10,7 @@ interface Config {
on_copy_mode: OnCopyMode; on_copy_mode: OnCopyMode;
skip_url: boolean; skip_url: boolean;
use_tsf_reconvert: boolean; use_tsf_reconvert: boolean;
skip_on_out_of_vrc: boolean;
} }
enum OnCopyMode { enum OnCopyMode {
@ -26,7 +27,8 @@ const SettingsComponent = () => {
ignore_prefix: false, ignore_prefix: false,
on_copy_mode: OnCopyMode.ReturnToChatbox, on_copy_mode: OnCopyMode.ReturnToChatbox,
skip_url: true, skip_url: true,
use_tsf_reconvert: false use_tsf_reconvert: false,
skip_on_out_of_vrc: true,
}); });
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null); const dropdownRef = useRef<HTMLDivElement>(null);
@ -48,9 +50,9 @@ const SettingsComponent = () => {
} }
}; };
const saveSettings = async () => { const saveSettings = async (newSettings: Config) => {
try { try {
await invoke('save_settings', { config: settings }); await invoke('save_settings', { config: newSettings });
alert('設定が正常に保存されました。'); alert('設定が正常に保存されました。');
} catch (error) { } catch (error) {
console.error('Failed to save settings:', error); console.error('Failed to save settings:', error);
@ -60,15 +62,19 @@ const SettingsComponent = () => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value, type, checked } = e.target; const { name, value, type, checked } = e.target;
setSettings(prev => ({ const newSettings = {
...prev, ...settings,
[name]: type === 'checkbox' ? checked : value [name]: type === 'checkbox' ? checked : value
})); };
setSettings(newSettings);
saveSettings(newSettings);
}; };
const handleSelectChange = (value: OnCopyMode) => { const handleSelectChange = (value: OnCopyMode) => {
setSettings(prev => ({ ...prev, on_copy_mode: value })); const newSettings = { ...settings, on_copy_mode: value };
setSettings(newSettings);
setIsOpen(false); setIsOpen(false);
saveSettings(newSettings);
}; };
const handleClickOutside = (event: MouseEvent) => { const handleClickOutside = (event: MouseEvent) => {
@ -195,12 +201,19 @@ const SettingsComponent = () => {
Windows10または11を使用している場合は Microsoft IME 使 Windows10または11を使用している場合は Microsoft IME 使
</label> </label>
</div> </div>
<button <div className="flex items-center">
onClick={saveSettings} <input
className="bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 transition-colors" type="checkbox"
> id="skip_on_out_of_vrc"
name="skip_on_out_of_vrc"
</button> checked={settings.skip_on_out_of_vrc}
onChange={handleChange}
className="mr-2"
/>
<label htmlFor="skip_on_out_of_vrc" className="text-sm font-medium text-gray-700">
VRChat以外からのコピーをスキップ
</label>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -10,7 +10,7 @@ const TitleBar = () => {
<div className="flex justify-between items-center bg-gray-800 text-white h-8 px-2" data-tauri-drag-region> <div className="flex justify-between items-center bg-gray-800 text-white h-8 px-2" data-tauri-drag-region>
<div className="flex items-center"> <div className="flex items-center">
<span className="text-sm font-semibold">VRClipboard-IME</span> <span className="text-sm font-semibold">VRClipboard-IME</span>
<span className="text-xs font-semibold ml-2">v1.7.0</span> <span className="text-xs font-semibold ml-2">v1.9.0</span>
</div> </div>
<div className="flex"> <div className="flex">
<button onClick={handleMinimize} className="p-1 hover:bg-gray-700 focus:outline-none"> <button onClick={handleMinimize} className="p-1 hover:bg-gray-700 focus:outline-none">