Merge pull request #6618 from github-roushan/show-supported-files

Show supported files
This commit is contained in:
Nguyen Ngoc Minh 2025-09-29 03:17:39 +00:00 committed by GitHub
commit 5403e58681
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 67 additions and 14 deletions

View File

@ -1,9 +1,8 @@
import { getJanDataFolderPath, fs, joinPath, events } from '@janhq/core' import { getJanDataFolderPath, fs, joinPath, events } from '@janhq/core'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { getProxyConfig } from './util' import { getProxyConfig, basenameNoExt } from './util'
import { dirname, basename } from '@tauri-apps/api/path' import { dirname, basename } from '@tauri-apps/api/path'
import { getSystemInfo } from '@janhq/tauri-plugin-hardware-api' import { getSystemInfo } from '@janhq/tauri-plugin-hardware-api'
/* /*
* Reads currently installed backends in janDataFolderPath * Reads currently installed backends in janDataFolderPath
* *
@ -73,10 +72,7 @@ async function fetchRemoteSupportedBackends(
if (!name.startsWith(prefix)) continue if (!name.startsWith(prefix)) continue
const backend = name const backend = basenameNoExt(name).slice(prefix.length)
.replace(prefix, '')
.replace('.tar.gz', '')
.replace('.zip', '')
if (supportedBackends.includes(backend)) { if (supportedBackends.includes(backend)) {
remote.push({ version, backend }) remote.push({ version, backend })

View File

@ -1,3 +1,23 @@
// File path utilities
export function basenameNoExt(filePath: string): string {
const VALID_EXTENSIONS = [".tar.gz", ".zip"];
// handle VALID extensions first
for (const ext of VALID_EXTENSIONS) {
if (filePath.toLowerCase().endsWith(ext)) {
return filePath.slice(0, -ext.length);
}
}
// fallback: remove only the last extension
const lastDotIndex = filePath.lastIndexOf('.');
if (lastDotIndex > 0) {
return filePath.slice(0, lastDotIndex);
}
return filePath;
}
// Zustand proxy state structure // Zustand proxy state structure
interface ProxyState { interface ProxyState {
proxyEnabled: boolean proxyEnabled: boolean

View File

@ -465,7 +465,11 @@ async fn download_single_file(
.await .await
.map_err(err_to_string)?; .map_err(err_to_string)?;
log::info!("Started downloading: {}", item.url); // Decode URL for better readability in logs
let decoded_url = url::Url::parse(&item.url)
.map(|u| u.to_string())
.unwrap_or_else(|_| item.url.clone());
log::info!("Started downloading: {}", decoded_url);
let client = _get_client_for_item(item, &header_map).map_err(err_to_string)?; let client = _get_client_for_item(item, &header_map).map_err(err_to_string)?;
let mut download_delta = 0u64; let mut download_delta = 0u64;
let mut initial_progress = 0u64; let mut initial_progress = 0u64;
@ -584,7 +588,11 @@ async fn download_single_file(
.await .await
.map_err(err_to_string)?; .map_err(err_to_string)?;
log::info!("Finished downloading: {}", item.url); // Decode URL for better readability in logs
let decoded_url = url::Url::parse(&item.url)
.map(|u| u.to_string())
.unwrap_or_else(|_| item.url.clone());
log::info!("Finished downloading: {}", decoded_url);
Ok(save_path.to_path_buf()) Ok(save_path.to_path_buf())
} }

View File

@ -1,11 +1,28 @@
import { type ClassValue, clsx } from 'clsx' import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { ExtensionManager } from './extension' import { ExtensionManager } from './extension'
import path from "path"
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)) return twMerge(clsx(inputs))
} }
export function basenameNoExt(filePath: string): string {
const base = path.basename(filePath);
const VALID_EXTENSIONS = [".tar.gz", ".zip"];
// handle VALID extensions first
for (const ext of VALID_EXTENSIONS) {
if (base.toLowerCase().endsWith(ext)) {
return base.slice(0, -ext.length);
}
}
// fallback: remove only the last extension
return base.slice(0, -path.extname(base).length);
}
export function getProviderLogo(provider: string) { export function getProviderLogo(provider: string) {
switch (provider) { switch (provider) {
case 'jan': case 'jan':

View File

@ -41,6 +41,7 @@ import { useLlamacppDevices } from '@/hooks/useLlamacppDevices'
import { PlatformFeatures } from '@/lib/platform/const' import { PlatformFeatures } from '@/lib/platform/const'
import { PlatformFeature } from '@/lib/platform/types' import { PlatformFeature } from '@/lib/platform/types'
import { useBackendUpdater } from '@/hooks/useBackendUpdater' import { useBackendUpdater } from '@/hooks/useBackendUpdater'
import { basenameNoExt } from '@/lib/utils'
// as route.threadsDetail // as route.threadsDetail
export const Route = createFileRoute('/settings/providers/$providerName')({ export const Route = createFileRoute('/settings/providers/$providerName')({
@ -382,7 +383,7 @@ function ProviderDetail() {
filters: [ filters: [
{ {
name: 'Backend Archives', name: 'Backend Archives',
extensions: ['tar.gz', 'zip'], extensions: ['tar.gz', 'zip', 'gz'],
}, },
], ],
}) })
@ -394,9 +395,7 @@ function ProviderDetail() {
await installBackend(selectedFile) await installBackend(selectedFile)
// Extract filename from the selected file path and replace spaces with dashes // Extract filename from the selected file path and replace spaces with dashes
const fileName = ( const fileName = basenameNoExt(selectedFile).replace(/\s+/g, "-")
selectedFile.split(/[/\\]/).pop() || selectedFile
).replace(/\s+/g, '-')
toast.success(t('settings:backendInstallSuccess'), { toast.success(t('settings:backendInstallSuccess'), {
description: `Llamacpp ${fileName} installed`, description: `Llamacpp ${fileName} installed`,

View File

@ -9,7 +9,16 @@ import { DefaultDialogService } from './default'
export class TauriDialogService extends DefaultDialogService { export class TauriDialogService extends DefaultDialogService {
async open(options?: DialogOpenOptions): Promise<string | string[] | null> { async open(options?: DialogOpenOptions): Promise<string | string[] | null> {
try { try {
return await open(options) console.log('TauriDialogService: Opening dialog with options:', options)
if (options?.filters) {
console.log('TauriDialogService: File filters:', options.filters)
options.filters.forEach((filter, index) => {
console.log(`TauriDialogService: Filter ${index} - Name: "${filter.name}", Extensions:`, filter.extensions)
})
}
const result = await open(options)
console.log('TauriDialogService: Dialog result:', result)
return result
} catch (error) { } catch (error) {
console.error('Error opening dialog in Tauri:', error) console.error('Error opening dialog in Tauri:', error)
return null return null

View File

@ -19,10 +19,14 @@ export class WebDialogService implements DialogService {
} }
if (options?.filters) { if (options?.filters) {
console.log('WebDialogService: Processing file filters:', options.filters)
const extensions = options.filters.flatMap(filter => const extensions = options.filters.flatMap(filter =>
filter.extensions.map(ext => `.${ext}`) filter.extensions.map(ext => `.${ext}`)
) )
input.accept = extensions.join(',') console.log('WebDialogService: Generated extensions with dots:', extensions)
const acceptString = extensions.join(',')
console.log('WebDialogService: Final accept attribute:', acceptString)
input.accept = acceptString
} }
input.onchange = (e) => { input.onchange = (e) => {