Compare commits
10 commits
1d4c36d607
...
1d7d379e61
Author | SHA1 | Date | |
---|---|---|---|
1d7d379e61 | |||
53724cbb4f | |||
6bb9cc2eeb | |||
3fdf0e69ba | |||
984cdd740e | |||
bd1c2112f5 | |||
ff3bc9c8aa | |||
57396e708f | |||
2ea242c5cf | |||
815764bafb |
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -3,10 +3,6 @@
|
||||||
debug/
|
debug/
|
||||||
target/
|
target/
|
||||||
|
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
|
||||||
Cargo.lock
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
|
5186
Cargo.lock
generated
Normal file
5186
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "jiji"
|
name = "jiji"
|
||||||
version = "1.0.1"
|
version = "1.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"categories":[{"name":"to do","content":[{"name":"clean up bot code","description":"try to remove unnecessary code\n\nunindent\n\ngive sender to function ?","id":2},{"name":"trayable ?","description":"// Hello there","id":5},{"name":"new message marker","description":"perma if too complicated to detect read","id":2},{"name":"proper links","description":"when there is a link, ability to click it","id":3},{"name":"move config","description":"move config from .jiji/save.json\nto .config/jiji/config.json","id":2}]},{"name":"in progress","content":[]},{"name":"done","content":[{"name":"run discord bot","description":"make it so the bot is running","id":1},{"name":"fixed token in github","description":"// Hello there","id":1},{"name":"fetch previous messages","description":"// Hello there","id":4},{"name":"ability to write messages","description":"// Hello there","id":5},{"name":"get incoming messages","description":"read","id":2},{"name":"unread system","description":"add a * when a channel just received a message","id":1},{"name":"remember channel id for dm","description":"and put in config file\n\nmaybe load message ? dm first ?","id":3},{"name":"bug : does not save notification state for dm","description":"// Hello there","id":1},{"name":"handle unknown channel better","description":"when receiving a message from a not yet scanned guild, create the channel and put the message\n\nallow scanning if guild selected\n\ndo not add duplicate channel","id":1},{"name":"guild unread ?","description":"// Hello there","id":2},{"name":"timestamps","description":"// Hello there","id":1},{"name":"better ui error display","description":"handle the error packet for better display","id":1},{"name":"notifications !!!","description":"// Hello there","id":4}]},{"name":"bugs","content":[]},{"name":"v1.0","content":[{"name":"ability to change token","description":"use a config file to store token so that \n\n1- it is away from github\n\n2- it is configurable if need be","id":1}]},{"name":"+","content":[]}]}
|
{"categories":[{"name":"to do","content":[{"name":"clean up bot code","description":"try to remove unnecessary code\n\nunindent\n\ngive sender to function ?","id":2},{"name":"trayable ?","description":"// Hello there","id":5},{"name":"memory leak ?","description":"peaked at 4.2 Go Ram","id":1},{"name":"tenor favourite gif bank","description":"// Hello there","id":1}]},{"name":"in progress","content":[]},{"name":"done","content":[{"name":"run discord bot","description":"make it so the bot is running","id":1},{"name":"fixed token in github","description":"// Hello there","id":1},{"name":"fetch previous messages","description":"// Hello there","id":4},{"name":"ability to write messages","description":"// Hello there","id":5},{"name":"get incoming messages","description":"read","id":2},{"name":"unread system","description":"add a * when a channel just received a message","id":1},{"name":"remember channel id for dm","description":"and put in config file\n\nmaybe load message ? dm first ?","id":3},{"name":"bug : does not save notification state for dm","description":"// Hello there","id":1},{"name":"handle unknown channel better","description":"when receiving a message from a not yet scanned guild, create the channel and put the message\n\nallow scanning if guild selected\n\ndo not add duplicate channel","id":1},{"name":"guild unread ?","description":"// Hello there","id":2},{"name":"timestamps","description":"// Hello there","id":1},{"name":"better ui error display","description":"handle the error packet for better display","id":1},{"name":"notifications !!!","description":"// Hello there","id":4},{"name":"ability to change token","description":"use a config file to store token so that \n\n1- it is away from github\n\n2- it is configurable if need be","id":1},{"name":"fix timestam (utc+2)","description":"// Hello there","id":1},{"name":"move config","description":"move config from .jiji/save.json\nto .config/jiji/config.json","id":2},{"name":"scroll to bottom when new message","description":"// Hello there","id":1},{"name":"proper links","description":"when there is a link, ability to click it","id":3},{"name":"text emoji","description":"( ˘ w˘(˘w ˘ )","id":2}]},{"name":"bugs","content":[]},{"name":"v1.0","content":[]},{"name":"v1.1","content":[]},{"name":"+","content":[]}]}
|
16
shell.nix
16
shell.nix
|
@ -1,13 +1,6 @@
|
||||||
{ pkgs ? import <nixpkgs> { overlays = [ (import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz)) ]; },
|
{ pkgs ? import <nixpkgs> { overlays = [ (import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz)) ]; },}:
|
||||||
unstable ? import <nixos-unstable> { config = { allowUnfree = true; }; }
|
|
||||||
}:
|
|
||||||
with pkgs;
|
with pkgs;
|
||||||
|
|
||||||
let
|
|
||||||
# Specify Pillow as a build input
|
|
||||||
pillow = python3Packages.pillow;
|
|
||||||
in
|
|
||||||
|
|
||||||
mkShell {
|
mkShell {
|
||||||
nativeBuildInputs = with xorg; [
|
nativeBuildInputs = with xorg; [
|
||||||
libxcb
|
libxcb
|
||||||
|
@ -17,8 +10,11 @@ mkShell {
|
||||||
pkg-config
|
pkg-config
|
||||||
] ++ [
|
] ++ [
|
||||||
cargo
|
cargo
|
||||||
unstable.rustc
|
rustc
|
||||||
python3
|
atk
|
||||||
|
gdk-pixbuf
|
||||||
|
webkitgtk
|
||||||
|
glib
|
||||||
libGL
|
libGL
|
||||||
libGLU
|
libGLU
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
|
|
|
@ -79,6 +79,10 @@ pub struct Channel {
|
||||||
pub messages: Vec<Message>,
|
pub messages: Vec<Message>,
|
||||||
pub notify: bool,
|
pub notify: bool,
|
||||||
pub unread: bool,
|
pub unread: bool,
|
||||||
|
pub scroll_offset: f32,
|
||||||
|
pub content_size: f32,
|
||||||
|
pub inner_size: f32,
|
||||||
|
pub registered_messages: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
|
@ -90,6 +94,10 @@ impl Channel {
|
||||||
messages: vec![Message::create("0".into(), id, guild_id, "+".into(), "".into(), "".into())],
|
messages: vec![Message::create("0".into(), id, guild_id, "+".into(), "".into(), "".into())],
|
||||||
notify: false,
|
notify: false,
|
||||||
unread: false,
|
unread: false,
|
||||||
|
scroll_offset: 0.0,
|
||||||
|
content_size: 0.0,
|
||||||
|
inner_size: 0.0,
|
||||||
|
registered_messages: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
src/emoji_window.rs
Normal file
37
src/emoji_window.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use eframe::egui;
|
||||||
|
|
||||||
|
pub struct EmojiWindow {
|
||||||
|
pub visible: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EmojiWindow {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { visible: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show(&mut self, ctx: &egui::Context) {
|
||||||
|
let mut visible = self.visible;
|
||||||
|
egui::Window::new("Emojis")
|
||||||
|
.open(&mut visible)
|
||||||
|
.vscroll(true)
|
||||||
|
.hscroll(true)
|
||||||
|
.show(ctx, |ui| self.ui(ui));
|
||||||
|
self.visible = self.visible && visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
|
ui.set_min_width(250.0);
|
||||||
|
ui.label("\\(°^°)/");
|
||||||
|
ui.label("o(`O´)o");
|
||||||
|
ui.label("•`_´•");
|
||||||
|
ui.label("( ☉ _ ☉ )");
|
||||||
|
ui.label("~(o _ o)~");
|
||||||
|
ui.label("~(-■_■)~ ♪♬");
|
||||||
|
ui.label("☆ (◕w◕) ☆");
|
||||||
|
ui.label("\\(^o^)/");
|
||||||
|
ui.label("✌(^o^)✌");
|
||||||
|
ui.label("(♥u♥)");
|
||||||
|
ui.label("(T_T)");
|
||||||
|
ui.label("☭ ♥ ✿ ☢ ☠");
|
||||||
|
}
|
||||||
|
}
|
29
src/main.rs
29
src/main.rs
|
@ -12,6 +12,8 @@ mod discord_structure;
|
||||||
mod state;
|
mod state;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod app;
|
mod app;
|
||||||
|
mod emoji_window;
|
||||||
|
use emoji_window::EmojiWindow;
|
||||||
|
|
||||||
const MAX_FPS: f32 = 30.0;
|
const MAX_FPS: f32 = 30.0;
|
||||||
const RUNNING_REQUEST_REFRESH_DELAY: f32 = 0.2;
|
const RUNNING_REQUEST_REFRESH_DELAY: f32 = 0.2;
|
||||||
|
@ -63,6 +65,8 @@ struct Jiji {
|
||||||
current_message: String,
|
current_message: String,
|
||||||
channels_to_notify: Vec<String>,
|
channels_to_notify: Vec<String>,
|
||||||
errors: Vec<String>,
|
errors: Vec<String>,
|
||||||
|
redraw: bool,
|
||||||
|
emoji_window: EmojiWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Jiji {
|
impl Jiji {
|
||||||
|
@ -96,6 +100,8 @@ impl Jiji {
|
||||||
current_message: "".into(),
|
current_message: "".into(),
|
||||||
channels_to_notify: app_state.channels_to_notify.clone(),
|
channels_to_notify: app_state.channels_to_notify.clone(),
|
||||||
errors: vec![],
|
errors: vec![],
|
||||||
|
redraw: false,
|
||||||
|
emoji_window: EmojiWindow::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,6 +113,18 @@ impl eframe::App for Jiji {
|
||||||
));
|
));
|
||||||
self.next_frame = time::Instant::now();
|
self.next_frame = time::Instant::now();
|
||||||
|
|
||||||
|
//if ctx.input(|i| i.key_pressed(egui::Key::Enter) && i.modifiers.ctrl) {
|
||||||
|
if ctx.input_mut(|i| i.consume_shortcut(&egui::KeyboardShortcut::new(egui::Modifiers::CTRL, egui::Key::Enter))) {
|
||||||
|
if let Some(guild_index) = self.selected_guild {
|
||||||
|
if let Some(channel_index) = self.selected_channel {
|
||||||
|
if self.current_message != "" {
|
||||||
|
let _ = self.sender.send(postman::Packet::SendMessage(self.guilds[guild_index].channels[channel_index].id.clone(), self.current_message.clone()));
|
||||||
|
self.current_message = "".to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.handle_packets();
|
self.handle_packets();
|
||||||
|
|
||||||
self.draw_selection(ctx);
|
self.draw_selection(ctx);
|
||||||
|
@ -115,11 +133,19 @@ impl eframe::App for Jiji {
|
||||||
|
|
||||||
self.draw_feed(ctx);
|
self.draw_feed(ctx);
|
||||||
|
|
||||||
|
if self.emoji_window.visible {
|
||||||
|
self.emoji_window.show(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
self.time_watch = self.next_frame.elapsed().as_micros() as f32 / 1000.0;
|
self.time_watch = self.next_frame.elapsed().as_micros() as f32 / 1000.0;
|
||||||
|
|
||||||
if self.pending_bot_requests > 0 {
|
if self.pending_bot_requests > 0 {
|
||||||
egui::Context::request_repaint_after(ctx, Duration::from_secs_f32(RUNNING_REQUEST_REFRESH_DELAY));
|
egui::Context::request_repaint_after(ctx, Duration::from_secs_f32(RUNNING_REQUEST_REFRESH_DELAY));
|
||||||
}
|
}
|
||||||
|
if self.redraw {
|
||||||
|
egui::Context::request_repaint(ctx);
|
||||||
|
self.redraw = false;
|
||||||
|
}
|
||||||
egui::Context::request_repaint_after(ctx, Duration::from_secs_f32(BACKGROUND_REFRESH_DELAY));
|
egui::Context::request_repaint_after(ctx, Duration::from_secs_f32(BACKGROUND_REFRESH_DELAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +159,8 @@ pub fn save_path() -> PathBuf {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_path()
|
.as_path()
|
||||||
.join(".jiji")
|
.join(".config")
|
||||||
|
.join("jiji")
|
||||||
.join("save.json")
|
.join("save.json")
|
||||||
.to_path_buf()
|
.to_path_buf()
|
||||||
}
|
}
|
||||||
|
|
77
src/ui.rs
77
src/ui.rs
|
@ -1,9 +1,11 @@
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use chrono::DateTime;
|
use chrono::{DateTime, Local};
|
||||||
|
|
||||||
use crate::postman;
|
use crate::postman;
|
||||||
use crate::Jiji;
|
use crate::Jiji;
|
||||||
|
|
||||||
|
const MESSAGE_EDIT_ROWS : usize = 4;
|
||||||
|
|
||||||
impl Jiji {
|
impl Jiji {
|
||||||
pub fn draw_selection(&mut self, ctx: &egui::Context) {
|
pub fn draw_selection(&mut self, ctx: &egui::Context) {
|
||||||
egui::TopBottomPanel::top("server_selection")
|
egui::TopBottomPanel::top("server_selection")
|
||||||
|
@ -136,14 +138,20 @@ impl Jiji {
|
||||||
if let Some(channel_index) = self.selected_channel {
|
if let Some(channel_index) = self.selected_channel {
|
||||||
ui.label("");
|
ui.label("");
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.button(">").clicked() {
|
ui.vertical(|ui| {
|
||||||
let _ = self.sender.send(postman::Packet::SendMessage(self.guilds[guild_index].channels[channel_index].id.clone(), self.current_message.clone()));
|
if ui.button(">").clicked() && self.current_message != "" {
|
||||||
self.current_message = "".to_string();
|
let _ = self.sender.send(postman::Packet::SendMessage(self.guilds[guild_index].channels[channel_index].id.clone(), self.current_message.clone()));
|
||||||
}
|
self.current_message = "".to_string();
|
||||||
|
}
|
||||||
|
if ui.button("#").clicked() {
|
||||||
|
self.emoji_window.visible = !self.emoji_window.visible;
|
||||||
|
}
|
||||||
|
});
|
||||||
egui::ScrollArea::vertical()
|
egui::ScrollArea::vertical()
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let _response = ui.add(egui::TextEdit::multiline(&mut self.current_message)
|
let _response = ui.add(egui::TextEdit::multiline(&mut self.current_message)
|
||||||
.desired_width(f32::INFINITY)
|
.desired_width(f32::INFINITY)
|
||||||
|
.desired_rows(MESSAGE_EDIT_ROWS)
|
||||||
.lock_focus(true));
|
.lock_focus(true));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -165,31 +173,31 @@ impl Jiji {
|
||||||
|
|
||||||
pub fn draw_feed(&mut self, ctx: &egui::Context) {
|
pub fn draw_feed(&mut self, ctx: &egui::Context) {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
egui::ScrollArea::vertical()
|
if let Some(selected_guild_index) = &self.selected_guild {
|
||||||
.stick_to_bottom(true)
|
if let Some(selected_channel_index) = &self.selected_channel {
|
||||||
.show(ui, |ui| {
|
let selected_guild = &mut self.guilds[*selected_guild_index];
|
||||||
if let Some(selected_guild_index) = &self.selected_guild {
|
let selected_channel = &mut selected_guild.channels[*selected_channel_index];
|
||||||
if let Some(selected_channel_index) = &self.selected_channel {
|
|
||||||
|
let scrollarea_result = egui::ScrollArea::vertical()
|
||||||
|
.stick_to_bottom(true)
|
||||||
|
.vertical_scroll_offset(selected_channel.scroll_offset)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
|
||||||
let mut last_author = "".to_string();
|
let mut last_author = "".to_string();
|
||||||
|
|
||||||
if self.guilds[*selected_guild_index].channels[*selected_channel_index].messages.len() < 2 {
|
if selected_channel.messages.len() < 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for message in &self.guilds[*selected_guild_index].channels[*selected_channel_index].messages {
|
for message in &selected_channel.messages {
|
||||||
if message.author_name == "+" {
|
if message.author_name == "+" {
|
||||||
if ui.button("+").clicked() {
|
if ui.button("+").clicked() {
|
||||||
if let Some(selected_guild_index) = &self.selected_guild {
|
let _ = self.sender.send(postman::Packet::FetchMessages(
|
||||||
if let Some(selected_channel_index) = &self.selected_channel {
|
selected_guild.id.clone(),
|
||||||
let _ = self.sender.send(postman::Packet::FetchMessages(
|
selected_channel.id.clone(),
|
||||||
self.guilds[*selected_guild_index].id.clone(),
|
selected_channel.messages[1].id.clone(),
|
||||||
self.guilds[*selected_guild_index].channels[*selected_channel_index].id.clone(),
|
));
|
||||||
self.guilds[*selected_guild_index].channels[*selected_channel_index].messages[1].id.clone(),
|
self.pending_bot_requests += 1;
|
||||||
));
|
|
||||||
self.pending_bot_requests += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -198,7 +206,8 @@ impl Jiji {
|
||||||
ui.horizontal( |ui| {
|
ui.horizontal( |ui| {
|
||||||
ui.colored_label(hex_str_to_color("#3399ff"), &message.author_name);
|
ui.colored_label(hex_str_to_color("#3399ff"), &message.author_name);
|
||||||
if let Ok(timestamp) = DateTime::parse_from_rfc2822(&message.timestamp) {
|
if let Ok(timestamp) = DateTime::parse_from_rfc2822(&message.timestamp) {
|
||||||
ui.label(timestamp.format("%H:%M (%a, %e %b)").to_string());
|
let local_timestamp = timestamp.with_timezone(&Local);
|
||||||
|
ui.label(local_timestamp.format("%H:%M (%a, %e %b)").to_string());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -207,9 +216,29 @@ impl Jiji {
|
||||||
ui.label(&message.content);
|
ui.label(&message.content);
|
||||||
last_author = message.author_name.clone();
|
last_author = message.author_name.clone();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let new_content_size = scrollarea_result.content_size[1];
|
||||||
|
let new_inner_size = scrollarea_result.inner_rect.max.y - scrollarea_result.inner_rect.min.y;
|
||||||
|
|
||||||
|
if selected_channel.registered_messages != selected_channel.messages.len() {
|
||||||
|
if selected_channel.scroll_offset >= selected_channel.content_size - selected_channel.inner_size * 1.5 {
|
||||||
|
selected_channel.scroll_offset = new_content_size - new_inner_size;
|
||||||
|
} else if selected_channel.scroll_offset < 1.0 {
|
||||||
|
selected_channel.scroll_offset = new_content_size - selected_channel.content_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
selected_channel.registered_messages = selected_channel.messages.len();
|
||||||
|
self.redraw = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
selected_channel.scroll_offset = scrollarea_result.state.offset[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selected_channel.content_size = new_content_size;
|
||||||
|
selected_channel.inner_size = new_inner_size;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue