extract bookmarks controller

This commit is contained in:
Nikita Galaiko 2023-11-08 13:32:46 +01:00 committed by GitButler
parent 2510e5b075
commit 43ffb2dc05
7 changed files with 192 additions and 97 deletions

View File

@ -1,10 +1,10 @@
use std::{collections::HashMap, ops, path};
use std::{collections::HashMap, path};
use anyhow::{Context, Result};
use tauri::{AppHandle, Manager};
use crate::{
bookmarks, gb_repository,
gb_repository,
git::{self, diff},
keys,
paths::DataDir,
@ -24,7 +24,6 @@ pub struct App {
keys: keys::Controller,
watchers: watcher::Watchers,
sessions_database: sessions::Database,
bookmarks_database: bookmarks::Database,
}
#[derive(Debug, thiserror::Error)]
@ -50,7 +49,6 @@ impl TryFrom<&AppHandle> for App {
users: users::Controller::from(value),
watchers: value.state::<watcher::Watchers>().inner().clone(),
sessions_database: sessions::Database::from(value),
bookmarks_database: bookmarks::Database::from(value),
})
}
}
@ -186,42 +184,6 @@ impl App {
Ok(())
}
pub async fn upsert_bookmark(&self, bookmark: &bookmarks::Bookmark) -> Result<(), Error> {
{
let project = self.projects.get(&bookmark.project_id)?;
let project_repository = project_repository::Repository::try_from(&project)?;
let user = self.users.get_user().context("failed to get user")?;
let gb_repository = gb_repository::Repository::open(
&self.local_data_dir,
&project_repository,
user.as_ref(),
)
.context("failed to open gb repository")?;
let writer = bookmarks::Writer::new(&gb_repository).context("failed to open writer")?;
writer.write(bookmark).context("failed to write bookmark")?;
}
if let Err(error) = self
.watchers
.post(watcher::Event::Bookmark(bookmark.clone()))
.await
{
tracing::error!(?error, "failed to send session event");
}
Ok(())
}
pub fn list_bookmarks(
&self,
project_id: &ProjectId,
range: Option<ops::Range<u128>>,
) -> Result<Vec<bookmarks::Bookmark>, Error> {
self.bookmarks_database
.list_by_project_id(project_id, range)
.map_err(Error::Other)
}
pub fn git_wd_diff(
&self,
project_id: &ProjectId,

View File

@ -5,8 +5,8 @@ use futures::executor::block_on;
use tauri::{generate_context, Manager};
use gblib::{
analytics, app, assets, commands, database, deltas, github, keys, logs, projects, sessions,
storage, users, virtual_branches, watcher, zip,
analytics, app, assets, bookmarks, commands, database, deltas, github, keys, logs, projects,
sessions, storage, users, virtual_branches, watcher, zip,
};
fn main() {
@ -121,6 +121,10 @@ fn main() {
let deltas_controller = deltas::Controller::from(&app_handle);
app_handle.manage(deltas_controller);
let bookmarks_controller = bookmarks::Controller::try_from(&app_handle)
.expect("failed to initialize bookmarks controller");
app_handle.manage(bookmarks_controller);
let sessions_controller = sessions::Controller::try_from(&app_handle)
.expect("failed to initialize sessions controller");
app_handle.manage(sessions_controller);
@ -162,12 +166,12 @@ fn main() {
commands::git_head,
commands::git_wd_diff,
commands::delete_all_data,
commands::upsert_bookmark,
commands::list_bookmarks,
commands::fetch_from_target,
commands::mark_resolved,
commands::git_set_global_config,
commands::git_get_global_config,
bookmarks::commands::upsert_bookmark,
bookmarks::commands::list_bookmarks,
zip::commands::get_logs_archive_path,
zip::commands::get_project_archive_path,
zip::commands::get_project_data_archive_path,

View File

@ -0,0 +1,88 @@
use std::{ops::Range, time};
use tauri::{AppHandle, Manager};
use tracing::instrument;
use crate::error::{Code, Error};
use super::{
controller::{ListError, UpsertError},
Bookmark, Controller,
};
impl From<UpsertError> for Error {
fn from(value: UpsertError) -> Self {
match value {
UpsertError::GetUser(error) => Error::from(error),
UpsertError::GetProject(error) => Error::from(error),
UpsertError::Other(error) => {
tracing::error!(?error);
Error::Unknown
}
}
}
}
#[tauri::command(async)]
#[instrument(skip(handle))]
pub async fn upsert_bookmark(
handle: AppHandle,
project_id: String,
timestamp_ms: u64,
note: String,
deleted: bool,
) -> Result<(), Error> {
let project_id = project_id.parse().map_err(|_| Error::UserError {
code: Code::Validation,
message: "Malformed project id".to_string(),
})?;
let now = time::UNIX_EPOCH
.elapsed()
.map_err(|error| {
tracing::error!(?error);
Error::Unknown
})?
.as_millis();
let bookmark = Bookmark {
project_id,
timestamp_ms: timestamp_ms.into(),
created_timestamp_ms: now,
updated_timestamp_ms: now,
note,
deleted,
};
handle
.state::<Controller>()
.upsert(&bookmark)
.map(|_| ())
.map_err(Into::into)
}
impl From<ListError> for Error {
fn from(value: ListError) -> Self {
match value {
ListError::Other(error) => {
tracing::error!(?error);
Error::Unknown
}
}
}
}
#[tauri::command(async)]
#[instrument(skip(handle))]
pub async fn list_bookmarks(
handle: AppHandle,
project_id: &str,
range: Option<Range<u128>>,
) -> Result<Vec<Bookmark>, Error> {
let project_id = project_id.parse().map_err(|_| Error::UserError {
code: Code::Validation,
message: "Malformed project id".to_string(),
})?;
handle
.state::<Controller>()
.list(&project_id, range)
.map_err(Into::into)
}

View File

@ -0,0 +1,84 @@
use std::ops::Range;
use anyhow::Context;
use tauri::AppHandle;
use crate::{
gb_repository,
paths::DataDir,
project_repository,
projects::{self, ProjectId},
users,
};
use super::{database::Database, Bookmark, Writer};
#[derive(Clone)]
pub struct Controller {
local_data_dir: DataDir,
database: Database,
projects: projects::Controller,
users: users::Controller,
}
impl TryFrom<&AppHandle> for Controller {
type Error = anyhow::Error;
fn try_from(value: &AppHandle) -> Result<Self, Self::Error> {
Ok(Self {
local_data_dir: DataDir::try_from(value)?,
database: Database::from(value),
projects: projects::Controller::try_from(value)?,
users: users::Controller::from(value),
})
}
}
#[derive(Debug, thiserror::Error)]
pub enum UpsertError {
#[error(transparent)]
GetProject(#[from] projects::GetError),
#[error(transparent)]
GetUser(#[from] users::GetError),
#[error(transparent)]
Other(#[from] anyhow::Error),
}
#[derive(Debug, thiserror::Error)]
pub enum ListError {
#[error(transparent)]
Other(#[from] anyhow::Error),
}
impl Controller {
pub fn upsert(&self, bookmark: &Bookmark) -> Result<Option<Bookmark>, UpsertError> {
let project = self.projects.get(&bookmark.project_id)?;
let project_repository = project_repository::Repository::try_from(&project)
.context("failed to open project repository")?;
let user = self.users.get_user()?;
let gb_repository = gb_repository::Repository::open(
&self.local_data_dir,
&project_repository,
user.as_ref(),
)
.context("failed to open gb repository")?;
let writer = Writer::new(&gb_repository).context("failed to open writer")?;
writer.write(bookmark).context("failed to write bookmark")?;
self.database
.upsert(bookmark)
.context("failed to upsert bookmark")
.map_err(Into::into)
}
pub fn list(
&self,
project_id: &ProjectId,
range: Option<Range<u128>>,
) -> Result<Vec<Bookmark>, ListError> {
self.database
.list_by_project_id(project_id, range)
.map_err(Into::into)
}
}

View File

@ -2,6 +2,11 @@ mod database;
mod reader;
mod writer;
pub mod commands;
mod controller;
pub use controller::Controller;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
@ -15,7 +20,6 @@ pub struct Bookmark {
pub deleted: bool,
}
pub use database::Database;
pub use reader::BookmarksReader as Reader;
pub use writer::BookmarksWriter as Writer;

View File

@ -1,11 +1,10 @@
use std::{collections::HashMap, ops, path, time};
use std::{collections::HashMap, path};
use anyhow::Context;
use tauri::Manager;
use tracing::instrument;
use crate::{
app, assets, bookmarks,
app, assets,
error::{Code, Error},
git, reader,
sessions::SessionId,
@ -117,52 +116,6 @@ pub async fn delete_all_data(handle: tauri::AppHandle) -> Result<(), Error> {
Ok(())
}
#[tauri::command(async)]
#[instrument(skip(handle))]
pub async fn upsert_bookmark(
handle: tauri::AppHandle,
project_id: String,
timestamp_ms: u64,
note: String,
deleted: bool,
) -> Result<(), Error> {
let app = handle.state::<app::App>();
let now = time::UNIX_EPOCH
.elapsed()
.context("failed to get time")?
.as_millis();
let project_id = project_id.parse().map_err(|_| Error::UserError {
code: Code::Validation,
message: "Malformed project id".to_string(),
})?;
let bookmark = bookmarks::Bookmark {
project_id,
timestamp_ms: timestamp_ms.into(),
created_timestamp_ms: now,
updated_timestamp_ms: now,
note,
deleted,
};
app.upsert_bookmark(&bookmark).await?;
Ok(())
}
#[tauri::command(async)]
#[instrument(skip(handle))]
pub async fn list_bookmarks(
handle: tauri::AppHandle,
project_id: &str,
range: Option<ops::Range<u128>>,
) -> Result<Vec<bookmarks::Bookmark>, Error> {
let app = handle.state::<app::App>();
let project_id = project_id.parse().map_err(|_| Error::UserError {
code: Code::Validation,
message: "Malformed project id".to_string(),
})?;
let bookmarks = app.list_bookmarks(&project_id, range)?;
Ok(bookmarks)
}
#[tauri::command(async)]
#[instrument(skip(handle))]
pub async fn fetch_from_target(handle: tauri::AppHandle, project_id: &str) -> Result<(), Error> {

View File

@ -21,7 +21,7 @@ pub struct Handler {
users: users::Controller,
sessions_database: sessions::Database,
deltas_database: deltas::Database,
bookmarks_database: bookmarks::Database,
bookmarks: bookmarks::Controller,
}
impl TryFrom<&AppHandle> for Handler {
@ -34,7 +34,7 @@ impl TryFrom<&AppHandle> for Handler {
users: users::Controller::from(value),
sessions_database: sessions::Database::from(value),
deltas_database: deltas::Database::from(value),
bookmarks_database: bookmarks::Database::from(value),
bookmarks: bookmarks::Controller::try_from(value)?,
})
}
}
@ -58,7 +58,7 @@ impl Handler {
project_id: &ProjectId,
bookmark: &bookmarks::Bookmark,
) -> Result<Vec<events::Event>> {
let updated = self.bookmarks_database.upsert(bookmark)?;
let updated = self.bookmarks.upsert(bookmark)?;
if let Some(updated) = updated {
Ok(vec![events::Event::Emit(app_events::Event::bookmark(
project_id, &updated,