feat: add support for markdown in offline message. Closes #2921 (#2977)

This commit is contained in:
Gabe Kangas 2023-05-01 19:45:27 -07:00 committed by GitHub
parent 295e7768a0
commit 7aca27cb08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 13 deletions

View File

@ -72,6 +72,7 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) {
func getConfigResponse() webConfigResponse {
pageContent := utils.RenderPageContentMarkdown(data.GetExtraPageBodyContent())
offlineMessage := utils.RenderSimpleMarkdown(data.GetCustomOfflineMessage())
socialHandles := data.GetSocialHandles()
for i, handle := range socialHandles {
platform := models.GetSocialHandle(handle.Platform)
@ -119,7 +120,7 @@ func getConfigResponse() webConfigResponse {
return webConfigResponse{
Name: data.GetServerName(),
Summary: serverSummary,
OfflineMessage: data.GetCustomOfflineMessage(),
OfflineMessage: offlineMessage,
Logo: "/logo",
Tags: data.GetServerMetadataTags(),
Version: config.GetReleaseString(),

View File

@ -371,11 +371,12 @@ test('set override websocket host', async (done) => {
test('verify updated config values', async (done) => {
const res = await request.get('/api/config');
expect(res.body.name).toBe(newServerName);
expect(res.body.streamTitle).toBe(newStreamTitle);
expect(res.body.summary).toBe(`${newServerSummary}`);
expect(res.body.extraPageContent).toBe(newPageContent);
expect(res.body.offlineMessage).toBe(newOfflineMessage);
expect(res.body.offlineMessage).toBe(`<p>${newOfflineMessage}</p>`);
expect(res.body.logo).toBe('/logo');
expect(res.body.socialHandles).toStrictEqual(newSocialHandles);
expect(res.body.socketHostOverride).toBe(overriddenWebsocketHost);

View File

@ -145,7 +145,7 @@ func RenderSimpleMarkdown(raw string) string {
log.Fatalln(err)
}
return buf.String()
return strings.TrimSpace(buf.String())
}
// RenderPageContentMarkdown will return HTML specifically handled for the user-specified page content.

View File

@ -1,5 +1,9 @@
import React, { useState, useContext, useEffect } from 'react';
import { Typography } from 'antd';
import { Button, Typography } from 'antd';
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
import CodeMirror from '@uiw/react-codemirror';
import { bbedit } from '@uiw/codemirror-theme-bbedit';
import { languages } from '@codemirror/language-data';
import {
TextFieldWithSubmit,
TEXTFIELD_TYPE_TEXTAREA,
@ -16,10 +20,13 @@ import {
FIELD_PROPS_YP,
FIELD_PROPS_NSFW,
FIELD_PROPS_HIDE_VIEWER_COUNT,
API_SERVER_OFFLINE_MESSAGE,
} from '../../../../utils/config-constants';
import { UpdateArgs } from '../../../../types/config-section';
import { ToggleSwitch } from '../../ToggleSwitch';
import { EditLogo } from '../../EditLogo';
import FormStatusIndicator from '../../FormStatusIndicator';
import { createInputStatus, STATUS_SUCCESS } from '../../../../utils/input-statuses';
const { Title } = Typography;
@ -32,6 +39,8 @@ export default function EditInstanceDetails() {
const { instanceDetails, yp, hideViewerCount } = serverConfig;
const { instanceUrl } = yp;
const [offlineMessageSaveStatus, setOfflineMessageSaveStatus] = useState(null);
useEffect(() => {
setFormDataValues({
...instanceDetails,
@ -56,6 +65,17 @@ export default function EditInstanceDetails() {
}
};
const handleSaveOfflineMessage = () => {
postConfigUpdateToAPI({
apiPath: API_SERVER_OFFLINE_MESSAGE,
data: { value: formDataValues.offlineMessage },
});
setOfflineMessageSaveStatus(createInputStatus(STATUS_SUCCESS));
setTimeout(() => {
setOfflineMessageSaveStatus(null);
}, 2000);
};
const handleFieldChange = ({ fieldName, value }: UpdateArgs) => {
setFormDataValues({
...formDataValues,
@ -103,14 +123,42 @@ export default function EditInstanceDetails() {
onChange={handleFieldChange}
/>
<TextFieldWithSubmit
fieldName="offlineMessage"
{...TEXTFIELD_PROPS_SERVER_OFFLINE_MESSAGE}
type={TEXTFIELD_TYPE_TEXTAREA}
value={formDataValues.offlineMessage}
initialValue={instanceDetails.offlineMessage}
onChange={handleFieldChange}
/>
<div style={{ marginBottom: '50px', marginRight: '150px' }}>
<div
style={{
display: 'flex',
width: '80vh',
justifyContent: 'space-between',
alignItems: 'end',
}}
>
<p style={{ margin: '20px', marginRight: '10px', fontWeight: '400' }}>Offline Message:</p>
<CodeMirror
value={formDataValues.offlineMessage}
{...TEXTFIELD_PROPS_SERVER_OFFLINE_MESSAGE}
theme={bbedit}
height="150px"
width="450px"
onChange={value => {
handleFieldChange({ fieldName: 'offlineMessage', value });
}}
extensions={[markdown({ base: markdownLanguage, codeLanguages: languages })]}
/>
</div>
<div className="field-tip">
The offline message is displayed to your page visitors when you&apos;re not streaming.
Markdown is supported.
</div>
<Button
type="primary"
onClick={handleSaveOfflineMessage}
style={{ margin: '10px', float: 'right' }}
>
Save Message
</Button>
<FormStatusIndicator status={offlineMessageSaveStatus} />
</div>
{/* Logo section */}
<EditLogo />

View File

@ -1,3 +1,4 @@
/* eslint-disable react/no-danger */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import { Divider } from 'antd';
import { FC } from 'react';
@ -85,7 +86,12 @@ export const OfflineBanner: FC<OfflineBannerProps> = ({
<Divider className={styles.separator} />
</>
)}
<div className={styles.bodyText}>{text}</div>
{customText ? (
<div className={styles.bodyText} dangerouslySetInnerHTML={{ __html: text }} />
) : (
<div className={styles.bodyText}>{text}</div>
)}
{lastLive && (
<div className={styles.lastLiveDate}>
<ClockCircleOutlined className={styles.clockIcon} />