mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
address MR comments
This commit is contained in:
parent
6457015406
commit
b399fbba22
@ -8,22 +8,17 @@
|
|||||||
<link href="./styles/standalone-chat.css" rel="stylesheet" />
|
<link href="./styles/standalone-chat.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script src="//unpkg.com/showdown/dist/showdown.min.js"></script>
|
<script src="//unpkg.com/showdown/dist/showdown.min.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="messages-only"></div>
|
<div id="messages-only"></div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { render, h } from 'https://unpkg.com/preact?module';
|
import { render, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
|
||||||
const html = htm.bind(h);
|
|
||||||
import StandaloneChat from './js/app-standalone-chat.js';
|
import StandaloneChat from './js/app-standalone-chat.js';
|
||||||
|
render(
|
||||||
(function () {
|
html`<${StandaloneChat} messagesOnly />`, document.getElementById("messages-only")
|
||||||
render(html`<${StandaloneChat} messagesOnly />`, document.getElementById("messages-only"));
|
);
|
||||||
})();
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -20,15 +20,9 @@
|
|||||||
<div id="video-only"></div>
|
<div id="video-only"></div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { h, render } from 'https://unpkg.com/preact?module';
|
import { render, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
|
||||||
const html = htm.bind(h);
|
|
||||||
|
|
||||||
import VideoOnly from './js/app-video-only.js';
|
import VideoOnly from './js/app-video-only.js';
|
||||||
|
render(html`<${VideoOnly} />`, document.getElementById("video-only"));
|
||||||
(function () {
|
|
||||||
render(html`<${VideoOnly} />`, document.getElementById("video-only"));
|
|
||||||
})();
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -28,54 +28,47 @@
|
|||||||
<script src="//unpkg.com/video.js@7.9.2/dist/video.js"></script>
|
<script src="//unpkg.com/video.js@7.9.2/dist/video.js"></script>
|
||||||
<!-- markdown renderer -->
|
<!-- markdown renderer -->
|
||||||
<script src="//unpkg.com/showdown/dist/showdown.min.js"></script>
|
<script src="//unpkg.com/showdown/dist/showdown.min.js"></script>
|
||||||
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@0.6.2/lite-youtube.js"></script>
|
||||||
|
|
||||||
|
|
||||||
<link href="./styles/video.css" rel="stylesheet" />
|
<link href="./styles/video.css" rel="stylesheet" />
|
||||||
<link href="./styles/chat.css" rel="stylesheet" />
|
<link href="./styles/chat.css" rel="stylesheet" />
|
||||||
<link href="./styles/user-content.css" rel="stylesheet" />
|
<link href="./styles/user-content.css" rel="stylesheet" />
|
||||||
<link href="./styles/app.css" rel="stylesheet" />
|
<link href="./styles/app.css" rel="stylesheet" />
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
<body class="bg-gray-300 text-gray-800">
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
<body class="bg-gray-300 text-gray-800">
|
import { render, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
|
||||||
<div id="app"></div>
|
import App from './js/app.js';
|
||||||
|
|
||||||
<script type="module">
|
|
||||||
import { render, h } from 'https://unpkg.com/preact?module';
|
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
|
||||||
const html = htm.bind(h);
|
|
||||||
import App from './js/app.js';
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
render(html`<${App} />`, document.getElementById("app"));
|
render(html`<${App} />`, document.getElementById("app"));
|
||||||
})();
|
</script>
|
||||||
</script>
|
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<style>
|
||||||
|
.noscript {
|
||||||
|
text-align: center;
|
||||||
|
padding: 30px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
<noscript>
|
.noscript a {
|
||||||
<style>
|
display: inline;
|
||||||
.noscript {
|
color: blue;
|
||||||
text-align: center;
|
text-decoration: underline;
|
||||||
padding: 30px;
|
}
|
||||||
display: flex;
|
</style>
|
||||||
justify-content: center;
|
<div class="noscript">
|
||||||
align-items: center;
|
<img src="https://owncast.online/images/logo.png" />
|
||||||
flex-direction: column;
|
<br/>
|
||||||
}
|
<p>
|
||||||
|
This <a href="https://owncast.online" target="_blank">Owncast</a> stream requires Javascript to play.
|
||||||
.noscript a {
|
</p>
|
||||||
display: inline;
|
</div>
|
||||||
color: blue;
|
</noscript>
|
||||||
text-decoration: underline;
|
</body>
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div class="noscript">
|
|
||||||
<img src="https://owncast.online/images/logo.png" />
|
|
||||||
<br/>
|
|
||||||
<p>
|
|
||||||
This <a href="https://owncast.online" target="_blank">Owncast</a> stream requires Javascript to play.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</noscript>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -29,10 +29,6 @@ export default class StandaloneChat extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChatToggle() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
render(props, state) {
|
render(props, state) {
|
||||||
const { username, userAvatarImage, websocket } = state;
|
const { username, userAvatarImage, websocket } = state;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export default class ChatInput extends Component {
|
|||||||
this.emojiPickerButton = createRef();
|
this.emojiPickerButton = createRef();
|
||||||
|
|
||||||
this.messageCharCount = 0;
|
this.messageCharCount = 0;
|
||||||
this.maxMessageLength = 500;
|
this.maxMessageLength = 500;
|
||||||
this.maxMessageBuffer = 20;
|
this.maxMessageBuffer = 20;
|
||||||
|
|
||||||
this.emojiPicker = null;
|
this.emojiPicker = null;
|
||||||
@ -98,94 +98,107 @@ export default class ChatInput extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// autocomplete user names
|
// autocomplete user names
|
||||||
autoCompleteNames() {
|
autoCompleteNames() {
|
||||||
const { chatUserNames } = this.props;
|
const { chatUserNames } = this.props;
|
||||||
const { inputHTML } = this.state;
|
const { inputHTML } = this.state;
|
||||||
const position = getCaretPosition(this.formMessageInput.current);
|
const position = getCaretPosition(this.formMessageInput.current);
|
||||||
const at = inputHTML.lastIndexOf('@', position - 1);
|
const at = inputHTML.lastIndexOf('@', position - 1);
|
||||||
if (at === -1) {
|
if (at === -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let partial = inputHTML.substring(at + 1, position).trim();
|
let partial = inputHTML.substring(at + 1, position).trim();
|
||||||
|
|
||||||
if (partial === this.suggestion) {
|
if (partial === this.suggestion) {
|
||||||
partial = this.partial;
|
partial = this.partial;
|
||||||
} else {
|
} else {
|
||||||
this.partial = partial;
|
this.partial = partial;
|
||||||
}
|
}
|
||||||
|
|
||||||
const possibilities = chatUserNames.filter(function (username) {
|
const possibilities = chatUserNames.filter(function (username) {
|
||||||
return username.toLowerCase().startsWith(partial.toLowerCase());
|
return username.toLowerCase().startsWith(partial.toLowerCase());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.completionIndex === undefined || ++this.completionIndex >= possibilities.length) {
|
if (this.completionIndex === undefined || ++this.completionIndex >= possibilities.length) {
|
||||||
this.completionIndex = 0;
|
this.completionIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (possibilities.length > 0) {
|
if (possibilities.length > 0) {
|
||||||
this.suggestion = possibilities[this.completionIndex];
|
this.suggestion = possibilities[this.completionIndex];
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
inputHTML: inputHTML.substring(0, at + 1) + this.suggestion + ' ' + inputHTML.substring(position),
|
inputHTML: inputHTML.substring(0, at + 1) + this.suggestion + ' ' + inputHTML.substring(position),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMessageInputKeydown(event) {
|
handleMessageInputKeydown(event) {
|
||||||
const okCodes = [37,38,39,40,16,91,18,46,8];
|
const okCodes = [
|
||||||
|
'ArrowLeft',
|
||||||
|
'ArrowUp',
|
||||||
|
'ArrowRight',
|
||||||
|
'ArrowDown',
|
||||||
|
'Shift',
|
||||||
|
'Meta',
|
||||||
|
'Alt',
|
||||||
|
'Delete',
|
||||||
|
'Backspace',
|
||||||
|
];
|
||||||
|
// const okCodes = [37,38,39,40,16,91,18,46,8];//left, up , right , down , shift, left window key, alt, delete, backspace
|
||||||
const formField = this.formMessageInput.current;
|
const formField = this.formMessageInput.current;
|
||||||
|
|
||||||
let textValue = formField.innerText.trim(); // get this only to count chars
|
let textValue = formField.innerText.trim(); // get this only to count chars
|
||||||
|
|
||||||
let numCharsLeft = this.maxMessageLength - textValue.length;
|
let numCharsLeft = this.maxMessageLength - textValue.length;
|
||||||
if (event.keyCode === 13) { // enter
|
const key = event.key;
|
||||||
if (!this.prepNewLine) {
|
|
||||||
this.sendMessage();
|
|
||||||
event.preventDefault();
|
|
||||||
this.prepNewLine = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (event.keyCode === 16 || event.keyCode === 17) { // ctrl, shift
|
|
||||||
this.prepNewLine = true;
|
|
||||||
}
|
|
||||||
if (event.keyCode === 9) { // tab
|
|
||||||
if (this.autoCompleteNames()) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// value could have been changed, update char count
|
if (key === 'Enter') {
|
||||||
textValue = formField.innerText.trim();
|
if (!this.prepNewLine) {
|
||||||
numCharsLeft = this.maxMessageLength - textValue.length;
|
this.sendMessage();
|
||||||
}
|
event.preventDefault();
|
||||||
}
|
this.prepNewLine = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key === 'Control' || key === 'Shift') {
|
||||||
|
this.prepNewLine = true;
|
||||||
|
}
|
||||||
|
if (key === 'Tab') {
|
||||||
|
if (this.autoCompleteNames()) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// value could have been changed, update char count
|
||||||
|
textValue = formField.innerText.trim();
|
||||||
|
numCharsLeft = this.maxMessageLength - textValue.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// text count
|
// text count
|
||||||
if (numCharsLeft <= this.maxMessageBuffer) {
|
if (numCharsLeft <= this.maxMessageBuffer) {
|
||||||
this.setState({
|
this.setState({
|
||||||
inputWarning: `${numCharsLeft} chars left`,
|
inputWarning: `${numCharsLeft} chars left`,
|
||||||
});
|
});
|
||||||
if (numCharsLeft <= 0 && !okCodes.includes(event.keyCode)) {
|
if (numCharsLeft <= 0 && !okCodes.includes(key)) {
|
||||||
event.preventDefault(); // prevent typing more
|
event.preventDefault(); // prevent typing more
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
inputWarning: '',
|
inputWarning: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMessageInputKeyup(event) {
|
handleMessageInputKeyup(event) {
|
||||||
if (event.keyCode === 16 || event.keyCode === 17) { // ctrl, shift
|
if (event.key === 'Control' || event.key === 'Shift') {
|
||||||
this.prepNewLine = false;
|
this.prepNewLine = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMessageInputBlur(event) {
|
handleMessageInputBlur(event) {
|
||||||
this.prepNewLine = false;
|
this.prepNewLine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePaste(event) {
|
handlePaste(event) {
|
||||||
|
@ -95,9 +95,9 @@ export default class Chat extends Component {
|
|||||||
sendUsernameChange(oldName, newName, image) {
|
sendUsernameChange(oldName, newName, image) {
|
||||||
const nameChange = {
|
const nameChange = {
|
||||||
type: SOCKET_MESSAGE_TYPES.NAME_CHANGE,
|
type: SOCKET_MESSAGE_TYPES.NAME_CHANGE,
|
||||||
oldName: oldName,
|
oldName,
|
||||||
newName: newName,
|
newName,
|
||||||
image: image,
|
image,
|
||||||
};
|
};
|
||||||
this.websocket.send(nameChange);
|
this.websocket.send(nameChange);
|
||||||
}
|
}
|
||||||
@ -106,12 +106,14 @@ export default class Chat extends Component {
|
|||||||
this.addMessage(message);
|
this.addMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if incoming message has same id as existing message, don't add it
|
|
||||||
addMessage(message) {
|
addMessage(message) {
|
||||||
const { messages: curMessages } = this.state;
|
const { messages: curMessages } = this.state;
|
||||||
|
|
||||||
|
// if incoming message has same id as existing message, don't add it
|
||||||
const existing = curMessages.filter(function (item) {
|
const existing = curMessages.filter(function (item) {
|
||||||
return item.id === message.id;
|
return item.id === message.id;
|
||||||
})
|
})
|
||||||
|
|
||||||
if (existing.length === 0 || !existing) {
|
if (existing.length === 0 || !existing) {
|
||||||
const newState = {
|
const newState = {
|
||||||
messages: [...curMessages, message],
|
messages: [...curMessages, message],
|
||||||
|
@ -112,7 +112,10 @@ function getYoutubeIdFromURL(url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getYoutubeEmbedFromID(id) {
|
function getYoutubeEmbedFromID(id) {
|
||||||
return `<iframe class="chat-embed youtube-embed" src="//www.youtube.com/embed/${id}" frameborder="0" allowfullscreen></iframe>`;
|
return `
|
||||||
|
<div class="chat-embed youtube-embed">
|
||||||
|
<lite-youtube videoid="${id}" />
|
||||||
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInstagramEmbedFromURL(url) {
|
function getInstagramEmbedFromURL(url) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user