Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@
"vue-eslint-parser": "^10.2.0",
"vue-tsc": "^3.0.6"
},
"overrides": {
"tmp": "^0.2.4"
"resolutions": {
"tmp": "^0.2.4",
"js-yaml": "^4.1.1",
"glob": "^10.5.0"
}
}
19 changes: 13 additions & 6 deletions scripts/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,19 @@ async function main() {
)
)

await retryTask('rclone', async () => {
await getLatestRcloneVersion()
await resolveSidecar(
createBinaryInfo('rclone', getRcloneArchMap(rcloneVersion), `https://downloads.rclone.org`, rcloneVersion)
)
})
// Only bundle rclone for Windows and macOS, Linux users should install rclone from system package manager
const isLinux = platform === 'linux'
if (!isLinux) {
await retryTask('rclone', async () => {
await getLatestRcloneVersion()
await resolveSidecar(
createBinaryInfo('rclone', getRcloneArchMap(rcloneVersion), `https://downloads.rclone.org`, rcloneVersion)
)
})
} else {
console.log('Skipping rclone download for Linux - users should install rclone from system package manager')
}

if (isWin) {
await resolvePlugins()
}
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src-tauri/src/cmd/rclone_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ use crate::utils::path::{get_app_logs_dir, get_rclone_binary_path, get_rclone_co
// admin:admin base64 encoded
pub const RCLONE_AUTH: &str = "Basic YWRtaW46YWRtaW4=";

#[tauri::command]
pub async fn check_rclone_available() -> Result<bool, String> {
get_rclone_binary_path().map(|_| true).or(Ok(false))
}

#[tauri::command]
pub async fn create_and_start_rclone_backend(
state: State<'_, AppState>,
Expand Down
4 changes: 3 additions & 1 deletion src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ use cmd::os_operate::{
open_url_in_browser, select_directory, update_tool_version,
};
use cmd::rclone_core::{
create_and_start_rclone_backend, create_rclone_backend_process, get_rclone_backend_status,
check_rclone_available, create_and_start_rclone_backend, create_rclone_backend_process,
get_rclone_backend_status,
};
use cmd::rclone_mount::{
check_mount_status, create_rclone_mount_remote_process, get_mount_info_list,
Expand Down Expand Up @@ -126,6 +127,7 @@ pub fn run() {
create_openlist_core_process,
get_openlist_core_status,
get_rclone_backend_status,
check_rclone_available,
create_rclone_backend_process,
create_and_start_rclone_backend,
rclone_list_config,
Expand Down
25 changes: 24 additions & 1 deletion src-tauri/src/utils/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,30 @@ pub fn get_openlist_binary_path() -> Result<PathBuf, String> {
}

pub fn get_rclone_binary_path() -> Result<PathBuf, String> {
get_binary_path("rclone", "Rclone")
// Windows/macOS: rclone is bundled with the app
#[cfg(not(target_os = "linux"))]
{
get_binary_path("rclone", "Rclone")
}

// Linux: rclone is not bundled, find it in system PATH
#[cfg(target_os = "linux")]
{
use std::process::Command;
if let Ok(output) = Command::new("which").arg("rclone").output()
&& output.status.success()
{
let path_str = String::from_utf8_lossy(&output.stdout).trim().to_string();
if !path_str.is_empty() {
return Ok(PathBuf::from(path_str));
}
}
Err(
"Rclone not found. Please install it via your package manager (e.g., apt install \
rclone)"
.to_string(),
)
}
}

pub fn get_app_config_dir() -> Result<PathBuf, String> {
Expand Down
1 change: 0 additions & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
"externalBin": [
"binary/openlist",
"binary/rclone",
"binary/install-openlist-service",
"binary/openlist-desktop-service",
"binary/uninstall-openlist-service"
Expand Down
5 changes: 3 additions & 2 deletions src-tauri/tauri.linux.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"linux": {
"deb": {
"depends": ["openssl"],
"recommends": ["rclone"],
"desktopTemplate": "./packages/linux/openlist.desktop",
"provides": ["openlist-desktop"],
"conflicts": ["openlist-desktop"],
Expand All @@ -15,6 +16,7 @@
},
"rpm": {
"depends": ["openssl"],
"recommends": ["rclone"],
"desktopTemplate": "./packages/linux/openlist.desktop",
"provides": ["openlist-desktop"],
"conflicts": ["openlist-desktop"],
Expand All @@ -27,8 +29,7 @@
"./binary/install-openlist-service",
"./binary/uninstall-openlist-service",
"./binary/openlist-desktop-service",
"./binary/openlist",
"./binary/rclone"
"./binary/openlist"
]
}
}
9 changes: 8 additions & 1 deletion src-tauri/tauri.macos.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
"exceptionDomain": "",
"signingIdentity": null,
"entitlements": "packages/macos/entitlements.plist"
}
},
"externalBin": [
"./binary/install-openlist-service",
"./binary/uninstall-openlist-service",
"./binary/openlist-desktop-service",
"./binary/openlist",
"./binary/rclone"
]
}
}
9 changes: 8 additions & 1 deletion src-tauri/tauri.windows.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
"installMode": "perMachine",
"template": "./packages/windows/installer.nsi"
}
}
},
"externalBin": [
"./binary/install-openlist-service",
"./binary/uninstall-openlist-service",
"./binary/openlist-desktop-service",
"./binary/openlist",
"./binary/rclone"
]
}
}
3 changes: 2 additions & 1 deletion src/api/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export class TauriAPI {
backend: {
create: (): Promise<boolean> => call('create_rclone_backend_process'),
createAndStart: (): Promise<ProcessConfig> => call('create_and_start_rclone_backend'),
isRunning: (): Promise<boolean> => call('get_rclone_backend_status')
isRunning: (): Promise<boolean> => call('get_rclone_backend_status'),
isAvailable: (): Promise<boolean> => call('check_rclone_available')
},
remotes: {
list: (): Promise<string[]> => call('rclone_list_remotes'),
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@
"webdavMessage": "Before mounting remotes, please ensure WebDAV management for specific user is enabled in OpenList Core.",
"winfspTitle": "WinFSP Installation Required",
"winfspMessage": "On Windows, you need to install WinFSP first to use mount functionality. Please download and install it from GitHub: https://github.com/winfsp/winfsp/releases",
"rcloneTitle": "Rclone Installation Required",
"rcloneMessage": "On Linux, rclone is not bundled with the application. Please install it using your package manager (e.g., sudo apt install rclone) or from https://rclone.org/install/",
"dismissForever": "Dismiss forever"
}
},
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@
"webdavMessage": "在挂载远程存储之前,请确保在 OpenList 核心中为用户启用了 WebDAV 管理功能",
"winfspTitle": "需要安装 WinFSP",
"winfspMessage": "在 Windows 系统上,您需要先安装 WinFSP 才能使用挂载功能。请从 GitHub 下载并安装:https://github.com/winfsp/winfsp/releases",
"rcloneTitle": "需要安装 Rclone",
"rcloneMessage": "在 Linux 系统上,rclone 不随应用程序捆绑。请使用包管理器安装(例如:sudo apt install rclone)或从 https://rclone.org/install/ 下载安装",
"dismissForever": "永久关闭"
}
},
Expand Down
14 changes: 13 additions & 1 deletion src/stores/rclone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const useRcloneStore = defineStore('rclone', () => {
const loading = ref(false)
const error = ref<string | undefined>()
const serviceRunning = ref(false)
const rcloneAvailable = ref(true)

const setError = (msg?: string) => (error.value = msg)

Expand Down Expand Up @@ -65,16 +66,27 @@ export const useRcloneStore = defineStore('rclone', () => {
return running
}

const init = () => console.log('Initializing Rclone store...')
const checkRcloneAvailable = async () => {
const available = await TauriAPI.rclone.backend.isAvailable().catch(() => false)
rcloneAvailable.value = available
return available
}

const init = () => {
console.log('Initializing Rclone store...')
checkRcloneAvailable()
}

return {
loading,
error,
serviceRunning,
rcloneAvailable,
clearError,
startRcloneBackend,
stopRcloneBackend,
checkRcloneBackendStatus,
checkRcloneAvailable,
init
}
})
34 changes: 34 additions & 0 deletions src/views/MountView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,23 @@ const dismissWinfspTip = () => {
localStorage.setItem('winfsp_tip_dismissed', 'true')
}

const isLinux = computed(() => {
return typeof OS_PLATFORM !== 'undefined' && OS_PLATFORM === 'linux'
})
const showRcloneTip = ref(false)

const dismissRcloneTip = () => {
showRcloneTip.value = false
localStorage.setItem('rclone_tip_dismissed', 'true')
}

const shouldShowWebdavTip = computed(() => {
if (isWindows.value) {
return !showWinfspTip.value && showWebdavTip.value
}
if (isLinux.value && showRcloneTip.value) {
return false
}
return showWebdavTip.value
})

Expand All @@ -482,6 +495,12 @@ onMounted(async () => {
rcloneStore.checkRcloneBackendStatus()
}, 15 * 1000)
rcloneStore.init()

// Check rclone availability on Linux
if (isLinux.value && !localStorage.getItem('rclone_tip_dismissed')) {
const available = await rcloneStore.checkRcloneAvailable()
showRcloneTip.value = !available
}
})

