Introducing Damus Notedeck: a nostr browser

This splits notedeck into:

- notedeck
- notedeck_chrome
- notedeck_columns

The `notedeck` crate is the library that `notedeck_chrome` and
`notedeck_columns`, use. It contains common functionality related to
notedeck apps such as the NoteCache, ImageCache, etc.

The `notedeck_chrome` crate is the binary and ui chrome. It is
responsible for managing themes, user accounts, signing, data paths,
nostrdb, image caches etc. It will eventually have its own ui which has
yet to be determined.  For now it just manages the browser data, which
is passed to apps via a new struct called `AppContext`.

`notedeck_columns` is our columns app, with less responsibility now that
more things are handled by `notedeck_chrome`

There is still much work left to do before this is a proper browser:

- process isolation
- sandboxing
- etc

This is the beginning of a new era! We're just getting started.

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2024-12-11 04:22:05 -08:00
parent aa14fb092d
commit ec755493d9
146 changed files with 2820 additions and 2794 deletions

View File

@@ -1,126 +1,31 @@
use std::{fmt, io};
use std::io;
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum FilterError {
EmptyContactList,
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum SubscriptionError {
//#[error("No active subscriptions")]
NoActive,
/// When a timeline has an unexpected number
/// of active subscriptions. Should only happen if there
/// is a bug in notedeck
//#[error("Unexpected subscription count")]
UnexpectedSubscriptionCount(i32),
}
impl Error {
pub fn unexpected_sub_count(c: i32) -> Self {
Error::SubscriptionError(SubscriptionError::UnexpectedSubscriptionCount(c))
}
pub fn no_active_sub() -> Self {
Error::SubscriptionError(SubscriptionError::NoActive)
}
}
impl fmt::Display for SubscriptionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NoActive => write!(f, "No active subscriptions"),
Self::UnexpectedSubscriptionCount(c) => {
write!(f, "Unexpected subscription count: {}", c)
}
}
}
}
#[derive(Debug)]
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("timeline not found")]
TimelineNotFound,
#[error("load failed")]
LoadFailed,
SubscriptionError(SubscriptionError),
Filter(FilterError),
Io(io::Error),
Nostr(enostr::Error),
Ndb(nostrdb::Error),
Image(image::error::ImageError),
#[error("network error: {0}")]
Nostr(#[from] enostr::Error),
#[error("database error: {0}")]
Ndb(#[from] nostrdb::Error),
#[error("io error: {0}")]
Io(#[from] io::Error),
#[error("notedeck app error: {0}")]
App(#[from] notedeck::Error),
#[error("generic error: {0}")]
Generic(String),
}
impl Error {
pub fn empty_contact_list() -> Self {
Error::Filter(FilterError::EmptyContactList)
}
}
impl fmt::Display for FilterError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::EmptyContactList => {
write!(f, "empty contact list")
}
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::SubscriptionError(e) => {
write!(f, "{e}")
}
Self::TimelineNotFound => write!(f, "Timeline not found"),
Self::LoadFailed => {
write!(f, "load failed")
}
Self::Filter(e) => {
write!(f, "{e}")
}
Self::Nostr(e) => write!(f, "{e}"),
Self::Ndb(e) => write!(f, "{e}"),
Self::Image(e) => write!(f, "{e}"),
Self::Generic(e) => write!(f, "{e}"),
Self::Io(e) => write!(f, "{e}"),
}
}
}
impl From<String> for Error {
fn from(s: String) -> Self {
Error::Generic(s)
}
}
impl From<nostrdb::Error> for Error {
fn from(e: nostrdb::Error) -> Self {
Error::Ndb(e)
}
}
impl From<image::error::ImageError> for Error {
fn from(err: image::error::ImageError) -> Self {
Error::Image(err)
}
}
impl From<enostr::Error> for Error {
fn from(err: enostr::Error) -> Self {
Error::Nostr(err)
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::Io(err)
}
}
impl From<FilterError> for Error {
fn from(err: FilterError) -> Self {
Error::Filter(err)
}
}