More notifications

This commit is contained in:
micialware committed 2026-08-23 22:16:02 +03:00
1 parent f113d2b3d7
commit 3fcfe95720
4 files changed
+43 -32

No files matched your search

+18 -16
View File
@@ -4,14 +4,16 @@ use reqwest::Error;
use tokio::fs::{File, OpenOptions}; use tokio::fs::{File, OpenOptions};
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use zstd::{DEFAULT_COMPRESSION_LEVEL, Decoder, Encoder}; use zstd::{DEFAULT_COMPRESSION_LEVEL, Decoder, Encoder};
use crate::notification::NotificationData;
use crate::notification::NotificationData::{PermissionDenied, WebApiUnavailable};
// const API_URL: &str = "http://127.0.0.1:8089/"; // const API_URL: &str = "http://127.0.0.1:8089/";
const API_URL: &str = "https://learning.micialware.ru/"; const API_URL: &str = "https://learning.micialware.ru/";
pub async fn send_data(id: String) -> Result<(), ()> { pub async fn send_data(id: String) -> Result<(), NotificationData> {
let path = app_data_dir(); let path = app_data_dir();
let db_file = path.join("data.db"); let db_file = path.join("data.db");
let data = tokio::fs::read(db_file).await.map_err(|_| ())?; let data = tokio::fs::read(db_file).await.map_err(|_| WebApiUnavailable)?;
let data = compress(data); let data = compress(data);
let api_url = API_URL.to_string(); let api_url = API_URL.to_string();
@@ -22,10 +24,10 @@ pub async fn send_data(id: String) -> Result<(), ()> {
.post(&id_url) .post(&id_url)
.body(data) .body(data)
.send() .send()
.await.map_err(|_| ())? .await.map_err(|_| WebApiUnavailable)?
.text() .text()
.await.map_err(|_| ())?; .await.map_err(|_| WebApiUnavailable)?;
set_local_version(new_version.parse::<u32>().unwrap()).await; set_local_version(new_version.parse::<u32>().unwrap_or_default()).await;
Ok(()) Ok(())
} }
@@ -35,16 +37,16 @@ fn compress(data: Vec<u8>) -> Vec<u8> {
encoder.finish().unwrap() encoder.finish().unwrap()
} }
pub async fn load_data(id: String, temp: bool) -> Result<(), Error> { pub async fn load_data(id: String, temp: bool) -> Result<(), NotificationData> {
let api_url = API_URL.to_string(); let api_url = API_URL.to_string();
let id_url = format!("{api_url}download/{id}"); let id_url = format!("{api_url}download/{id}");
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let data = client let data = client
.get(&id_url) .get(&id_url)
.send() .send()
.await? .await.map_err(|_| WebApiUnavailable)?
.bytes() .bytes()
.await? .await.map_err(|_| WebApiUnavailable)?
.to_vec(); .to_vec();
let data = decompress(data); let data = decompress(data);
@@ -52,15 +54,15 @@ pub async fn load_data(id: String, temp: bool) -> Result<(), Error> {
let file_name = if temp { "data.db.tmp" } else { "data.db" }; let file_name = if temp { "data.db.tmp" } else { "data.db" };
let db_file = path.join(file_name); let db_file = path.join(file_name);
tokio::fs::write(db_file, data).await.unwrap(); tokio::fs::write(db_file, data).await.map_err(|_| PermissionDenied)?;
let version_url = format!("{API_URL}{id}/version"); let version_url = format!("{API_URL}{id}/version");
let version = client let version = client
.get(&version_url) .get(&version_url)
.send() .send()
.await? .await.map_err(|_| WebApiUnavailable)?
.text() .text()
.await?; .await.map_err(|_| WebApiUnavailable)?;
set_local_version(version.parse::<u32>().unwrap_or_default()).await; set_local_version(version.parse::<u32>().unwrap_or_default()).await;
Ok(()) Ok(())
} }
@@ -75,7 +77,7 @@ pub fn decompress(data: Vec<u8>) -> Vec<u8> {
decompressed decompressed
} }
pub async fn first_sync() -> Result<String, ()> { pub async fn first_sync() -> Result<String, NotificationData> {
let id_url = API_URL.to_string() + "generate"; let id_url = API_URL.to_string() + "generate";
let client = reqwest::Client::new(); let client = reqwest::Client::new();
@@ -83,18 +85,18 @@ pub async fn first_sync() -> Result<String, ()> {
.get(&id_url) .get(&id_url)
.send() .send()
.await .await
.map_err(|_| ())? .map_err(|_| WebApiUnavailable)?
.text() .text()
.await .await
.map_err(|_| ())?; .map_err(|_| WebApiUnavailable)?;
println!("id: {}", id); println!("id: {}", id);
Ok(id) Ok(id)
} }
pub async fn get_web_version(key: &str) -> Result<u32, reqwest::Error> { pub async fn get_web_version(key: &str) -> Result<u32, NotificationData> {
let id_url = format!("{API_URL}{key}/version"); let id_url = format!("{API_URL}{key}/version");
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let version = client.get(&id_url).send().await?.text().await?; let version = client.get(&id_url).send().await.map_err(|_| WebApiUnavailable)?.text().await.map_err(|_| WebApiUnavailable)?;
println!("version: {}", version); println!("version: {}", version);
Ok(version.parse::<u32>().unwrap_or_default()) Ok(version.parse::<u32>().unwrap_or_default())
} }
+20 -15
View File
@@ -1,3 +1,4 @@
use crate::app::{fill_state, AppState};
use crate::data_provider::history::{get_history_of_set, history_dir}; use crate::data_provider::history::{get_history_of_set, history_dir};
use crate::data_provider::sqlite::{create_db, default_connection}; use crate::data_provider::sqlite::{create_db, default_connection};
use crate::data_provider::web_api::{get_local_version, get_web_version, load_data, set_local_version}; use crate::data_provider::web_api::{get_local_version, get_web_version, load_data, set_local_version};
@@ -8,8 +9,8 @@ use crate::import::{ImportMessage, ImportState};
use crate::lang::Id; use crate::lang::Id;
use crate::message_navigation; use crate::message_navigation;
use crate::navigation::Page::*; use crate::navigation::Page::*;
use crate::navigation::RootMessage::{DataLoaded, Keyboard, PushNotification, UpdateData, Notification}; use crate::navigation::RootMessage::{DataLoaded, Keyboard, Notification, PushNotification, UpdateData};
use crate::notification::{NotificationRequest, NotificationManager, NotificationMessage}; use crate::notification::{NotificationData, NotificationManager, NotificationMessage, NotificationRequest};
use crate::quiz::{QuizMessage, QuizState}; use crate::quiz::{QuizMessage, QuizState};
use crate::randomizer::{RandomizerMessage, RandomizerState}; use crate::randomizer::{RandomizerMessage, RandomizerState};
use crate::repetition::{RepetitionMessage, RepetitionState}; use crate::repetition::{RepetitionMessage, RepetitionState};
@@ -22,18 +23,16 @@ use crate::sync::{SyncMessage, SyncState};
use crate::view_navigation; use crate::view_navigation;
use crate::word::{WordMessage, WordState}; use crate::word::{WordMessage, WordState};
use crate::writing::{WritingMessage, WritingState}; use crate::writing::{WritingMessage, WritingState};
use crate::app::{fill_state, AppState};
use chrono::NaiveDate; use chrono::NaiveDate;
use hashbrown::HashMap; use hashbrown::HashMap;
use iced::keyboard::Event; use iced::keyboard::Event;
use iced::widget::stack; use iced::widget::stack;
use iced::{Element, Task}; use iced::{Element, Task};
use iced_core::Length::Fill;
use parking_lot::Mutex; use parking_lot::Mutex;
use reqwest::Error;
use rusqlite::Connection; use rusqlite::Connection;
use std::sync::Arc; use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use iced_core::Length::Fill;
impl Default for ScreenState { impl Default for ScreenState {
fn default() -> Self { fn default() -> Self {
@@ -108,15 +107,21 @@ impl ScreenState {
let key = state_guard.sync_data.key.clone().unwrap(); let key = state_guard.sync_data.key.clone().unwrap();
final_task = Task::batch([ final_task = Task::batch([
reading_additional_task, reading_additional_task,
Task::perform(Self::load_web_backup(key), |result| { Task::perform(
if let Ok(update) = result Self::load_web_backup(key),
&& update |result| {
{ match result {
UpdateData Ok(update) => {
} else { if update {
RootMessage::None UpdateData
}else {
RootMessage::None
}
}
Err(err) => PushNotification(NotificationRequest::Warning(err))
}
} }
}), ),
]); ]);
} else { } else {
final_task = reading_additional_task; final_task = reading_additional_task;
@@ -153,7 +158,7 @@ impl ScreenState {
DataLoaded(map) DataLoaded(map)
} }
async fn load_web_backup(string: String) -> Result<bool, Error> { async fn load_web_backup(string: String) -> Result<bool, NotificationData> {
let local = get_local_version().await; let local = get_local_version().await;
let web = get_web_version(string.as_str()).await?; let web = get_web_version(string.as_str()).await?;
println!("{} {}", local, web); println!("{} {}", local, web);
@@ -198,7 +203,7 @@ impl ScreenState {
if let Notification(message) = message { if let Notification(message) = message {
return self.notification_manager.update(message); return self.notification_manager.update(message);
} }
if let PushNotification(notification) = &message { if let PushNotification(notification) = &message {
return self.notification_manager.push(notification.clone()) return self.notification_manager.push(notification.clone())
} }
+4
View File
@@ -154,6 +154,9 @@ impl NotificationManager {
NotificationData::PermissionDenied => { NotificationData::PermissionDenied => {
text!("У приложение недостаточно прав") text!("У приложение недостаточно прав")
} }
NotificationData::WebApiUnavailable => {
text!("Не получается подключиться к Api")
}
} }
.width(Fill) .width(Fill)
.into() .into()
@@ -175,4 +178,5 @@ pub enum NotificationData {
IncorrectAnkiFile, IncorrectAnkiFile,
OpenFileError, OpenFileError,
VoiceVoxUnavailable, VoiceVoxUnavailable,
WebApiUnavailable,
} }
+1 -1
View File
@@ -63,7 +63,7 @@ impl NavigatedPage<SyncMessage> for SyncState {
return Task::perform(first_sync(), |id| { return Task::perform(first_sync(), |id| {
match id { match id {
Ok(id) => RootMessage::Sync(IdReceived(id)), Ok(id) => RootMessage::Sync(IdReceived(id)),
Err(_) => RootMessage::None Err(err) => RootMessage::PushNotification(NotificationRequest::Error(err))
} }
}); });
} }