onUnmounted(() => {
Expand Down Expand Up @@ -580,6 +599,21 @@ onUnmounted(() => {
</div>
</div>

<div v-if="showRcloneTip" class="rclone-tip">
<div class="tip-content">
<div class="tip-icon">
<HardDrive class="icon" />
</div>
<div class="tip-message">
<h4 class="tip-title">{{ t('mount.tip.rcloneTitle') }}</h4>
<p class="tip-description">{{ t('mount.tip.rcloneMessage') }}</p>
</div>
<button class="tip-close" :title="t('mount.tip.dismissForever')" @click="dismissRcloneTip">
<X class="close-icon" />
</button>
</div>
</div>

<!-- Controls Section -->
<div class="controls-section">
<div class="search-container">
Expand Down
82 changes: 82 additions & 0 deletions src/views/css/MountView.css
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,88 @@
color: #60a5fa;
}

/* Rclone tip - orange theme for Linux */
.rclone-tip {
position: relative;
z-index: 1;
margin: 0 28px 12px;
background: linear-gradient(135deg, #ffedd5 0%, #fed7aa 100%);
border: 1px solid #f97316;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(249, 115, 22, 0.1);
overflow: hidden;
}

.rclone-tip .tip-icon {
background: rgba(249, 115, 22, 0.1);
}

.rclone-tip .tip-icon .icon {
color: #c2410c;
}

.rclone-tip .tip-title {
color: #9a3412;
}

.rclone-tip .tip-description {
color: #c2410c;
}

.rclone-tip .tip-close {
background: rgba(249, 115, 22, 0.1);
}

.rclone-tip .tip-close:hover {
background: rgba(249, 115, 22, 0.2);
}

.rclone-tip .tip-close .close-icon {
color: #c2410c;
}

:root.dark .rclone-tip,
:root.auto.dark .rclone-tip {
background: linear-gradient(135deg, #431407 0%, #7c2d12 100%);
border-color: #f97316;
box-shadow: 0 1px 4px rgba(249, 115, 22, 0.1);
}

:root.dark .rclone-tip .tip-icon,
:root.auto.dark .rclone-tip .tip-icon {
background: rgba(249, 115, 22, 0.1);
}

:root.dark .rclone-tip .tip-icon .icon,
:root.auto.dark .rclone-tip .tip-icon .icon {
color: #fb923c;
}

:root.dark .rclone-tip .tip-title,
:root.auto.dark .rclone-tip .tip-title {
color: #fdba74;
}

:root.dark .rclone-tip .tip-description,
:root.auto.dark .rclone-tip .tip-description {
color: #fb923c;
}

:root.dark .rclone-tip .tip-close,
:root.auto.dark .rclone-tip .tip-close {
background: rgba(249, 115, 22, 0.1);
}

:root.dark .rclone-tip .tip-close:hover,
:root.auto.dark .rclone-tip .tip-close:hover {
background: rgba(249, 115, 22, 0.2);
}

:root.dark .rclone-tip .tip-close .close-icon,
:root.auto.dark .rclone-tip .tip-close .close-icon {
color: #fb923c;
}

@media (max-width: 1024px) {
.header-content {
grid-template-columns: 1fr;
Expand Down
Loading
Loading