Skip to content

Commit

Permalink
GH-29: Minor improvements
Browse files Browse the repository at this point in the history
- User comments are now shown in profile cards
- Empty user comment images are now animated
- replaced join channel with change user state
  • Loading branch information
SetZero committed May 28, 2023
1 parent fe5b994 commit 7a59ec3
Show file tree
Hide file tree
Showing 20 changed files with 119 additions and 68 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,5 @@ dist-ssr
*.sw?

src-tauri/data
src-tauri/src/proto/Mumble.proto
src-tauri/src/proto/Mumble.proto
src-tauri/gen
25 changes: 10 additions & 15 deletions src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,6 @@ pub async fn like_message(
Ok(())
}

#[tauri::command]
pub async fn join_channel(
channel_id: u32,
state: State<'_, ConnectionState>,
) -> Result<(), String> {
let guard = state.connection.lock().await;
if let Some(guard) = guard.as_ref() {
if let Err(e) = guard.join_channel(channel_id) {
return Err(format!("{e:?}"));
}
}

Ok(())
}

#[tauri::command]
pub async fn set_user_image(
image_path: &str,
Expand Down Expand Up @@ -180,3 +165,13 @@ pub async fn change_user_state(

Ok(())
}

#[tauri::command]
pub async fn get_audio_devices(state: State<'_, ConnectionState>) -> Result<Vec<String>, String> {
let connection = &state.connection;
let guard = connection.lock().await;

if let Some(guard) = guard.as_ref() {}

Err("Failed to get audio devices".to_string())
}
31 changes: 0 additions & 31 deletions src-tauri/src/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,37 +201,6 @@ impl Connection {
Ok(())
}

pub fn join_channel(&self, channel_id: u32) -> AnyError<()> {
let join_channel = mumble::proto::UserState {
session: None,
actor: None,
name: None,
user_id: None,
channel_id: Some(channel_id),
mute: None,
deaf: None,
suppress: None,
self_mute: None,
self_deaf: None,
texture: None,
plugin_context: None,
plugin_identity: None,
comment: None,
hash: None,
comment_hash: None,
texture_hash: None,
priority_speaker: None,
recording: None,
temporary_access_tokens: Vec::new(),
listening_channel_add: Vec::new(),
listening_channel_remove: Vec::new(),
listening_volume_adjustment: Vec::new(),
};
self.tx_out.send(message_builder(&join_channel))?;

Ok(())
}

pub fn update_user_info(&self, user: &mut UpdateableUserState) -> AnyError<()> {
let updated_state = mumble::proto::UserState {
session: None,
Expand Down
6 changes: 3 additions & 3 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use tracing::Level;
use tracing_subscriber::fmt;

use crate::commands::{
change_user_state, connect_to_server, join_channel, like_message, logout, send_message,
change_user_state, connect_to_server, get_audio_devices, like_message, logout, send_message,
set_user_image,
};

Expand Down Expand Up @@ -61,9 +61,9 @@ fn main() {
send_message,
logout,
like_message,
join_channel,
set_user_image,
change_user_state
change_user_state,
get_audio_devices
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/manager/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub struct User {
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct UpdateableUserState {
pub id: u32,
pub id: Option<u32>,
pub name: Option<String>,
pub channel_id: Option<u32>,
pub mute: Option<bool>,
Expand Down
29 changes: 29 additions & 0 deletions src-tauri/src/utils/audio/audio_device_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::collections::HashMap;

use rodio::{
cpal::{self, traits::HostTrait},
Device,
};

use crate::errors::AnyError;

struct AudioDeviceManager {
pub audio_device: Option<Device>,
pub audio_device_list: HashMap<u32, Device>,
}

impl AudioDeviceManager {
pub fn new() -> Self {
Self {
audio_device: None,
audio_device_list: HashMap::new(),
}
}

pub fn get_audio_device(&self) -> AnyError<Vec<Device>> {
let host = cpal::default_host();
let devices = host.input_devices()?;

Ok(devices.collect())
}
}
1 change: 1 addition & 0 deletions src-tauri/src/utils/audio/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod audio_device_manager;
pub mod decoder;
pub mod player;
pub mod recorder;
1 change: 0 additions & 1 deletion src-tauri/src/utils/audio/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ impl Player {

pub fn start(&mut self) -> AnyError<()> {
if self.playing.swap(true, Ordering::Relaxed) || self.audio_thread.is_some() {
error!("Audio thread already started");
return Err("Audio thread already started".into());
}

Expand Down
3 changes: 1 addition & 2 deletions src/components/ChannelSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import SearchIcon from '@mui/icons-material/Search';
import React from "react";
import { useSelector } from "react-redux";
import { RootState } from "../store/store";
import { getChannelImageFromDescription } from "../helper/ChannelInfoHelper";
import { invoke } from "@tauri-apps/api";
import './styles/ChannelSearch.css';
import Fuse from 'fuse.js';
Expand Down Expand Up @@ -46,7 +45,7 @@ function ChannelSearch() {

const joinChannel = (channelId: number) => (event: any) => {
event?.stopPropagation();
invoke('join_channel', { channelId: channelId });
invoke('change_user_state', { userState: { channel_id: channelId }});
}


Expand Down
2 changes: 1 addition & 1 deletion src/components/ChannelViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function ChannelViewer() {
}

function joinChannel(channelId: number) {
invoke('join_channel', { channelId: channelId });
invoke('change_user_state', { userState: { channel_id: channelId }});
}

function displayUserInfo(user: UsersState): ReactNode {
Expand Down
4 changes: 3 additions & 1 deletion src/components/CurrentUserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import MicOffIcon from '@mui/icons-material/MicOff';
import './styles/CurrentUserInfo.css'
import { invoke } from "@tauri-apps/api";
import { UpdateableUserState, UsersState, updateUser, updateUserFromUpdateable } from "../store/features/users/userSlice";
import "./styles/common.css"

function CurrentUserInfo() {
const dispatch = useDispatch();
Expand Down Expand Up @@ -58,7 +59,8 @@ function CurrentUserInfo() {
display: 'flex',
padding: '0 10px',
backgroundSize: 'cover',
}}>
}}
className={userBackground ? "" : "animated-background"}>
<Box sx={{
display: 'flex',
flexDirection: 'column',
Expand Down
16 changes: 10 additions & 6 deletions src/components/UserInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Typography, Popover, Card, Avatar, CardMedia, CardContent, Paper, IconButton, InputBase, Divider, Box } from "@mui/material";
import { UsersState } from "../store/features/users/userSlice";
import React, { useEffect, useState } from "react";
import { getBackgroundFromComment, getProfileImage } from "../helper/UserInfoHelper";
import { getBackgroundFromComment, getProfileImage, getTextFromcomment } from "../helper/UserInfoHelper";
import SendIcon from '@mui/icons-material/Send';
import "./styles/UserInfo.css";
import dayjs from "dayjs";
import MessageParser from "../helper/MessageParser";
import { ChatMessageHandler } from "../helper/ChatMessage";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../store/store";
import "./styles/common.css"

interface UserInfoProps {
anchorEl: HTMLElement | null;
Expand All @@ -17,8 +18,8 @@ interface UserInfoProps {
}

function UserInfo(props: UserInfoProps) {
const currentUser = useSelector((state: RootState) => state.reducer.userInfo.currentUser);
const background = getBackgroundFromComment(props.userInfo, false);
const profileText = getTextFromcomment(props.userInfo);
const [chatMessage, setChatMessage] = useState("");

const dispatch = useDispatch();
Expand All @@ -28,7 +29,7 @@ function UserInfo(props: UserInfoProps) {
let deafenedText = props.userInfo?.deafenedSince ? dayjs(props.userInfo?.deafenedSince).fromNow() : '';

function generateCardMedia() {
if (!background.startsWith("#")) {
if (background) {
return (
<CardMedia
component="img"
Expand All @@ -39,7 +40,7 @@ function UserInfo(props: UserInfoProps) {
);
} else {
return (
<Box sx={{ bgcolor: 'primary.main', width: '100%', height: 100 }} />
<Box sx={{ width: '100%', height: 100 }} className="animated-background" />
);
}
}
Expand All @@ -57,7 +58,7 @@ function UserInfo(props: UserInfoProps) {
function keyDownHandler(e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) {
if (e && e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
chatMessageHandler.sendPrivateMessage(chatMessage, currentUser, props.userInfo?.id || 0);
chatMessageHandler.sendPrivateMessage(chatMessage, props.userInfo?.id || 0);
}
}

Expand Down Expand Up @@ -97,6 +98,10 @@ function UserInfo(props: UserInfoProps) {
{showStatusBox("Muted", mutedText)}
{showStatusBox("Deafened", deafenedText)}
</Box>
<Divider sx={{ margin: '10px 0' }} />
<Box className="user-info-text">
<Box className="user-profile-content" dangerouslySetInnerHTML={{__html: profileText}}></Box>
</Box>
<Paper
component="form"
sx={{ p: '2px 4px', display: 'flex', alignItems: 'center' }}
Expand All @@ -109,7 +114,6 @@ function UserInfo(props: UserInfoProps) {
onChange={e => setChatMessage(e.target.value)}
onKeyDown={keyDownHandler}
value={chatMessage}
multiline
/>
<Divider sx={{ height: 28, m: 0.5 }} orientation="vertical" />
<IconButton color="primary" sx={{ p: '10px' }} aria-label="directions">
Expand Down
19 changes: 19 additions & 0 deletions src/components/settings/Audio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Container, Typography } from "@mui/material";
import { invoke } from "@tauri-apps/api";

function AudioSettings() {
function getAudioDevices() {
invoke('get_audio_devices')
.then((devices: any) => {
console.log(devices);
})
}

return (
<Container>
<Typography variant="h3">Audio</Typography>
</Container>
)
}

export default AudioSettings;
4 changes: 2 additions & 2 deletions src/components/styles/CurrentUserInfo.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.small_icon {
transform: scale(0.7);
}
transform: scale(0.7);
}
5 changes: 5 additions & 0 deletions src/components/styles/UserInfo.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@
justify-content: space-between;
align-items: center;
margin: 5px 0;
}

.user-profile-content {
max-height: 200px;
overflow: auto;
}
17 changes: 17 additions & 0 deletions src/components/styles/common.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.animated-background {
animation: gradient 40s ease infinite;
background: linear-gradient(137.42deg, #BF247A 0%, #812B8C 25%, #2A2359 50%, #D9731A 75%, #BF3939 100%);
background-size: 300% 300% !important;
}

@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
2 changes: 1 addition & 1 deletion src/helper/ChatMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class ChatMessageHandler {
this.setChatMessage("");
}

public sendPrivateMessage(data: string, userInfo: UsersState | undefined, reciever: number) {
public sendPrivateMessage(data: string, reciever: number) {
invoke('send_message', { chatMessage: data, reciever: reciever });
this.setChatMessage("");
}
Expand Down
12 changes: 11 additions & 1 deletion src/helper/UserInfoHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useSelector } from "react-redux";
import { RootState } from "../store/store";

export function getBackgroundFromComment(user: UsersState | undefined, withUrl: boolean = true) {
let defaultColor = "#0057b7";
let defaultColor = undefined;

if (!user || !user.comment) {
return defaultColor;
Expand All @@ -23,6 +23,16 @@ export function getBackgroundFromComment(user: UsersState | undefined, withUrl:

}

export function getTextFromcomment(user: UsersState | undefined) {
if (!user || !user.comment) {
return "";
}

let cleanMessage = DOMPurify.sanitize(user.comment, {ALLOWED_TAGS: ['b', 'ul', 'li', 'i', 'br', 'span', 'div', 'p']});

return cleanMessage;
}

export function getProfileImage(user_id: number) {
const userList = useSelector((state: RootState) => state.reducer.userInfo);

Expand Down
3 changes: 2 additions & 1 deletion src/routes/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import PersonIcon from '@mui/icons-material/Person';
import KeyIcon from '@mui/icons-material/Key';
import SecurityIcon from '@mui/icons-material/Security';
import Profile from "../components/settings/Profile";
import AudioSettings from "../components/settings/Audio";

function Settings() {
const navigate = useNavigate();
Expand Down Expand Up @@ -63,7 +64,7 @@ function Settings() {
</Box>
<Box sx={{ flexGrow: 1, overflow: 'auto' }}>
<Box sx={{ p: 3 }}>
{selectedIndex === 0 && <div>Audio</div>}
{selectedIndex === 0 && <AudioSettings />}
{selectedIndex === 1 && <Profile />}
{selectedIndex === 2 && <div>Additional Features</div>}
{selectedIndex === 3 && <div>Privacy</div>}
Expand Down
2 changes: 1 addition & 1 deletion src/store/features/users/userSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'


export interface UpdateableUserState {
id: number
id?: number
channel_id?: number,
comment?: string,
deaf?: boolean,
Expand Down

0 comments on commit 7a59ec3

Please sign in to comment.