Add commands to repo plugin

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent f90580ea06
commit 6912ad6f05

@ -11,6 +11,8 @@ tracing = "0.1.29"
thiserror = "1.0.30"
async-trait = {version = "0.1.51", optional=true}
rmp-ipc = {version = "0.7.2", optional=true}
parking_lot = {version="0.11.2", optional=true}
serde_json = {version="1.0.68", optional=true}
[dependencies.serde]
version = "1.0.130"
@ -26,6 +28,11 @@ optional=true
default-features = false
features = []
[dependencies.tokio]
version = "1.12.0"
optional = true
features = ["sync"]
[features]
tauri-plugin = ["client-api","tauri", "rmp-ipc"]
tauri-plugin = ["client-api","tauri", "rmp-ipc", "parking_lot", "serde_json"]
client-api = ["rmp-ipc", "async-trait"]

@ -65,6 +65,7 @@ impl ApiClient {
}
/// Connects to the ipc Socket
#[tracing::instrument(level = "debug")]
pub async fn connect(address: &str) -> ApiResult<Self> {
let ctx = IPCBuilder::new().address(address).build_client().await?;
@ -83,4 +84,10 @@ impl ApiClient {
.await?;
Ok(res.data::<InfoResponse>()?)
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn exit(self) -> ApiResult<()> {
self.ctx.stop().await?;
Ok(())
}
}

@ -0,0 +1,61 @@
use crate::tauri_plugin::commands::{add_once_buffer, ApiAccess, BufferAccess};
use crate::tauri_plugin::error::PluginResult;
use crate::types::files::{FileMetadataResponse, ThumbnailMetadataResponse};
#[tauri::command]
pub async fn get_all_files(api_state: ApiAccess<'_>) -> PluginResult<Vec<FileMetadataResponse>> {
let api = api_state.api().await?;
let all_files = api.file.all_files().await?;
Ok(all_files)
}
#[tauri::command]
pub async fn find_files(
tags: Vec<String>,
api_state: ApiAccess<'_>,
) -> PluginResult<Vec<FileMetadataResponse>> {
let api = api_state.api().await?;
let files = api.file.find_files(tags).await?;
Ok(files)
}
#[tauri::command]
pub async fn read_file_by_hash(
hash: String,
mime_type: String,
api_state: ApiAccess<'_>,
buffer_state: BufferAccess<'_>,
) -> PluginResult<String> {
let api = api_state.api().await?;
let content = api.file.read_file_by_hash(hash.clone()).await?;
let uri = add_once_buffer(buffer_state, hash, mime_type, content);
Ok(uri)
}
#[tauri::command]
pub async fn get_file_thumbnails(
hash: String,
api_state: ApiAccess<'_>,
) -> PluginResult<Vec<ThumbnailMetadataResponse>> {
let api = api_state.api().await?;
let thumbs = api.file.get_file_thumbnails(hash).await?;
Ok(thumbs)
}
#[tauri::command]
pub async fn read_thumbnail(
hash: String,
mime_type: String,
api_state: ApiAccess<'_>,
buffer_state: BufferAccess<'_>,
) -> PluginResult<String> {
let api = api_state.api().await?;
let content = api.file.read_thumbnail(hash.clone()).await?;
let uri = add_once_buffer(buffer_state, hash, mime_type, content);
Ok(uri)
}

@ -0,0 +1,20 @@
use tauri::State;
pub use file::*;
use crate::tauri_plugin::state::{ApiState, BufferState, OnceBuffer};
pub mod file;
pub type ApiAccess<'a> = State<'a, ApiState>;
pub type BufferAccess<'a> = State<'a, BufferState>;
/// Adds a once-buffer to the buffer store
fn add_once_buffer(buffer_state: BufferAccess, key: String, mime: String, buf: Vec<u8>) -> String {
let uri = format!("once://{}", key);
let once_buffer = OnceBuffer::new(mime, buf);
let mut once_buffers = buffer_state.buffer.lock();
once_buffers.insert(key, once_buffer);
uri
}

@ -0,0 +1,25 @@
use crate::tauri_plugin::state::BufferState;
use tauri::http::ResponseBuilder;
use tauri::{Builder, Manager, Runtime};
pub fn register_custom_uri_schemes<R: Runtime>(builder: Builder<R>) -> Builder<R> {
builder.register_uri_scheme_protocol("once", |app, request| {
let buf_state = app.state::<BufferState>();
let resource_key = request.uri().trim_start_matches("once://");
let buffer = {
let mut buffers = buf_state.buffer.lock();
buffers.remove(resource_key)
};
if let Some(buffer) = buffer {
ResponseBuilder::new()
.mimetype(&buffer.mime)
.status(200)
.body(buffer.buf)
} else {
ResponseBuilder::new()
.mimetype("text/plain")
.status(404)
.body("Resource not found".as_bytes().to_vec())
}
})
}

@ -0,0 +1,25 @@
use crate::client_api::error::ApiError;
use serde::Serialize;
pub type PluginResult<T> = Result<T, PluginError>;
#[derive(Clone, Serialize)]
pub struct PluginError {
message: String,
}
impl From<&str> for PluginError {
fn from(s: &str) -> Self {
Self {
message: s.to_string(),
}
}
}
impl From<ApiError> for PluginError {
fn from(e: ApiError) -> Self {
Self {
message: format!("ApiError: {:?}", e),
}
}
}

@ -0,0 +1,61 @@
use tauri::plugin::Plugin;
use tauri::{AppHandle, Builder, Invoke, Manager, Runtime};
use state::ApiState;
use crate::tauri_plugin::state::BufferState;
mod commands;
pub mod custom_schemes;
pub mod error;
mod state;
use commands::*;
pub fn register_plugin<R: Runtime>(builder: Builder<R>) -> Builder<R> {
let repo_plugin = MediarepoPlugin::new();
custom_schemes::register_custom_uri_schemes(builder.plugin(repo_plugin))
}
pub struct MediarepoPlugin<R: Runtime> {
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>,
}
impl<R: Runtime> MediarepoPlugin<R> {
pub fn new() -> Self {
Self {
invoke_handler: Box::new(tauri::generate_handler![
get_all_files,
find_files,
read_file_by_hash,
get_file_thumbnails,
read_thumbnail
]),
}
}
}
impl<R: Runtime> Plugin<R> for MediarepoPlugin<R> {
fn name(&self) -> &'static str {
"mediarepo"
}
fn initialize(
&mut self,
app: &AppHandle<R>,
_config: serde_json::value::Value,
) -> tauri::plugin::Result<()> {
let api_state = ApiState::new();
app.manage(api_state);
let buffer_state = BufferState::default();
app.manage(buffer_state);
Ok(())
}
fn extend_api(&mut self, message: Invoke<R>) {
(self.invoke_handler)(message)
}
}

