added more boilerplate for using login, but the misskey login thing doesnt work so bleh

This commit is contained in:
emilis 2023-01-27 17:37:19 +00:00
parent e2776996ef
commit eef6c40dc1
6 changed files with 106 additions and 31 deletions

13
Cargo.lock generated
View File

@ -57,6 +57,17 @@ dependencies = [
"event-listener",
]
[[package]]
name = "async-trait"
version = "0.1.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-tungstenite"
version = "0.18.0"
@ -609,6 +620,7 @@ name = "kkdisp"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"serde",
"termion",
]
@ -618,6 +630,7 @@ name = "kkx"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"futures",
"kkdisp",
"misskey",

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.68"
async-trait = "0.1.63"
# termion = "2.0.1"
[dependencies.serde]
@ -14,4 +15,4 @@ version = "1"
features = ["std", "derive"]
[dependencies.termion]
git = "https://sectorinf.com/emilis/termion"
git = "https://sectorinf.com/emilis/termion"

View File

@ -227,7 +227,7 @@ where
);
let mut events_iter = termion::async_stdin().events();
let mut plans =
PlanState::from_plans(view.init()?, base_colorset)?;
PlanState::from_plans(view.init().await?, base_colorset)?;
plans.render(&mut screen)?;
// FIXME: current loop means that pasting a string with len >1
// results in only the first character being rendered, until
@ -235,7 +235,7 @@ where
loop {
if let Some(msg) = view.query() {
plans = plans.act_on(
view.update(Event::Message(msg))?,
view.update(Event::Message(msg)).await?,
&mut screen,
)?;
continue;
@ -304,7 +304,8 @@ where
// }
if let Some(event) = event {
plans = plans.act_on(view.update(event)?, &mut screen)?;
plans = plans
.act_on(view.update(event).await?, &mut screen)?;
}
}
Ok(())
@ -368,10 +369,11 @@ pub enum Action {
Nothing,
}
#[async_trait::async_trait]
pub trait View {
type Message;
fn init(
async fn init(
&mut self,
) -> std::result::Result<PlanLayers, anyhow::Error>;
@ -380,7 +382,7 @@ pub trait View {
// from some sort of queue, or None if there's an empty queue.
fn query(&mut self) -> Option<Self::Message>;
fn update(
async fn update(
&mut self,
event: Event<Self::Message>,
) -> std::result::Result<Action, anyhow::Error>;

View File

@ -9,6 +9,7 @@ edition = "2021"
anyhow = "1.0.68"
kkdisp = { version = "0.1.0", path = "../kkdisp" }
futures = "0.3.25"
async-trait = "0.1.63"
[dependencies.tokio]
version = "1.24.2"

View File

@ -6,10 +6,12 @@ use kkdisp::{
view::{Event, Key},
Action,
};
use misskey::{StreamingClientExt, WebSocketClient};
use tokio::sync::mpsc::{self, Receiver, Sender};
use misskey::{
websocket::WebSocketClientBuilder, ClientExt, StreamingClientExt,
WebSocketClient,
};
use crate::Message;
use crate::{AuthDetail, Message};
pub enum LoginFocus {
Hostname,
Token,
@ -30,7 +32,7 @@ pub struct LoginPrompt {
token: String,
error: Option<String>,
focus: LoginFocus,
client: Option<WebSocketClient>,
client: Option<AuthDetail>,
}
impl LoginPrompt {
@ -62,12 +64,13 @@ impl LoginPrompt {
LoginFocus::OK => {}
}
}
pub fn query(&mut self) -> Option<()> {
todo!()
pub fn query(&mut self) -> Option<AuthDetail> {
self.client.take()
}
pub fn attempt(&mut self) {
let hostname = self.hostname.clone();
pub async fn attempt(&mut self) {
let hostname =
self.hostname.trim_end_matches('/').to_string();
if hostname.len() == 0 {
self.error = Some("empty hostname".into());
self.focus = LoginFocus::Hostname;
@ -79,17 +82,42 @@ impl LoginPrompt {
self.focus = LoginFocus::Token;
return;
}
todo!();
let auth = AuthDetail { hostname, token };
match auth.normal().await {
Ok(client) => {
match client.recommended_users().try_next().await {
Ok(next) => {
eprintln!("next: {:#?}", next);
self.client = Some(auth);
}
Err(err) => {
self.error = Some(err.to_string());
}
};
}
Err(err) => {
self.error = Some(err.to_string());
}
};
}
pub fn update(
fn down(&mut self) {
self.focus = match self.focus {
LoginFocus::Hostname => LoginFocus::Token,
LoginFocus::Token => LoginFocus::OK,
LoginFocus::OK => LoginFocus::Hostname,
};
}
pub async fn update(
&mut self,
event: Event<Message>,
) -> Result<Action, anyhow::Error> {
match event {
Event::Link(lnk) => {
if lnk == "ok" {
self.attempt();
self.attempt().await;
Ok(Action::ReplaceAll(vec![self.plan()]))
} else if lnk == "token" {
self.focus = LoginFocus::Token;
@ -110,9 +138,10 @@ impl LoginPrompt {
LoginFocus::Token => {
self.focus = LoginFocus::OK;
}
LoginFocus::OK => self.attempt(),
LoginFocus::OK => self.attempt().await,
},
Key::Backspace => self.backspace(),
Key::Tab => self.down(),
Key::Up => {
self.focus = match self.focus {
LoginFocus::Hostname => LoginFocus::OK,
@ -120,13 +149,7 @@ impl LoginPrompt {
LoginFocus::OK => LoginFocus::Token,
};
}
Key::Down => {
self.focus = match self.focus {
LoginFocus::Hostname => LoginFocus::Token,
LoginFocus::Token => LoginFocus::OK,
LoginFocus::OK => LoginFocus::Hostname,
};
}
Key::Down => self.down(),
Key::Char(c) => match self.focus {
LoginFocus::Hostname => self.hostname.push(c),
LoginFocus::Token => self.token.push(c),

View File

@ -8,6 +8,9 @@ use kkdisp::{
Action, PlanLayers, View,
};
use login::LoginPrompt;
use misskey::{
websocket::WebSocketClientBuilder, HttpClient, WebSocketClient,
};
use tokio::sync::mpsc::{self, Receiver, Sender};
mod login;
@ -17,6 +20,30 @@ async fn main() {
std::process::exit(0);
}
#[derive(Clone, Debug)]
pub struct AuthDetail {
pub hostname: String,
pub token: String,
}
impl AuthDetail {
pub async fn streaming(
&self,
) -> Result<WebSocketClient, anyhow::Error> {
Ok(WebSocketClientBuilder::with_host(&self.hostname)
.token(&self.token)
.connect()
.await?)
}
pub async fn normal(&self) -> Result<HttpClient, anyhow::Error> {
Ok(HttpClient::builder(
format!("https://{}", &self.hostname).as_str(),
)
.token(&self.token)
.build()?)
}
}
pub enum Page {
Login(LoginPrompt),
}
@ -31,6 +58,7 @@ impl Page {
pub struct AppView {
recv: Receiver<Message>,
auth: Option<AuthDetail>,
page: Page,
}
@ -46,35 +74,42 @@ impl Default for AppView {
Self {
recv,
page: Page::Login(LoginPrompt::new()),
auth: None,
}
}
}
pub enum Message {}
#[async_trait::async_trait]
impl View for AppView {
type Message = Message;
fn init(
async fn init(
&mut self,
) -> std::result::Result<kkdisp::PlanLayers, anyhow::Error> {
self.page.init()
}
fn update(
async fn update(
&mut self,
event: Event<Self::Message>,
) -> std::result::Result<Action, anyhow::Error> {
let page = &mut self.page;
match page {
Page::Login(login) => login.update(event),
Page::Login(login) => login.update(event).await,
}
}
fn query(&mut self) -> Option<Self::Message> {
match self.recv.try_recv() {
Ok(msg) => Some(msg),
Err(_) => None,
match &mut self.page {
Page::Login(log) => match log.query() {
Some(auth) => {
self.auth = Some(auth);
None
}
None => None,
},
}
}
}