Following widget can only be accessed in chat/dashboard

This commit is contained in:
Xithrius 2023-07-27 21:22:41 -07:00
parent 60989703dc
commit 4e9a211e5e
No known key found for this signature in database
GPG Key ID: DF6738B80C155B71
7 changed files with 64 additions and 43 deletions

View File

@ -18,8 +18,9 @@ use crate::{
user_input::events::{Event, Key}, user_input::events::{Event, Key},
}, },
terminal::TerminalAction, terminal::TerminalAction,
twitch::oauth::FollowingList,
ui::{ ui::{
components::{utils::centered_rect, Component, Components}, components::{Component, Components},
statics::LINE_BUFFER_CAPACITY, statics::LINE_BUFFER_CAPACITY,
}, },
}; };
@ -58,7 +59,7 @@ macro_rules! shared {
} }
impl App { impl App {
pub fn new(config: CompleteConfig) -> Self { pub fn new(config: CompleteConfig, following: FollowingList) -> Self {
let shared_config = shared!(config.clone()); let shared_config = shared!(config.clone());
let shared_config_borrow = shared_config.borrow(); let shared_config_borrow = shared_config.borrow();
@ -83,6 +84,7 @@ impl App {
storage.clone(), storage.clone(),
filters.clone(), filters.clone(),
messages.clone(), messages.clone(),
following,
); );
Self { Self {
@ -124,11 +126,7 @@ impl App {
} }
} }
if self.components.following.is_focused() { if self.components.debug.is_focused() {
let rect = centered_rect(60, 60, 20, size);
self.components.following.draw(f, rect, None);
} else if self.components.debug.is_focused() {
let new_rect = Rect::new(size.x, size.y + 1, size.width - 1, size.height - 2); let new_rect = Rect::new(size.x, size.y + 1, size.width - 1, size.height - 2);
let rect = Layout::default() let rect = Layout::default()
@ -144,8 +142,6 @@ impl App {
if let Event::Input(key) = event { if let Event::Input(key) = event {
if self.components.debug.is_focused() { if self.components.debug.is_focused() {
return self.components.debug.event(event); return self.components.debug.event(event);
} else if self.components.following.is_focused() {
return self.components.following.event(event);
} }
match key { match key {
@ -153,9 +149,6 @@ impl App {
Key::Ctrl('d') => { Key::Ctrl('d') => {
self.components.debug.toggle_focus(); self.components.debug.toggle_focus();
} }
Key::Char('f') => {
self.components.following.toggle_focus();
}
_ => { _ => {
return match self.state { return match self.state {
State::Dashboard => self.components.dashboard.event(event), State::Dashboard => self.components.dashboard.event(event),

View File

@ -11,7 +11,7 @@
clippy::too_many_lines clippy::too_many_lines
)] )]
use crate::emotes::graphics_protocol::get_terminal_cell_size; use crate::{emotes::graphics_protocol::get_terminal_cell_size, twitch::oauth::get_following};
use clap::Parser; use clap::Parser;
use color_eyre::eyre::{Result, WrapErr}; use color_eyre::eyre::{Result, WrapErr};
use log::{info, warn}; use log::{info, warn};
@ -72,10 +72,9 @@ async fn main() -> Result<()> {
let (terminal_tx, twitch_rx) = broadcast::channel(100); let (terminal_tx, twitch_rx) = broadcast::channel(100);
let (emotes_tx, emotes_rx) = mpsc::channel(1); let (emotes_tx, emotes_rx) = mpsc::channel(1);
let mut app = App::new(config.clone()); let following = get_following(&config.twitch.clone()).await;
// TODO: Move this into the following file. let mut app = App::new(config.clone(), following);
app.components.following.get_following().await;
info!("Started tokio communication channels."); info!("Started tokio communication channels.");

View File

@ -5,6 +5,8 @@ use reqwest::{
}; };
use serde::Deserialize; use serde::Deserialize;
use crate::handlers::config::TwitchConfig;
#[derive(Deserialize)] #[derive(Deserialize)]
#[allow(dead_code)] #[allow(dead_code)]
pub struct ClientId { pub struct ClientId {
@ -112,3 +114,14 @@ pub async fn get_user_following(client: &Client, user_id: i32) -> FollowingList
.await .await
.unwrap() .unwrap()
} }
pub async fn get_following(twitch_config: &TwitchConfig) -> FollowingList {
let oauth_token = twitch_config.token.clone();
let app_user = twitch_config.username.clone();
let client = get_twitch_client(oauth_token).await.unwrap();
let user_id = get_channel_id(&client, &app_user).await.unwrap();
get_user_following(&client, user_id).await
}

View File

@ -27,9 +27,10 @@ use crate::{
}, },
}, },
terminal::TerminalAction, terminal::TerminalAction,
twitch::oauth::FollowingList,
ui::components::{ ui::components::{
utils::centered_rect, ChannelSwitcherWidget, ChatInputWidget, Component, following::FollowingWidget, utils::centered_rect, ChannelSwitcherWidget, ChatInputWidget,
MessageSearchWidget, Component, MessageSearchWidget,
}, },
utils::text::{title_line, TitleStyle}, utils::text::{title_line, TitleStyle},
}; };
@ -40,6 +41,7 @@ pub struct ChatWidget {
chat_input: ChatInputWidget, chat_input: ChatInputWidget,
channel_input: ChannelSwitcherWidget, channel_input: ChannelSwitcherWidget,
search_input: MessageSearchWidget, search_input: MessageSearchWidget,
following: FollowingWidget,
filters: SharedFilters, filters: SharedFilters,
pub scroll_offset: Scrolling, pub scroll_offset: Scrolling,
// theme: Theme, // theme: Theme,
@ -51,10 +53,12 @@ impl ChatWidget {
messages: SharedMessages, messages: SharedMessages,
storage: &SharedStorage, storage: &SharedStorage,
filters: SharedFilters, filters: SharedFilters,
following: FollowingList,
) -> Self { ) -> Self {
let chat_input = ChatInputWidget::new(config.clone(), storage.clone()); let chat_input = ChatInputWidget::new(config.clone(), storage.clone());
let channel_input = ChannelSwitcherWidget::new(config.clone(), storage.clone()); let channel_input = ChannelSwitcherWidget::new(config.clone(), storage.clone());
let search_input = MessageSearchWidget::new(config.clone()); let search_input = MessageSearchWidget::new(config.clone());
let following = FollowingWidget::new(config.clone(), following);
let scroll_offset = Scrolling::new(config.borrow().frontend.inverted_scrolling); let scroll_offset = Scrolling::new(config.borrow().frontend.inverted_scrolling);
@ -64,6 +68,7 @@ impl ChatWidget {
chat_input, chat_input,
channel_input, channel_input,
search_input, search_input,
following,
filters, filters,
scroll_offset, scroll_offset,
} }
@ -328,6 +333,9 @@ impl Component for ChatWidget {
} else if self.search_input.is_focused() { } else if self.search_input.is_focused() {
self.search_input self.search_input
.draw(f, v_chunks.next().copied().unwrap(), None); .draw(f, v_chunks.next().copied().unwrap(), None);
} else if self.following.is_focused() {
self.following
.draw(f, centered_rect(60, 60, 20, f.size()), None);
} }
} }
@ -342,6 +350,8 @@ impl Component for ChatWidget {
self.channel_input.event(event) self.channel_input.event(event)
} else if self.search_input.is_focused() { } else if self.search_input.is_focused() {
self.search_input.event(event) self.search_input.event(event)
} else if self.following.is_focused() {
self.following.event(event)
} else { } else {
match key { match key {
Key::Char('i' | 'c') => self.chat_input.toggle_focus(), Key::Char('i' | 'c') => self.chat_input.toggle_focus(),
@ -349,6 +359,7 @@ impl Component for ChatWidget {
Key::Char('/') => self.chat_input.toggle_focus_with("/"), Key::Char('/') => self.chat_input.toggle_focus_with("/"),
Key::Char('s') => self.channel_input.toggle_focus(), Key::Char('s') => self.channel_input.toggle_focus(),
Key::Ctrl('f') => self.search_input.toggle_focus(), Key::Ctrl('f') => self.search_input.toggle_focus(),
Key::Char('f') => self.following.toggle_focus(),
Key::Ctrl('t') => self.filters.borrow_mut().toggle(), Key::Ctrl('t') => self.filters.borrow_mut().toggle(),
Key::Ctrl('r') => self.filters.borrow_mut().reverse(), Key::Ctrl('r') => self.filters.borrow_mut().reverse(),
Key::Char('S') => return Some(TerminalAction::SwitchState(State::Dashboard)), Key::Char('S') => return Some(TerminalAction::SwitchState(State::Dashboard)),

View File

@ -18,11 +18,13 @@ use crate::{
user_input::events::{Event, Key}, user_input::events::{Event, Key},
}, },
terminal::TerminalAction, terminal::TerminalAction,
twitch::TwitchAction, twitch::{oauth::FollowingList, TwitchAction},
ui::components::{utils::centered_rect, ChannelSwitcherWidget, Component}, ui::components::{utils::centered_rect, ChannelSwitcherWidget, Component},
utils::styles::DASHBOARD_TITLE_COLOR, utils::styles::DASHBOARD_TITLE_COLOR,
}; };
use super::following::FollowingWidget;
const DASHBOARD_TITLE: [&str; 5] = [ const DASHBOARD_TITLE: [&str; 5] = [
" __ _ __ __ __ _ ", " __ _ __ __ __ _ ",
" / /__ __(_) /______/ /_ / /___ __(_)", " / /__ __(_) /______/ /_ / /___ __(_)",
@ -35,16 +37,23 @@ pub struct DashboardWidget {
config: SharedCompleteConfig, config: SharedCompleteConfig,
storage: SharedStorage, storage: SharedStorage,
channel_input: ChannelSwitcherWidget, channel_input: ChannelSwitcherWidget,
following: FollowingWidget,
} }
impl DashboardWidget { impl DashboardWidget {
pub fn new(config: SharedCompleteConfig, storage: SharedStorage) -> Self { pub fn new(
config: SharedCompleteConfig,
storage: SharedStorage,
following: FollowingList,
) -> Self {
let channel_input = ChannelSwitcherWidget::new(config.clone(), storage.clone()); let channel_input = ChannelSwitcherWidget::new(config.clone(), storage.clone());
let following = FollowingWidget::new(config.clone(), following);
Self { Self {
config, config,
storage, storage,
channel_input, channel_input,
following,
} }
} }
@ -215,6 +224,9 @@ impl Component for DashboardWidget {
if self.channel_input.is_focused() { if self.channel_input.is_focused() {
self.channel_input self.channel_input
.draw(f, centered_rect(60, 20, 3, f.size()), emotes); .draw(f, centered_rect(60, 20, 3, f.size()), emotes);
} else if self.following.is_focused() {
self.following
.draw(f, centered_rect(60, 60, 20, f.size()), None);
} }
} }
@ -222,12 +234,15 @@ impl Component for DashboardWidget {
if let Event::Input(key) = event { if let Event::Input(key) = event {
if self.channel_input.is_focused() { if self.channel_input.is_focused() {
return self.channel_input.event(event); return self.channel_input.event(event);
} else if self.following.is_focused() {
return self.following.event(event);
} }
match key { match key {
Key::Ctrl('p') => panic!("Manual panic triggered by user."), Key::Ctrl('p') => panic!("Manual panic triggered by user."),
Key::Char('q') => return Some(TerminalAction::Quit), Key::Char('q') => return Some(TerminalAction::Quit),
Key::Char('s') => self.channel_input.toggle_focus(), Key::Char('s') => self.channel_input.toggle_focus(),
Key::Char('f') => self.following.toggle_focus(),
Key::Enter => { Key::Enter => {
let action = TerminalAction::Enter(TwitchAction::Join( let action = TerminalAction::Enter(TwitchAction::Join(
self.config.borrow().twitch.channel.clone(), self.config.borrow().twitch.channel.clone(),

View File

@ -16,10 +16,7 @@ use crate::{
user_input::events::{Event, Key}, user_input::events::{Event, Key},
}, },
terminal::TerminalAction, terminal::TerminalAction,
twitch::{ twitch::{oauth::FollowingList, TwitchAction},
oauth::{get_channel_id, get_twitch_client, get_user_following, FollowingList},
TwitchAction,
},
ui::{components::Component, statics::NAME_MAX_CHARACTERS}, ui::{components::Component, statics::NAME_MAX_CHARACTERS},
utils::text::{title_line, TitleStyle}, utils::text::{title_line, TitleStyle},
}; };
@ -33,11 +30,11 @@ pub struct FollowingWidget {
} }
impl FollowingWidget { impl FollowingWidget {
pub fn new(config: SharedCompleteConfig) -> Self { pub fn new(config: SharedCompleteConfig, following: FollowingList) -> Self {
Self { Self {
config, config,
focused: false, focused: false,
following: FollowingList::default(), following,
state: TableState::default(), state: TableState::default(),
} }
} }
@ -68,17 +65,6 @@ impl FollowingWidget {
self.state.select(None); self.state.select(None);
} }
pub async fn get_following(&mut self) {
let oauth_token = self.config.borrow().twitch.token.clone();
let app_user = self.config.borrow().twitch.username.clone();
let client = get_twitch_client(oauth_token).await.unwrap();
let user_id = get_channel_id(&client, &app_user).await.unwrap();
self.following = get_user_following(&client, user_id).await;
}
pub const fn is_focused(&self) -> bool { pub const fn is_focused(&self) -> bool {
self.focused self.focused
} }

View File

@ -33,10 +33,9 @@ use crate::{
user_input::events::{Event, Key}, user_input::events::{Event, Key},
}, },
terminal::TerminalAction, terminal::TerminalAction,
twitch::oauth::FollowingList,
}; };
use self::following::FollowingWidget;
pub trait Component { pub trait Component {
#[allow(unused_variables)] #[allow(unused_variables)]
fn draw<B: Backend>(&mut self, f: &mut Frame<B>, area: Rect, emotes: Option<&mut Emotes>) { fn draw<B: Backend>(&mut self, f: &mut Frame<B>, area: Rect, emotes: Option<&mut Emotes>) {
@ -61,7 +60,6 @@ pub struct Components {
// Partial window widgets // Partial window widgets
pub tabs: StateTabsWidget, pub tabs: StateTabsWidget,
pub debug: DebugWidget, pub debug: DebugWidget,
pub following: FollowingWidget,
// Full window widgets // Full window widgets
pub chat: ChatWidget, pub chat: ChatWidget,
@ -76,14 +74,20 @@ impl Components {
storage: SharedStorage, storage: SharedStorage,
filters: SharedFilters, filters: SharedFilters,
messages: SharedMessages, messages: SharedMessages,
following: FollowingList,
) -> Self { ) -> Self {
Self { Self {
tabs: StateTabsWidget::new(config.clone()), tabs: StateTabsWidget::new(config.clone()),
debug: DebugWidget::new(config.clone()), debug: DebugWidget::new(config.clone()),
following: FollowingWidget::new(config.clone()),
chat: ChatWidget::new(config.clone(), messages, &storage, filters), chat: ChatWidget::new(
dashboard: DashboardWidget::new(config.clone(), storage), config.clone(),
messages,
&storage,
filters,
following.clone(),
),
dashboard: DashboardWidget::new(config.clone(), storage, following),
help: HelpWidget::new(config.clone()), help: HelpWidget::new(config.clone()),
error: ErrorWidget::new(), error: ErrorWidget::new(),
} }