@ -0,0 +1,53 @@
use std::collections::HashMap;
use std::mem;
use std::sync::Arc;
use parking_lot::Mutex;
use tauri::async_runtime::RwLock;
use crate::client_api::ApiClient;
use crate::tauri_plugin::error::{PluginError, PluginResult};
pub struct ApiState {
inner: Arc<RwLock<Option<ApiClient>>>,
}
impl ApiState {
pub fn new() -> Self {
Self {
inner: Arc::new(RwLock::new(None)),
}
}
pub async fn set_api(&self, client: ApiClient) {
let mut inner = self.inner.write().await;
let old_client = mem::replace(&mut *inner, Some(client));
if let Some(client) = old_client {
let _ = client.exit().await;
}
}
pub async fn api(&self) -> PluginResult<ApiClient> {
let inner = self.inner.read().await;
inner
.clone()
.ok_or_else(|| PluginError::from("Not connected"))
}
}
pub struct OnceBuffer {
pub mime: String,
pub buf: Vec<u8>,
}
impl OnceBuffer {
pub fn new(mime: String, buf: Vec<u8>) -> Self {
Self { mime, buf }
}
}
#[derive(Default)]
pub struct BufferState {
pub buffer: Arc<Mutex<HashMap<String, OnceBuffer>>>,
}
Loading…
Cancel
Save