diff --git a/app.vue b/app.vue
index 41027d2..fa71e44 100644
--- a/app.vue
+++ b/app.vue
@@ -33,10 +33,15 @@
@click="selectItem(groupIndex, index)"
:ref="el => { if (isSelected(groupIndex, index)) selectedElement = el as HTMLElement }">
-
-
+
+
-
+
@@ -49,8 +54,8 @@
-
+
{{ selectedItem?.content || '' }}
@@ -95,6 +100,9 @@ const selectedItemIndex: Ref = ref(0);
const selectedElement: Ref = ref(null);
const searchInput: Ref = ref(null);
const os: Ref = ref('');
+const imageLoadError = ref(false);
+const imageLoading = ref(true);
+const imageUrls: Ref> = shallowRef({});
const groupedHistory: ComputedRef = computed(() => {
const now = new Date();
@@ -205,7 +213,7 @@ const selectItem = (groupIndex: number, itemIndex: number): void => {
const pasteSelectedItem = async (): Promise => {
if (!selectedItem.value) return;
-
+
let content = selectedItem.value.content;
let contentType: String = selectedItem.value.content_type;
if (contentType === 'image') {
@@ -217,9 +225,9 @@ const pasteSelectedItem = async (): Promise => {
}
}
await hideApp();
- await invoke("write_and_paste", {
- content,
- contentType
+ await invoke("write_and_paste", {
+ content,
+ contentType
});
};
@@ -255,52 +263,74 @@ const getFaviconFromDb = (favicon: string): string => {
const getImageDimensions = (path: string): Promise => {
return new Promise(async (resolve) => {
const img = new Image();
- img.onload = () => resolve(`${img.width}x${img.height}`);
- img.onerror = () => resolve('0x0');
- if (path.includes('AppData\\Roaming\\net.pandadev.qopy\\images\\')) {
- const filename = path.split('\\').pop();
- try {
- const imageData = await invoke("read_image", { filename: filename });
- const blob = new Blob([imageData], { type: 'image/png' });
- img.src = URL.createObjectURL(blob);
- } catch (error) {
- console.error('Error reading image file:', error);
- resolve('0x0');
- }
- } else {
- img.src = `data:image/png;base64,${path}`;
+ img.onload = () => {
+ imageLoadError.value = false;
+ imageLoading.value = false;
+ resolve(`${img.width}x${img.height}`);
+ };
+ img.onerror = (e) => {
+ console.error('Error loading image:', e);
+ imageLoadError.value = true;
+ imageLoading.value = false;
+ resolve('0x0');
+ };
+
+ try {
+ imageLoading.value = true;
+ const dataUrl = await getImageUrl(path);
+ img.src = dataUrl;
+ } catch (error) {
+ console.error('Error getting image URL:', error);
+ imageLoadError.value = true;
+ imageLoading.value = false;
+ resolve('0x0');
}
});
};
-const imageUrls: Ref> = shallowRef({});
+const getImageUrl = async (path: string): Promise => {
+ const isWindows = path.includes('\\');
+ const separator = isWindows ? '\\' : '/';
+ const filename = path.split(separator).pop();
+
+ try {
+ imageLoading.value = true;
+ const base64 = await invoke("read_image", { filename });
+ console.log('Image data received, length:', base64.length);
+ if (!base64 || base64.length === 0) {
+ throw new Error('Received empty image data');
+ }
+
+ const dataUrl = `data:image/png;base64,${base64}`;
+
+ console.log('Data URL preview:', dataUrl.substring(0, 50) + '...');
+
+ imageLoadError.value = false;
+ imageLoading.value = false;
+ return dataUrl;
+ } catch (error) {
+ console.error('Error reading image file:', error);
+ imageLoadError.value = true;
+ imageLoading.value = false;
+ return '';
+ }
+};
const getComputedImageUrl = (item: HistoryItem): string => {
if (!imageUrls.value[item.id]) {
imageUrls.value[item.id] = '';
- getImageUrl(item.content).then(url => {
- imageUrls.value = { ...imageUrls.value, [item.id]: url };
- });
+ getImageUrl(item.content)
+ .then(url => {
+ imageUrls.value = { ...imageUrls.value, [item.id]: url };
+ })
+ .catch(error => {
+ console.error('Failed to get image URL:', error);
+ imageUrls.value = { ...imageUrls.value, [item.id]: '' };
+ });
}
return imageUrls.value[item.id] || '';
};
-const getImageUrl = async (path: string): Promise => {
- if (path.includes('AppData\\Roaming\\net.pandadev.qopy\\images\\')) {
- const filename = path.split('\\').pop();
- try {
- const imageData = await invoke("read_image", { filename: filename });
- const blob = new Blob([imageData], { type: 'image/png' });
- return URL.createObjectURL(blob);
- } catch (error) {
- console.error('Error reading image file:', error);
- return '';
- }
- } else {
- return `data:image/png;base64,${path}`;
- }
-};
-
const loadHistoryChunk = async (): Promise => {
if (!db.value || isLoading) return;
@@ -328,6 +358,7 @@ const loadHistoryChunk = async (): Promise => {
const processedChunk = await Promise.all(results.map(async item => {
if (item.content_type === 'image') {
const dimensions = await getImageDimensions(item.content);
+ getComputedImageUrl(item);
return { ...item, dimensions };
}
return item;
@@ -340,10 +371,10 @@ const loadHistoryChunk = async (): Promise => {
const handleScroll = (): void => {
if (!resultsContainer.value) return;
-
+
const { viewport } = resultsContainer.value?.osInstance().elements() ?? {};
const { scrollTop = 0, scrollHeight = 0, clientHeight = 0 } = viewport ?? {};
-
+
if (scrollHeight - scrollTop - clientHeight < 100) {
loadHistoryChunk();
}
diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json
index 10e711b..883a577 100644
--- a/src-tauri/capabilities/default.json
+++ b/src-tauri/capabilities/default.json
@@ -28,6 +28,7 @@
"core:window:allow-show",
"core:window:allow-set-focus",
"core:window:allow-is-focused",
- "core:window:allow-is-visible"
+ "core:window:allow-is-visible",
+ "fs:allow-read"
]
}
\ No newline at end of file
diff --git a/src-tauri/src/api/clipboard.rs b/src-tauri/src/api/clipboard.rs
index e382aa0..c587cb4 100644
--- a/src-tauri/src/api/clipboard.rs
+++ b/src-tauri/src/api/clipboard.rs
@@ -24,11 +24,12 @@ pub fn set_app_data_dir(path: std::path::PathBuf) {
}
#[tauri::command]
-pub fn read_image(filename: String) -> Result, String> {
+pub fn read_image(filename: String) -> Result {
let app_data_dir = APP_DATA_DIR.lock().unwrap();
let app_data_dir = app_data_dir.as_ref().expect("App data directory not set");
let image_path = app_data_dir.join("images").join(filename);
- fs::read(image_path).map_err(|e| e.to_string())
+ let image_data = fs::read(image_path).map_err(|e| e.to_string())?;
+ Ok(STANDARD.encode(image_data))
}
#[tauri::command]
@@ -107,26 +108,22 @@ pub fn setup(app: &AppHandle) {
let app = app.clone();
runtime.block_on(async move {
if IS_PROGRAMMATIC_PASTE.load(Ordering::SeqCst) {
- println!("Ignoring programmatic paste");
return;
}
let clipboard = app.state::();
let available_types = clipboard.available_types().unwrap();
- println!("Clipboard update detected");
-
match get_pool(&app).await {
Ok(pool) => {
if available_types.image {
println!("Handling image change");
if let Ok(image_data) = clipboard.read_image_base64() {
- let base64_image = STANDARD.encode(&image_data);
insert_content_if_not_exists(
app.clone(),
pool.clone(),
"image",
- base64_image,
+ image_data,
)
.await;
}
diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs
index eaa23e6..9138326 100644
--- a/src-tauri/src/api/hotkeys.rs
+++ b/src-tauri/src/api/hotkeys.rs
@@ -3,6 +3,7 @@ use tauri::Manager;
use crate::utils::commands::center_window_on_current_monitor;
+#[warn(dead_code)]
pub fn setup(app_handle: tauri::AppHandle) {
std::thread::spawn(move || {
let mut meta_pressed = false;
diff --git a/src-tauri/src/api/tray.rs b/src-tauri/src/api/tray.rs
index d332489..bf2af58 100644
--- a/src-tauri/src/api/tray.rs
+++ b/src-tauri/src/api/tray.rs
@@ -1,13 +1,12 @@
use tauri::{
menu::{MenuBuilder, MenuItemBuilder},
- tray::{MouseButton, TrayIconBuilder, TrayIconEvent},
+ tray::TrayIconBuilder,
Manager,
};
pub fn setup(app: &mut tauri::App) -> Result<(), Box> {
let window = app.get_webview_window("main").unwrap();
let window_clone_for_tray = window.clone();
- let window_clone_for_click = window.clone();
let icon_bytes = include_bytes!("../../icons/Square71x71Logo.png");
let icon = tauri::image::Image::from_bytes(icon_bytes).unwrap();
@@ -37,14 +36,6 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box> {
}
_ => (),
})
- // .on_tray_icon_event(move |_tray, event| {
- // if let TrayIconEvent::Click { button, .. } = event {
- // if button == MouseButton::Left {
- // window_clone_for_click.show().unwrap();
- // window_clone_for_click.set_focus().unwrap();
- // }
- // }
- // })
.icon(icon)
.build(app)?;