feat: extensions versioning
This commit is contained in:
parent
52bf1b2062
commit
5e77517a7f
@ -28,3 +28,4 @@ flate2 = "1.0"
|
|||||||
tar = "0.4"
|
tar = "0.4"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
tauri-plugin-http = { version = "2", features = ["unsafe-headers"] }
|
tauri-plugin-http = { version = "2", features = ["unsafe-headers"] }
|
||||||
|
tauri-plugin-store = "2"
|
||||||
|
|||||||
@ -2,9 +2,13 @@
|
|||||||
"$schema": "../gen/schemas/desktop-schema.json",
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
"identifier": "default",
|
"identifier": "default",
|
||||||
"description": "enables the default permissions",
|
"description": "enables the default permissions",
|
||||||
"windows": ["main"],
|
"windows": [
|
||||||
|
"main"
|
||||||
|
],
|
||||||
"remote": {
|
"remote": {
|
||||||
"urls": ["http://*"]
|
"urls": [
|
||||||
|
"http://*"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"core:default",
|
"core:default",
|
||||||
@ -12,7 +16,14 @@
|
|||||||
"shell:allow-open",
|
"shell:allow-open",
|
||||||
{
|
{
|
||||||
"identifier": "http:default",
|
"identifier": "http:default",
|
||||||
"allow": [{ "url": "https://*:*" }, { "url": "http://*:*" }],
|
"allow": [
|
||||||
|
{
|
||||||
|
"url": "https://*:*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "http://*:*"
|
||||||
|
}
|
||||||
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -41,6 +52,7 @@
|
|||||||
"sidecar": true
|
"sidecar": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"store:default"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -5,6 +5,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
|
|
||||||
|
use super::setup;
|
||||||
|
|
||||||
const CONFIGURATION_FILE_NAME: &str = "settings.json";
|
const CONFIGURATION_FILE_NAME: &str = "settings.json";
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
@ -192,6 +194,13 @@ pub fn open_file_explorer(path: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn install_extensions(app: AppHandle) {
|
||||||
|
if let Err(err) = setup::install_extensions(app, true) {
|
||||||
|
eprintln!("Failed to install extensions: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_active_extensions(app: AppHandle) -> Vec<serde_json::Value> {
|
pub fn get_active_extensions(app: AppHandle) -> Vec<serde_json::Value> {
|
||||||
let mut path = get_jan_extensions_path(app);
|
let mut path = get_jan_extensions_path(app);
|
||||||
@ -225,5 +234,3 @@ pub fn get_active_extensions(app: AppHandle) -> Vec<serde_json::Value> {
|
|||||||
pub fn get_user_home_path(app: AppHandle) -> String {
|
pub fn get_user_home_path(app: AppHandle) -> String {
|
||||||
return get_app_configurations(app.clone()).data_folder;
|
return get_app_configurations(app.clone()).data_folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -42,10 +42,7 @@ pub fn exists_sync(app_handle: tauri::AppHandle, args: Vec<String>) -> Result<bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn read_file_sync(
|
pub fn read_file_sync(app_handle: tauri::AppHandle, args: Vec<String>) -> Result<String, String> {
|
||||||
app_handle: tauri::AppHandle,
|
|
||||||
args: Vec<String>,
|
|
||||||
) -> Result<String, String> {
|
|
||||||
if args.is_empty() || args[0].is_empty() {
|
if args.is_empty() || args[0].is_empty() {
|
||||||
return Err("read_file_sync error: Invalid argument".to_string());
|
return Err("read_file_sync error: Invalid argument".to_string());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,54 @@
|
|||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
|
use std::{
|
||||||
|
fs::{self, File},
|
||||||
|
io::Read,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
use tar::Archive;
|
||||||
use tauri::{App, Listener, Manager};
|
use tauri::{App, Listener, Manager};
|
||||||
use tauri_plugin_shell::process::CommandEvent;
|
use tauri_plugin_shell::process::CommandEvent;
|
||||||
use tauri_plugin_shell::ShellExt;
|
use tauri_plugin_shell::ShellExt;
|
||||||
use std::{fs::{self, File}, io::Read, path::PathBuf, sync::{Arc, Mutex}};
|
use tauri_plugin_store::StoreExt;
|
||||||
use tar::Archive;
|
|
||||||
|
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
|
|
||||||
use super::cmd::get_jan_extensions_path;
|
use super::cmd::get_jan_extensions_path;
|
||||||
|
|
||||||
pub fn install_extensions(app: tauri::AppHandle) -> Result<(), String> {
|
pub fn install_extensions(app: tauri::AppHandle, force: bool) -> Result<(), String> {
|
||||||
|
let store = app.store("store.json").expect("Store not initialized");
|
||||||
|
let stored_version = if let Some(version) = store.get("version") {
|
||||||
|
if let Some(version_str) = version.as_str() {
|
||||||
|
version_str.to_string()
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let app_version = app
|
||||||
|
.config()
|
||||||
|
.version
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| "".to_string());
|
||||||
|
|
||||||
|
if !force {
|
||||||
|
if stored_version == app_version {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
let extensions_path = get_jan_extensions_path(app.clone());
|
let extensions_path = get_jan_extensions_path(app.clone());
|
||||||
let pre_install_path = PathBuf::from("./../pre-install");
|
let pre_install_path = PathBuf::from("./../pre-install");
|
||||||
|
|
||||||
|
// Attempt to remove extensions folder
|
||||||
|
if extensions_path.exists() {
|
||||||
|
fs::remove_dir_all(&extensions_path).unwrap_or_else(|_| {
|
||||||
|
println!("Failed to remove existing extensions folder, it may not exist.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to create it again
|
||||||
if !extensions_path.exists() {
|
if !extensions_path.exists() {
|
||||||
fs::create_dir_all(&extensions_path).map_err(|e| e.to_string())?;
|
fs::create_dir_all(&extensions_path).map_err(|e| e.to_string())?;
|
||||||
}
|
}
|
||||||
@ -106,6 +142,10 @@ pub fn install_extensions(app: tauri::AppHandle) -> Result<(), String> {
|
|||||||
)
|
)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Store the new app version
|
||||||
|
store.set("version", serde_json::json!(app_version));
|
||||||
|
store.save().expect("Failed to save store");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +250,6 @@ pub fn setup_sidecar(app: &App) -> Result<(), String> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn copy_dir_all(src: PathBuf, dst: PathBuf) -> Result<(), String> {
|
fn copy_dir_all(src: PathBuf, dst: PathBuf) -> Result<(), String> {
|
||||||
fs::create_dir_all(&dst).map_err(|e| e.to_string())?;
|
fs::create_dir_all(&dst).map_err(|e| e.to_string())?;
|
||||||
println!("Copying from {:?} to {:?}", src, dst);
|
println!("Copying from {:?} to {:?}", src, dst);
|
||||||
@ -229,12 +268,7 @@ fn copy_dir_all(src: PathBuf, dst: PathBuf) -> Result<(), String> {
|
|||||||
pub fn setup_engine_binaries(app: &App) -> Result<(), String> {
|
pub fn setup_engine_binaries(app: &App) -> Result<(), String> {
|
||||||
// Copy engine binaries to app_data
|
// Copy engine binaries to app_data
|
||||||
let app_data_dir = app.handle().path().app_data_dir().unwrap();
|
let app_data_dir = app.handle().path().app_data_dir().unwrap();
|
||||||
let binaries_dir = app
|
let binaries_dir = app.handle().path().resource_dir().unwrap().join("binaries");
|
||||||
.handle()
|
|
||||||
.path()
|
|
||||||
.resource_dir()
|
|
||||||
.unwrap()
|
|
||||||
.join("binaries");
|
|
||||||
let themes_dir = app
|
let themes_dir = app
|
||||||
.handle()
|
.handle()
|
||||||
.path()
|
.path()
|
||||||
|
|||||||
@ -3,7 +3,6 @@ use core::setup::{self, setup_engine_binaries, setup_sidecar};
|
|||||||
|
|
||||||
use rand::{distributions::Alphanumeric, Rng};
|
use rand::{distributions::Alphanumeric, Rng};
|
||||||
use tauri::{command, Emitter, State};
|
use tauri::{command, Emitter, State};
|
||||||
|
|
||||||
struct AppState {
|
struct AppState {
|
||||||
app_token: Option<String>,
|
app_token: Option<String>,
|
||||||
}
|
}
|
||||||
@ -24,6 +23,7 @@ fn generate_app_token() -> String {
|
|||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_store::Builder::new().build())
|
||||||
.plugin(tauri_plugin_http::init())
|
.plugin(tauri_plugin_http::init())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
@ -44,6 +44,7 @@ pub fn run() {
|
|||||||
core::cmd::relaunch,
|
core::cmd::relaunch,
|
||||||
core::cmd::open_app_directory,
|
core::cmd::open_app_directory,
|
||||||
core::cmd::open_file_explorer,
|
core::cmd::open_file_explorer,
|
||||||
|
core::cmd::install_extensions,
|
||||||
app_token,
|
app_token,
|
||||||
])
|
])
|
||||||
.manage(AppState {
|
.manage(AppState {
|
||||||
@ -59,7 +60,7 @@ pub fn run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Install extensions
|
// Install extensions
|
||||||
if let Err(e) = setup::install_extensions(app.handle().clone()) {
|
if let Err(e) = setup::install_extensions(app.handle().clone(), false) {
|
||||||
eprintln!("Failed to install extensions: {}", e);
|
eprintln!("Failed to install extensions: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||||
"productName": "jan-app",
|
"productName": "Jan",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"identifier": "jan.ai",
|
"identifier": "jan.ai",
|
||||||
"build": {
|
"build": {
|
||||||
|
|||||||
@ -16,6 +16,12 @@ export const setupBaseExtensions = async () => {
|
|||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_TAURI) {
|
||||||
|
await window.core?.api.installExtensions()
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
return
|
||||||
const baseExtensions = await window.core?.api.baseExtensions()
|
const baseExtensions = await window.core?.api.baseExtensions()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -2,10 +2,12 @@ import { CoreRoutes, APIRoutes } from '@janhq/core'
|
|||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
// Define API routes based on different route types
|
// Define API routes based on different route types
|
||||||
export const Routes = [...CoreRoutes, ...APIRoutes].map((r) => ({
|
export const Routes = [...CoreRoutes, ...APIRoutes, 'installExtensions'].map(
|
||||||
|
(r) => ({
|
||||||
path: `app`,
|
path: `app`,
|
||||||
route: r,
|
route: r,
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
|
|
||||||
// Function to open an external URL in a new browser window
|
// Function to open an external URL in a new browser window
|
||||||
export function openExternalUrl(url: string) {
|
export function openExternalUrl(url: string) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user