Skip to content

Commit

Permalink
feat: add toast messages to provide information
Browse files Browse the repository at this point in the history
  • Loading branch information
shonya3 committed Aug 5, 2023
1 parent 1e0bf56 commit c43d85b
Show file tree
Hide file tree
Showing 18 changed files with 322 additions and 798 deletions.
7 changes: 6 additions & 1 deletion packages/app/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<html class="sl-theme-dark" lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.6.0/cdn/themes/dark.css" />
<script
type="module"
src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.6.0/cdn/shoelace-autoloader.js"
></script>
</head>
<body>
<div id="app"></div>
Expand Down
3 changes: 2 additions & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@
"@divicards/shared": "workspace:^",
"@divicards/wc": "workspace:^",
"@formkit/auto-animate": "1.0.0-beta.6",
"@shoelace-style/shoelace": "^2.6.0",
"@tauri-apps/api": "^1.3.0",
"lit": "^2.7.6",
"pinia": "^2.1.3",
"vue": "^3.3.4"
},
"devDependencies": {
"@histoire/plugin-vue": "^0.16.1",
"@tauri-apps/cli": "^1.3.1",
"@vitejs/plugin-vue": "^4.2.3",
"typescript": "^5.0.4",
"vite": "^4.3.9",
"vite-plugin-static-copy": "^0.17.0",
"vite-plugin-vue-devtools": "^0.0.22",
"vue-tsc": "^1.6.5"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src-tauri/divi/src/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl From<Prices> for Cards {
|DivinationCardPrice {
name,
price,
sparkline,
sparkline: _,
}| DivinationCardRecord {
name,
price,
Expand Down
6 changes: 3 additions & 3 deletions packages/app/src-tauri/divi/src/prices.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
consts::{CARDS, CARDS_N},
error::Error,
league::TradeLeague,
};
use serde_big_array::BigArray;
Expand All @@ -24,7 +24,7 @@ pub struct DivinationCardPrice {
#[serde(transparent)]
pub struct Prices(#[serde(with = "BigArray")] pub [DivinationCardPrice; CARDS_N]);
impl Prices {
pub async fn fetch(league: &TradeLeague) -> Result<Prices, reqwest::Error> {
pub async fn fetch(league: &TradeLeague) -> Result<Prices, Error> {
#[derive(Deserialize, Debug, Serialize)]
struct PriceData {
lines: Vec<DivinationCardPrice>,
Expand All @@ -33,7 +33,7 @@ impl Prices {
let client = reqwest::Client::new();
let url = format!("https://poe.ninja/api/data/itemoverview?league={league}&type=DivinationCard&language=en");
let json = client.get(url).send().await?.text().await?;
std::fs::write("ninja.json", &json).unwrap();
// std::fs::write("ninja.json", &json).unwrap();
let data = serde_json::from_str::<PriceData>(&json).unwrap();
Ok(Prices::from(data.lines))
}
Expand Down
12 changes: 7 additions & 5 deletions packages/app/src-tauri/lib/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,21 @@ use divi::{
league::TradeLeague,
sample::{DivinationCardsSample, SampleData},
};
use tauri::{command, State};
use tauri::{command, State, Window};

use crate::{js_result::JSResult, prices::AppCardPrices};

#[command]
pub async fn sample(
pub async fn sample<'a>(
data: SampleData,
league: Option<TradeLeague>,
state: State<'_, Mutex<AppCardPrices>>,
window: Window,
) -> Result<JSResult<DivinationCardsSample>, ()> {
let prices = match league {
Some(league) => {
let mut guard = state.lock().await;
Some(guard.get_or_update(&league).await)
Some(guard.get_or_update(&league, &window).await)
}
None => None,
};
Expand All @@ -26,12 +27,13 @@ pub async fn sample(
}

#[command]
pub async fn merge(
pub async fn merge<'a>(
samples: Vec<DivinationCardsSample>,
state: State<'_, Mutex<AppCardPrices>>,
window: Window,
) -> Result<DivinationCardsSample, ()> {
let mut guard = state.lock().await;
let prices = guard.get_or_update(&TradeLeague::default()).await;
let prices = guard.get_or_update(&TradeLeague::default(), &window).await;
Ok(DivinationCardsSample::merge(Some(prices), &samples))
}

Expand Down
47 changes: 47 additions & 0 deletions packages/app/src-tauri/lib/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::fmt::Display;

use serde::Serialize;

#[derive(Debug)]
pub enum Error {
HttpError(reqwest::Error),
SerdeError(serde_json::Error),
DiviError(divi::error::Error),
}

impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::HttpError(err) => err.fmt(f),
Error::SerdeError(err) => err.fmt(f),
Error::DiviError(err) => err.fmt(f),
}
}
}

impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.to_string().as_str())
}
}

impl From<reqwest::Error> for Error {
fn from(value: reqwest::Error) -> Self {
Error::HttpError(value)
}
}

impl From<serde_json::Error> for Error {
fn from(value: serde_json::Error) -> Self {
Error::SerdeError(value)
}
}

impl From<divi::error::Error> for Error {
fn from(value: divi::error::Error) -> Self {
Error::DiviError(value)
}
}
46 changes: 46 additions & 0 deletions packages/app/src-tauri/lib/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use serde::{Deserialize, Serialize};
use tauri::Window;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
#[serde(tag = "type")]
pub enum Event {
#[serde(rename = "toast")]
#[serde(alias = "toast")]
Toast {
variant: ToastVariant,
message: String,
},
#[serde(rename = "auth-url")]
#[serde(alias = "auth-url")]
AuthUrl { url: String },
}

impl Event {
pub fn emit(&self, window: &Window) {
window.emit(&self.name(), &self).unwrap();
}

pub fn name(&self) -> &str {
match self {
Event::Toast {
variant: _,
message: _,
} => "toast",
Event::AuthUrl { url: _ } => "auth-url",
}
}
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum ToastVariant {
#[serde(rename = "info")]
Info,
#[serde(rename = "success")]
Success,
#[serde(rename = "neutral")]
Neutral,
#[serde(rename = "warning")]
Warning,
#[serde(rename = "danger")]
Danger,
}
2 changes: 2 additions & 0 deletions packages/app/src-tauri/lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pub mod commands;
pub mod dev;
pub mod discord;
pub mod error;
pub mod event;
pub mod google;
pub mod js_result;
pub mod oauth;
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src-tauri/lib/src/poe.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

use crate::oauth::AuthCodeResponse;
use crate::{event::Event, oauth::AuthCodeResponse};
use axum::{extract::Query, response::Html, routing::get, Router};
use divi::league::League;
use keyring::Entry;
Expand Down Expand Up @@ -65,6 +65,11 @@ pub async fn poe_auth(app_handle: AppHandle, window: Window) -> Result<String, S
let auth_url_string = auth_url.to_string();
window.emit("auth-url", auth_url_string).unwrap();

Event::AuthUrl {
url: auth_url.to_string(),
}
.emit(&window);

let AuthCodeResponse { code, csrf } = match receiver.recv().await {
Some(params) => params,
None => {
Expand Down
35 changes: 22 additions & 13 deletions packages/app/src-tauri/lib/src/prices.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#![allow(unused)]

use crate::{error::Error, paths};
use crate::{
error::Error,
event::{Event, ToastVariant},
paths,
};
use divi::{league::TradeLeague, prices::Prices};
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
fs,
path::{Path, PathBuf},
};
use std::{collections::HashMap, fs, path::PathBuf};
use tauri::Window;
use tracing::{debug, instrument};

pub const DAY_AS_SECS: u64 = 86_400;
Expand All @@ -28,8 +27,8 @@ impl AppCardPrices {
}
}

#[instrument(skip(self))]
pub async fn get_or_update(&mut self, league: &TradeLeague) -> Prices {
#[instrument(skip(self, window))]
pub async fn get_or_update(&mut self, league: &TradeLeague, window: &Window) -> Prices {
match self.prices_by_league.get(league) {
Some(prices) => prices.to_owned(),
None => match self.up_to_date(league) {
Expand All @@ -41,7 +40,7 @@ impl AppCardPrices {
}
false => {
dbg!("get_or_update. false branch of up_to_date");
match self.fetch_and_update(league).await {
match self.fetch_and_update(league, window).await {
Ok(prices) => prices,
Err(err) => {
dbg!(err);
Expand All @@ -57,8 +56,12 @@ impl AppCardPrices {
self.dir.join(format!("{}-prices.json", { league }))
}

#[instrument(skip(self))]
async fn fetch_and_update(&mut self, league: &TradeLeague) -> Result<Prices, Error> {
#[instrument(skip(self, window))]
async fn fetch_and_update(
&mut self,
league: &TradeLeague,
window: &Window,
) -> Result<Prices, Error> {
let prices = Prices::fetch(league).await?;
debug!("fetch_and_update: fetched. Serializing to json");
let json = serde_json::to_string(&prices)?;
Expand All @@ -71,6 +74,12 @@ impl AppCardPrices {
self.prices_by_league
.insert(league.to_owned(), prices.clone());

Event::Toast {
variant: ToastVariant::Neutral,
message: format!("Prices for {league} league have been updated"),
}
.emit(&window);

Ok(prices)
}

Expand Down
1 change: 1 addition & 0 deletions packages/app/src-tauri/ninja.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions packages/app/src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ export interface Commands {
}

const { format } = new Intl.NumberFormat();

const debug = false;
export const command = async <CommandName extends keyof Commands, Fn extends Commands[CommandName]>(
name: CommandName,
...args: Parameters<Fn>
): Promise<ReturnType<Fn>> => {
if (import.meta.env.DEV) {
if (debug) {
const t0 = performance.now();
const res = (await invoke(name, ...args)) as ReturnType<Fn>;
// console.log(`${name}: ${format(performance.now() - t0)}ms`);
console.log(`${name}: ${format(performance.now() - t0)}ms`);
return res;
} else return invoke(name, ...args) as Promise<ReturnType<Fn>>;
};
21 changes: 21 additions & 0 deletions packages/app/src/event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { EventCallback, listen } from '@tauri-apps/api/event';
import { ToastVariant } from './toast';

export interface RustEvents {
'auth-url': {
type: 'auth-url';
url: string;
};
toast: {
type: 'toast';
variant: ToastVariant;
message: string;
};
}

export const addRustListener = <EventName extends keyof RustEvents>(
name: EventName,
handler: EventCallback<RustEvents[EventName]>
) => {
return listen(name, handler);
};
24 changes: 24 additions & 0 deletions packages/app/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,32 @@ import './style.css';
import App from './App.vue';
import { createPinia } from 'pinia';

import '@shoelace-style/shoelace/dist/themes/dark.css';
import SlAlrt from '@shoelace-style/shoelace/dist/components/alert/alert.component.js';
import SlButton from '@shoelace-style/shoelace/dist/components/button/button.component.js';
import SlIcon from '@shoelace-style/shoelace/dist/components/icon/icon.component.js';
import { addRustListener } from './event';
import { toast } from './toast';

SlAlrt.define('sl-alert');
SlButton.define('sl-button');
SlIcon.define('sl-icon');

const pinia = createPinia();

const app = createApp(App);
app.use(pinia);
app.mount('#app');

app.config.errorHandler = err => {
console.log('from Vue error handler', err);
if (typeof err === 'string') {
toast('danger', err);
} else if (err instanceof Error) {
toast('danger', err.message);
}
};

addRustListener('toast', e => {
toast(e.payload.variant, e.payload.message);
});
Loading

0 comments on commit c43d85b

Please sign in to comment.