mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-20 09:54:19 +01:00
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>
149 lines
3.9 KiB
Rust
149 lines
3.9 KiB
Rust
use tracing::error;
|
|
|
|
use notedeck::{DataPath, DataPathType, Directory};
|
|
|
|
pub struct Support {
|
|
directory: Directory,
|
|
mailto_url: String,
|
|
most_recent_log: Option<String>,
|
|
}
|
|
|
|
fn new_log_dir(paths: &DataPath) -> Directory {
|
|
Directory::new(paths.path(DataPathType::Log))
|
|
}
|
|
|
|
impl Support {
|
|
pub fn new(path: &DataPath) -> Self {
|
|
let directory = new_log_dir(path);
|
|
|
|
Self {
|
|
mailto_url: MailtoBuilder::new(SUPPORT_EMAIL.to_string())
|
|
.with_subject("Help Needed".to_owned())
|
|
.with_content(EMAIL_TEMPLATE.to_owned())
|
|
.build(),
|
|
directory,
|
|
most_recent_log: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
static MAX_LOG_LINES: usize = 500;
|
|
static SUPPORT_EMAIL: &str = "support@damus.io";
|
|
static EMAIL_TEMPLATE: &str = concat!("version ", env!("CARGO_PKG_VERSION"), "\nCommit hash: ", env!("GIT_COMMIT_HASH"), "\n\nDescribe the bug you have encountered:\n<-- your statement here -->\n\n===== Paste your log below =====\n\n");
|
|
|
|
impl Support {
|
|
pub fn refresh(&mut self) {
|
|
self.most_recent_log = get_log_str(&self.directory);
|
|
}
|
|
|
|
pub fn get_mailto_url(&self) -> &str {
|
|
&self.mailto_url
|
|
}
|
|
|
|
pub fn get_log_dir(&self) -> Option<&str> {
|
|
self.directory.file_path.to_str()
|
|
}
|
|
|
|
pub fn get_most_recent_log(&self) -> Option<&String> {
|
|
self.most_recent_log.as_ref()
|
|
}
|
|
}
|
|
|
|
fn get_log_str(interactor: &Directory) -> Option<String> {
|
|
match interactor.get_most_recent() {
|
|
Ok(Some(most_recent_name)) => {
|
|
match interactor.get_file_last_n_lines(most_recent_name.clone(), MAX_LOG_LINES) {
|
|
Ok(file_output) => {
|
|
return Some(
|
|
get_prefix(
|
|
&most_recent_name,
|
|
file_output.output_num_lines,
|
|
file_output.total_lines_in_file,
|
|
) + &file_output.output,
|
|
)
|
|
}
|
|
Err(e) => {
|
|
error!(
|
|
"Error retrieving the last lines from file {}: {:?}",
|
|
most_recent_name, e
|
|
);
|
|
}
|
|
}
|
|
}
|
|
Ok(None) => {
|
|
error!("No files were found.");
|
|
}
|
|
Err(e) => {
|
|
error!("Error fetching the most recent file: {:?}", e);
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn get_prefix(file_name: &str, lines_displayed: usize, num_total_lines: usize) -> String {
|
|
format!(
|
|
"===\nDisplaying the last {} of {} lines in file {}\n===\n\n",
|
|
lines_displayed, num_total_lines, file_name,
|
|
)
|
|
}
|
|
|
|
struct MailtoBuilder {
|
|
content: Option<String>,
|
|
address: String,
|
|
subject: Option<String>,
|
|
}
|
|
|
|
impl MailtoBuilder {
|
|
fn new(address: String) -> Self {
|
|
Self {
|
|
content: None,
|
|
address,
|
|
subject: None,
|
|
}
|
|
}
|
|
|
|
// will be truncated so the whole URL is at most 2000 characters
|
|
pub fn with_content(mut self, content: String) -> Self {
|
|
self.content = Some(content);
|
|
self
|
|
}
|
|
|
|
pub fn with_subject(mut self, subject: String) -> Self {
|
|
self.subject = Some(subject);
|
|
self
|
|
}
|
|
|
|
pub fn build(self) -> String {
|
|
let mut url = String::new();
|
|
|
|
url.push_str("mailto:");
|
|
url.push_str(&self.address);
|
|
|
|
let has_subject = self.subject.is_some();
|
|
|
|
if has_subject || self.content.is_some() {
|
|
url.push('?');
|
|
}
|
|
|
|
if let Some(subject) = self.subject {
|
|
url.push_str("subject=");
|
|
url.push_str(&urlencoding::encode(&subject));
|
|
}
|
|
|
|
if let Some(content) = self.content {
|
|
if has_subject {
|
|
url.push('&');
|
|
}
|
|
|
|
url.push_str("body=");
|
|
|
|
let body = urlencoding::encode(&content);
|
|
|
|
url.push_str(&body);
|
|
}
|
|
|
|
url
|
|
}
|
|
}
|