mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 17:29:55 -05:00
Fix: Clear Moku Cache & SelectPortal Zoom (#82)
This commit is contained in:
@@ -58,12 +58,31 @@ pub fn exit_app(app: tauri::AppHandle) {
|
|||||||
app.exit(0);
|
app.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_dir_best_effort(path: &std::path::Path) {
|
||||||
|
if path.is_file() {
|
||||||
|
if let Err(e) = std::fs::remove_file(path) {
|
||||||
|
if e.raw_os_error() == Some(32) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if path.is_dir() {
|
||||||
|
if let Ok(entries) = std::fs::read_dir(path) {
|
||||||
|
for entry in entries.flatten() {
|
||||||
|
remove_dir_best_effort(&entry.path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = std::fs::remove_dir(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn clear_moku_cache(app: tauri::AppHandle) -> Result<(), String> {
|
pub async fn clear_moku_cache(app: tauri::AppHandle) -> Result<(), String> {
|
||||||
use tauri::Manager;
|
let window = app.get_webview_window("main").ok_or("no main window")?;
|
||||||
|
window.clear_all_browsing_data().map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let cache_dir = app.path().app_cache_dir().map_err(|e| e.to_string())?;
|
let cache_dir = app.path().app_cache_dir().map_err(|e| e.to_string())?;
|
||||||
if cache_dir.exists() {
|
if cache_dir.exists() {
|
||||||
std::fs::remove_dir_all(&cache_dir).map_err(|e| e.to_string())?;
|
remove_dir_best_effort(&cache_dir);
|
||||||
std::fs::create_dir_all(&cache_dir).map_err(|e| e.to_string())?;
|
std::fs::create_dir_all(&cache_dir).map_err(|e| e.to_string())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const GET_SOURCES = `
|
|||||||
sources {
|
sources {
|
||||||
nodes {
|
nodes {
|
||||||
id name lang displayName iconUrl isNsfw
|
id name lang displayName iconUrl isNsfw
|
||||||
isConfigurable supportsLatest baseUrl
|
isConfigurable supportsLatest
|
||||||
extension { pkgName }
|
extension { pkgName }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ export const GET_MIGRATABLE_SOURCES = `
|
|||||||
nodes {
|
nodes {
|
||||||
sourceId
|
sourceId
|
||||||
source {
|
source {
|
||||||
id name lang displayName iconUrl isNsfw isConfigurable supportsLatest baseUrl
|
id name lang displayName iconUrl isNsfw isConfigurable supportsLatest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,30 @@
|
|||||||
import type { Attachment } from "svelte/attachments";
|
import type { Attachment } from "svelte/attachments";
|
||||||
|
|
||||||
/**
|
|
||||||
* {@attach selectPortal(triggerEl)}
|
|
||||||
*
|
|
||||||
* Moves the decorated element to <body> and positions it below `triggerEl`.
|
|
||||||
* The element stays reactive — Svelte still owns its DOM, we just re-parent it.
|
|
||||||
*
|
|
||||||
* The portalled menu element is stored on `triggerEl.__selectMenuEl` so that
|
|
||||||
* the outside-click guard in Settings.svelte can exclude it from dismissal.
|
|
||||||
*/
|
|
||||||
export function selectPortal(triggerEl: HTMLElement & { __selectMenuEl?: HTMLElement | null }): Attachment {
|
export function selectPortal(triggerEl: HTMLElement & { __selectMenuEl?: HTMLElement | null }): Attachment {
|
||||||
return (menuEl: HTMLElement) => {
|
return (menuEl: HTMLElement) => {
|
||||||
// Position & move to body
|
|
||||||
function position() {
|
function position() {
|
||||||
|
const zoom = parseFloat(document.documentElement.style.zoom) / 100 || 1;
|
||||||
const r = triggerEl.getBoundingClientRect();
|
const r = triggerEl.getBoundingClientRect();
|
||||||
|
|
||||||
|
const top = r.bottom / zoom + 4;
|
||||||
|
const right = r.right / zoom;
|
||||||
|
const width = menuEl.offsetWidth;
|
||||||
|
const left = Math.max(8, right - width);
|
||||||
|
|
||||||
menuEl.style.position = "fixed";
|
menuEl.style.position = "fixed";
|
||||||
menuEl.style.top = `${r.bottom + 4}px`;
|
menuEl.style.top = `${top}px`;
|
||||||
menuEl.style.left = `${r.right - menuEl.offsetWidth}px`;
|
menuEl.style.left = `${left}px`;
|
||||||
// clamp to viewport left edge
|
|
||||||
const left = parseFloat(menuEl.style.left);
|
|
||||||
if (left < 8) menuEl.style.left = "8px";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menuEl.style.visibility = "hidden";
|
||||||
document.body.appendChild(menuEl);
|
document.body.appendChild(menuEl);
|
||||||
triggerEl.__selectMenuEl = menuEl;
|
triggerEl.__selectMenuEl = menuEl;
|
||||||
position();
|
|
||||||
|
|
||||||
// Reposition on scroll / resize while open
|
requestAnimationFrame(() => {
|
||||||
|
position();
|
||||||
|
menuEl.style.visibility = "";
|
||||||
|
});
|
||||||
|
|
||||||
window.addEventListener("scroll", position, true);
|
window.addEventListener("scroll", position, true);
|
||||||
window.addEventListener("resize", position);
|
window.addEventListener("resize", position);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user