Merge pull request #241 from jeyemwey/jv-119-remove-avatars
Remove Chat Avatars Thanks for the cleanup! Looks great.
This commit is contained in:
commit
57f2e4b567
@ -36,7 +36,6 @@ func createTable(db *sql.DB) {
|
||||
"id" string NOT NULL PRIMARY KEY,
|
||||
"author" TEXT,
|
||||
"body" TEXT,
|
||||
"image" TEXT,
|
||||
"messageType" TEXT,
|
||||
"visible" INTEGER,
|
||||
"timestamp" DATE
|
||||
@ -51,11 +50,11 @@ func createTable(db *sql.DB) {
|
||||
|
||||
func addMessage(message models.ChatMessage) {
|
||||
tx, err := _db.Begin()
|
||||
stmt, err := tx.Prepare("INSERT INTO messages(id, author, body, image, messageType, visible, timestamp) values(?, ?, ?, ?, ?, ?, ?)")
|
||||
stmt, err := tx.Prepare("INSERT INTO messages(id, author, body, messageType, visible, timestamp) values(?, ?, ?, ?, ?, ?)")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
_, err = stmt.Exec(message.ID, message.Author, message.Body, message.Image, message.MessageType, 1, message.Timestamp)
|
||||
_, err = stmt.Exec(message.ID, message.Author, message.Body, message.MessageType, 1, message.Timestamp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -78,12 +77,11 @@ func getChatHistory() []models.ChatMessage {
|
||||
var id string
|
||||
var author string
|
||||
var body string
|
||||
var image string
|
||||
var messageType string
|
||||
var visible int
|
||||
var timestamp time.Time
|
||||
|
||||
err = rows.Scan(&id, &author, &body, &image, &messageType, &visible, ×tamp)
|
||||
err = rows.Scan(&id, &author, &body, &messageType, &visible, ×tamp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -92,7 +90,6 @@ func getChatHistory() []models.ChatMessage {
|
||||
message.ID = id
|
||||
message.Author = author
|
||||
message.Body = body
|
||||
message.Image = image
|
||||
message.MessageType = messageType
|
||||
message.Visible = visible == 1
|
||||
message.Timestamp = timestamp
|
||||
|
@ -140,7 +140,7 @@ func (s *server) sendWelcomeMessageToClient(c *Client) {
|
||||
time.Sleep(7 * time.Second)
|
||||
|
||||
initialChatMessageText := fmt.Sprintf("Welcome to %s! %s", config.Config.InstanceDetails.Title, config.Config.InstanceDetails.Summary)
|
||||
initialMessage := models.ChatMessage{"owncast-server", config.Config.InstanceDetails.Name, initialChatMessageText, config.Config.InstanceDetails.Logo.Small, "initial-message-1", "CHAT", true, time.Now()}
|
||||
initialMessage := models.ChatMessage{"owncast-server", config.Config.InstanceDetails.Name, initialChatMessageText, "initial-message-1", "CHAT", true, time.Now()}
|
||||
c.Write(initialMessage)
|
||||
}()
|
||||
|
||||
|
@ -18,7 +18,6 @@ type ChatMessage struct {
|
||||
|
||||
Author string `json:"author"`
|
||||
Body string `json:"body"`
|
||||
Image string `json:"image"`
|
||||
ID string `json:"id"`
|
||||
MessageType string `json:"type"`
|
||||
Visible bool `json:"visible"`
|
||||
|
@ -311,9 +311,6 @@ paths:
|
||||
body:
|
||||
type: string
|
||||
description: Escaped HTML of the chat message content.
|
||||
image:
|
||||
type: string
|
||||
description: URL of the chat user avatar.
|
||||
id:
|
||||
type: string
|
||||
description: Unique ID of the chat message.
|
||||
|
@ -4,8 +4,8 @@ const html = htm.bind(h);
|
||||
|
||||
import Chat from './components/chat/chat.js';
|
||||
import Websocket from './utils/websocket.js';
|
||||
import { getLocalStorage, generateAvatar, generateUsername } from './utils/helpers.js';
|
||||
import { KEY_USERNAME, KEY_AVATAR } from './utils/constants.js';
|
||||
import { getLocalStorage, generateUsername } from './utils/helpers.js';
|
||||
import { KEY_USERNAME } from './utils/constants.js';
|
||||
|
||||
export default class StandaloneChat extends Component {
|
||||
constructor(props, context) {
|
||||
@ -15,28 +15,25 @@ export default class StandaloneChat extends Component {
|
||||
websocket: new Websocket(),
|
||||
chatEnabled: true, // always true for standalone chat
|
||||
username: getLocalStorage(KEY_USERNAME) || generateUsername(),
|
||||
userAvatarImage: getLocalStorage(KEY_AVATAR) || generateAvatar(`${this.username}${Date.now()}`),
|
||||
};
|
||||
|
||||
this.websocket = null;
|
||||
this.handleUsernameChange = this.handleUsernameChange.bind(this);
|
||||
}
|
||||
|
||||
handleUsernameChange(newName, newAvatar) {
|
||||
handleUsernameChange(newName) {
|
||||
this.setState({
|
||||
username: newName,
|
||||
userAvatarImage: newAvatar,
|
||||
});
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
const { username, userAvatarImage, websocket } = state;
|
||||
const { username, websocket } = state;
|
||||
return (
|
||||
html`
|
||||
<${Chat}
|
||||
websocket=${websocket}
|
||||
username=${username}
|
||||
userAvatarImage=${userAvatarImage}
|
||||
messagesOnly
|
||||
/>
|
||||
`
|
||||
|
@ -14,7 +14,6 @@ import {
|
||||
classNames,
|
||||
clearLocalStorage,
|
||||
debounce,
|
||||
generateAvatar,
|
||||
generateUsername,
|
||||
getLocalStorage,
|
||||
pluralize,
|
||||
@ -22,7 +21,6 @@ import {
|
||||
} from './utils/helpers.js';
|
||||
import {
|
||||
HEIGHT_SHORT_WIDE,
|
||||
KEY_AVATAR,
|
||||
KEY_CHAT_DISPLAYED,
|
||||
KEY_USERNAME,
|
||||
MESSAGE_OFFLINE,
|
||||
@ -50,9 +48,6 @@ export default class App extends Component {
|
||||
displayChat: chatStorage === null ? true : chatStorage,
|
||||
chatInputEnabled: false, // chat input box state
|
||||
username: getLocalStorage(KEY_USERNAME) || generateUsername(),
|
||||
userAvatarImage:
|
||||
getLocalStorage(KEY_AVATAR) ||
|
||||
generateAvatar(`${this.username}${Date.now()}`),
|
||||
|
||||
configData: {},
|
||||
extraPageContent: '',
|
||||
@ -282,10 +277,9 @@ export default class App extends Component {
|
||||
|
||||
}
|
||||
|
||||
handleUsernameChange(newName, newAvatar) {
|
||||
handleUsernameChange(newName) {
|
||||
this.setState({
|
||||
username: newName,
|
||||
userAvatarImage: newAvatar,
|
||||
});
|
||||
}
|
||||
|
||||
@ -330,7 +324,6 @@ export default class App extends Component {
|
||||
playerActive,
|
||||
streamOnline,
|
||||
streamStatusMessage,
|
||||
userAvatarImage,
|
||||
username,
|
||||
viewerCount,
|
||||
websocket,
|
||||
@ -415,7 +408,6 @@ export default class App extends Component {
|
||||
>
|
||||
<${UsernameForm}
|
||||
username=${username}
|
||||
userAvatarImage=${userAvatarImage}
|
||||
handleUsernameChange=${this.handleUsernameChange}
|
||||
/>
|
||||
<button
|
||||
@ -499,7 +491,6 @@ export default class App extends Component {
|
||||
<${Chat}
|
||||
websocket=${websocket}
|
||||
username=${username}
|
||||
userAvatarImage=${userAvatarImage}
|
||||
chatInputEnabled=${chatInputEnabled}
|
||||
/>
|
||||
</div>
|
||||
|
@ -43,14 +43,14 @@ export default class Chat extends Component {
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { username: prevName } = prevProps;
|
||||
const { username, userAvatarImage } = this.props;
|
||||
const { username } = this.props;
|
||||
|
||||
const { messages: prevMessages } = prevState;
|
||||
const { messages } = this.state;
|
||||
|
||||
// if username updated, send a message
|
||||
if (prevName !== username) {
|
||||
this.sendUsernameChange(prevName, username, userAvatarImage);
|
||||
this.sendUsernameChange(prevName, username);
|
||||
}
|
||||
// scroll to bottom of messages list when new ones come in
|
||||
if (messages.length > prevMessages.length) {
|
||||
@ -94,12 +94,11 @@ export default class Chat extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
sendUsernameChange(oldName, newName, image) {
|
||||
sendUsernameChange(oldName, newName) {
|
||||
const nameChange = {
|
||||
type: SOCKET_MESSAGE_TYPES.NAME_CHANGE,
|
||||
oldName,
|
||||
newName,
|
||||
image,
|
||||
};
|
||||
this.websocket.send(nameChange);
|
||||
}
|
||||
@ -145,11 +144,10 @@ export default class Chat extends Component {
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
const { username, userAvatarImage } = this.props;
|
||||
const { username } = this.props;
|
||||
const message = {
|
||||
body: content,
|
||||
author: username,
|
||||
image: userAvatarImage,
|
||||
type: SOCKET_MESSAGE_TYPES.CHAT,
|
||||
};
|
||||
this.websocket.send(message);
|
||||
|
@ -3,7 +3,6 @@ import htm from '/js/web_modules/htm.js';
|
||||
const html = htm.bind(h);
|
||||
|
||||
import { messageBubbleColorForString } from '../../utils/user-colors.js';
|
||||
import { generateAvatar } from '../../utils/helpers.js';
|
||||
import { convertToText } from '../../utils/chat.js';
|
||||
import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js';
|
||||
|
||||
@ -12,23 +11,15 @@ export default class Message extends Component {
|
||||
const { message, username } = props;
|
||||
const { type } = message;
|
||||
if (type === SOCKET_MESSAGE_TYPES.CHAT) {
|
||||
const { image, author, body, timestamp } = message;
|
||||
const { author, body, timestamp } = message;
|
||||
const formattedMessage = formatMessageText(body, username);
|
||||
const avatar = image || generateAvatar(author);
|
||||
const formattedTimestamp = formatTimestamp(timestamp);
|
||||
|
||||
const authorColor = messageBubbleColorForString(author);
|
||||
const avatarBgColor = { backgroundColor: authorColor };
|
||||
const authorTextColor = { color: authorColor };
|
||||
return (
|
||||
html`
|
||||
<div class="message flex flex-row items-start p-3">
|
||||
<div
|
||||
class="message-avatar rounded-full flex items-center justify-center mr-3"
|
||||
style=${avatarBgColor}
|
||||
>
|
||||
<img src=${avatar} class="p-1" />
|
||||
</div>
|
||||
<div class="message-content text-sm break-words w-full">
|
||||
<div class="message-author text-white font-bold" style=${authorTextColor}>
|
||||
${author}
|
||||
@ -44,17 +35,11 @@ export default class Message extends Component {
|
||||
</div>
|
||||
`);
|
||||
} else if (type === SOCKET_MESSAGE_TYPES.NAME_CHANGE) {
|
||||
const { oldName, newName, image } = message;
|
||||
const { oldName, newName } = message;
|
||||
return (
|
||||
html`
|
||||
<div class="message message-name-change flex items-center justify-start p-3">
|
||||
<div class="message-content flex flex-row items-center justify-center text-sm w-full">
|
||||
<div
|
||||
class="message-avatar rounded-full mr-3 bg-gray-900"
|
||||
>
|
||||
<img class="mr-2 p-1" src=${image} />
|
||||
</div>
|
||||
|
||||
<div class="text-white text-center opacity-50">
|
||||
<span class="font-bold">${oldName}</span> is now known as <span class="font-bold">${newName}</span>.
|
||||
</div>
|
||||
|
@ -2,8 +2,8 @@ import { h, Component, createRef } from '/js/web_modules/preact.js';
|
||||
import htm from '/js/web_modules/htm.js';
|
||||
const html = htm.bind(h);
|
||||
|
||||
import { generateAvatar, setLocalStorage } from '../../utils/helpers.js';
|
||||
import { KEY_USERNAME, KEY_AVATAR } from '../../utils/constants.js';
|
||||
import { setLocalStorage } from '../../utils/helpers.js';
|
||||
import { KEY_USERNAME } from '../../utils/constants.js';
|
||||
|
||||
export default class UsernameForm extends Component {
|
||||
constructor(props, context) {
|
||||
@ -47,11 +47,9 @@ export default class UsernameForm extends Component {
|
||||
let newName = this.textInput.current.value;
|
||||
newName = newName.trim();
|
||||
if (newName !== '' && newName !== curName) {
|
||||
const newAvatar = generateAvatar(`${newName}${Date.now()}`);
|
||||
setLocalStorage(KEY_USERNAME, newName);
|
||||
setLocalStorage(KEY_AVATAR, newAvatar);
|
||||
if (handleUsernameChange) {
|
||||
handleUsernameChange(newName, newAvatar);
|
||||
handleUsernameChange(newName);
|
||||
}
|
||||
this.handleHideForm();
|
||||
}
|
||||
@ -59,7 +57,7 @@ export default class UsernameForm extends Component {
|
||||
}
|
||||
|
||||
render(props, state) {
|
||||
const { username, userAvatarImage } = props;
|
||||
const { username } = props;
|
||||
const { displayForm } = state;
|
||||
|
||||
const narrowSpace = document.body.clientWidth < 640;
|
||||
@ -77,12 +75,6 @@ export default class UsernameForm extends Component {
|
||||
html`
|
||||
<div id="user-info">
|
||||
<div id="user-info-display" style=${styles.info} title="Click to update user name" class="flex flex-row justify-end items-center cursor-pointer py-2 px-4 overflow-hidden w-full opacity-1 transition-opacity duration-200 hover:opacity-75" onClick=${this.handleDisplayForm}>
|
||||
<img
|
||||
src=${userAvatarImage}
|
||||
alt=""
|
||||
id="username-avatar"
|
||||
class="rounded-full bg-black bg-opacity-50 border border-solid border-gray-700 mr-2 h-8 w-8"
|
||||
/>
|
||||
<span id="username-display" class="text-indigo-600 text-xs font-semibold truncate overflow-hidden whitespace-no-wrap">${username}</span>
|
||||
</div>
|
||||
|
||||
|
@ -22,7 +22,6 @@ export const PLAYER_VOLUME = 'owncast_volume';
|
||||
|
||||
|
||||
export const KEY_USERNAME = 'owncast_username';
|
||||
export const KEY_AVATAR = 'owncast_avatar';
|
||||
export const KEY_CHAT_DISPLAYED = 'owncast_chat';
|
||||
export const KEY_CHAT_FIRST_MESSAGE_SENT = 'owncast_first_message_sent';
|
||||
export const CHAT_INITIAL_PLACEHOLDER_TEXT = 'Type here to chat, no account necessary.';
|
||||
|
@ -92,16 +92,6 @@ export function getOrientation(forTouch = false) {
|
||||
}
|
||||
}
|
||||
|
||||
// generate random avatar from https://robohash.org
|
||||
export function generateAvatar(hash) {
|
||||
const avatarSource = 'https://robohash.org/';
|
||||
const optionSize = '?size=80x80';
|
||||
const optionSet = '&set=set2';
|
||||
const optionBg = ''; // or &bgset=bg1 or bg2
|
||||
|
||||
return avatarSource + hash + optionSize + optionSet + optionBg;
|
||||
}
|
||||
|
||||
export function generateUsername() {
|
||||
return `User ${(Math.floor(Math.random() * 42) + 1)}`;
|
||||
}
|
||||
|
@ -115,22 +115,6 @@
|
||||
scrollbar-color: var(--category-button-color) black;
|
||||
}
|
||||
|
||||
|
||||
/******************************/
|
||||
|
||||
.message-avatar {
|
||||
height: 3.0em;
|
||||
width: 3.0em;
|
||||
}
|
||||
.message-avatar img {
|
||||
max-width: unset;
|
||||
height: 3.0em;
|
||||
width: 3.0em;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* MESSAGE TEXT HTML */
|
||||
/* MESSAGE TEXT HTML */
|
||||
/* MESSAGE TEXT HTML */
|
||||
|
@ -28,14 +28,6 @@ The styles in this file mostly ovveride those coming from chat.css
|
||||
#messages-only .message-content {
|
||||
text-shadow: 1px 1px 0px rgba(0,0,0,0.25);
|
||||
}
|
||||
#messages-only .message-avatar {
|
||||
display: none;
|
||||
box-shadow: 0px 0px 3px 0px rgba(0,0,0,0.25);
|
||||
}
|
||||
#messages-only .message-avatar img {
|
||||
height: 1.8em;
|
||||
width: 1.8em;
|
||||
}
|
||||
#messages-only .message {
|
||||
padding: .5em;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user