Add option to hide viewer count. Closes #1939
This commit is contained in:
parent
97db93e0d7
commit
b08393295f
@ -711,6 +711,26 @@ func SetChatJoinMessagesEnabled(w http.ResponseWriter, r *http.Request) {
|
||||
controllers.WriteSimpleResponse(w, true, "chat join message status updated")
|
||||
}
|
||||
|
||||
// SetHideViewerCount will enable or disable hiding the viewer count.
|
||||
func SetHideViewerCount(w http.ResponseWriter, r *http.Request) {
|
||||
if !requirePOST(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
configValue, success := getValueFromRequest(w, r)
|
||||
if !success {
|
||||
controllers.WriteSimpleResponse(w, false, "unable to update hiding viewer count")
|
||||
return
|
||||
}
|
||||
|
||||
if err := data.SetHideViewerCount(configValue.Value.(bool)); err != nil {
|
||||
controllers.WriteSimpleResponse(w, false, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
controllers.WriteSimpleResponse(w, true, "hide viewer count setting updated")
|
||||
}
|
||||
|
||||
func requirePOST(w http.ResponseWriter, r *http.Request) bool {
|
||||
if r.Method != controllers.POST {
|
||||
controllers.WriteSimpleResponse(w, false, r.Method+" not supported")
|
||||
|
@ -55,6 +55,7 @@ func GetServerConfig(w http.ResponseWriter, r *http.Request) {
|
||||
ChatJoinMessagesEnabled: data.GetChatJoinMessagesEnabled(),
|
||||
SocketHostOverride: data.GetWebsocketOverrideHost(),
|
||||
ChatEstablishedUserMode: data.GetChatEstbalishedUsersOnlyMode(),
|
||||
HideViewerCount: data.GetHideViewerCount(),
|
||||
VideoSettings: videoSettings{
|
||||
VideoQualityVariants: videoQualityVariants,
|
||||
LatencyLevel: data.GetStreamLatencyLevel().Level,
|
||||
@ -113,6 +114,7 @@ type serverConfigAdminResponse struct {
|
||||
SuggestedUsernames []string `json:"suggestedUsernames"`
|
||||
SocketHostOverride string `json:"socketHostOverride,omitempty"`
|
||||
Notifications notificationsConfigResponse `json:"notifications"`
|
||||
HideViewerCount bool `json:"hideViewerCount"`
|
||||
}
|
||||
|
||||
type videoSettings struct {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/owncast/owncast/core"
|
||||
"github.com/owncast/owncast/core/data"
|
||||
"github.com/owncast/owncast/router/middleware"
|
||||
"github.com/owncast/owncast/utils"
|
||||
)
|
||||
@ -15,7 +16,6 @@ func GetStatus(w http.ResponseWriter, r *http.Request) {
|
||||
status := core.GetStatus()
|
||||
response := webStatusResponse{
|
||||
Online: status.Online,
|
||||
ViewerCount: status.ViewerCount,
|
||||
ServerTime: time.Now(),
|
||||
LastConnectTime: status.LastConnectTime,
|
||||
LastDisconnectTime: status.LastDisconnectTime,
|
||||
@ -23,6 +23,10 @@ func GetStatus(w http.ResponseWriter, r *http.Request) {
|
||||
StreamTitle: status.StreamTitle,
|
||||
}
|
||||
|
||||
if !data.GetHideViewerCount() {
|
||||
response.ViewerCount = status.ViewerCount
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
middleware.DisableCache(w)
|
||||
|
||||
@ -33,7 +37,7 @@ func GetStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
type webStatusResponse struct {
|
||||
Online bool `json:"online"`
|
||||
ViewerCount int `json:"viewerCount"`
|
||||
ViewerCount int `json:"viewerCount,omitempty"`
|
||||
ServerTime time.Time `json:"serverTime"`
|
||||
LastConnectTime *utils.NullTime `json:"lastConnectTime"`
|
||||
LastDisconnectTime *utils.NullTime `json:"lastDisconnectTime"`
|
||||
|
@ -65,6 +65,7 @@ const (
|
||||
browserPushPrivateKeyKey = "browser_push_private_key"
|
||||
twitterConfigurationKey = "twitter_configuration"
|
||||
hasConfiguredInitialNotificationsKey = "has_configured_initial_notifications"
|
||||
hideViewerCountKey = "hide_viewer_count"
|
||||
)
|
||||
|
||||
// GetExtraPageBodyContent will return the user-supplied body content.
|
||||
@ -908,3 +909,14 @@ func GetHasPerformedInitialNotificationsConfig() bool {
|
||||
configured, _ := _datastore.GetBool(hasConfiguredInitialNotificationsKey)
|
||||
return configured
|
||||
}
|
||||
|
||||
// GetHideViewerCount will return if the viewer count shold be hidden.
|
||||
func GetHideViewerCount() bool {
|
||||
hide, _ := _datastore.GetBool(hideViewerCountKey)
|
||||
return hide
|
||||
}
|
||||
|
||||
// SetHideViewerCount will set if the viewer count should be hidden.
|
||||
func SetHideViewerCount(hide bool) error {
|
||||
return _datastore.SetBool(hideViewerCountKey, hide)
|
||||
}
|
||||
|
@ -312,6 +312,9 @@ func Start() error {
|
||||
// Video playback metrics
|
||||
http.HandleFunc("/api/admin/metrics/video", middleware.RequireAdminAuth(admin.GetVideoPlaybackMetrics))
|
||||
|
||||
// Is the viewer count hidden from viewers
|
||||
http.HandleFunc("/api/admin/config/hideviewercount", middleware.RequireAdminAuth(admin.SetHideViewerCount))
|
||||
|
||||
// Inline chat moderation actions
|
||||
|
||||
// Update chat message visibility
|
||||
|
@ -85,7 +85,15 @@ test('set s3 configuration', async (done) => {
|
||||
});
|
||||
|
||||
test('set forbidden usernames', async (done) => {
|
||||
const res = await sendConfigChangeRequest('chat/forbiddenusernames', forbiddenUsernames);
|
||||
const res = await sendConfigChangeRequest(
|
||||
'chat/forbiddenusernames',
|
||||
forbiddenUsernames
|
||||
);
|
||||
done();
|
||||
});
|
||||
|
||||
test('set hide viewer count', async (done) => {
|
||||
const res = await sendConfigChangeRequest('hideviewercount', true);
|
||||
done();
|
||||
});
|
||||
|
||||
@ -101,7 +109,7 @@ test('verify updated config values', async (done) => {
|
||||
});
|
||||
|
||||
// Test that the raw video details being broadcasted are coming through
|
||||
test('stream details are correct', (done) => {
|
||||
test('admin stream details are correct', (done) => {
|
||||
request
|
||||
.get('/api/admin/status')
|
||||
.auth('admin', 'abc123')
|
||||
@ -149,7 +157,8 @@ test('admin configuration is correct', (done) => {
|
||||
expect(res.body.s3.secret).toBe(s3Config.secret);
|
||||
expect(res.body.s3.bucket).toBe(s3Config.bucket);
|
||||
expect(res.body.s3.region).toBe(s3Config.region);
|
||||
expect(res.body.s3.forcePathStyle).toBeTruthy();
|
||||
expect(res.body.s3.forcePathStyle).toBe(true);
|
||||
expect(res.body.hideViewerCount).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -166,6 +175,16 @@ test('frontend configuration is correct', (done) => {
|
||||
});
|
||||
});
|
||||
|
||||
test('frontend status is correct', (done) => {
|
||||
request
|
||||
.get('/api/status')
|
||||
.expect(200)
|
||||
.then((res) => {
|
||||
expect(res.body.viewerCount).toBe(undefined);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
async function sendConfigChangeRequest(endpoint, value) {
|
||||
const url = '/api/admin/config/' + endpoint;
|
||||
const res = await request
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
API_YP_SWITCH,
|
||||
FIELD_PROPS_YP,
|
||||
FIELD_PROPS_NSFW,
|
||||
FIELD_PROPS_HIDE_VIEWER_COUNT,
|
||||
} from '../../utils/config-constants';
|
||||
|
||||
import { UpdateArgs } from '../../types/config-section';
|
||||
@ -61,6 +62,10 @@ export default function EditInstanceDetails() {
|
||||
});
|
||||
};
|
||||
|
||||
function handleHideViewerCountChange(enabled: boolean) {
|
||||
handleFieldChange({ fieldName: 'hideViewerCount', value: enabled });
|
||||
}
|
||||
|
||||
const hasInstanceUrl = instanceUrl !== '';
|
||||
|
||||
return (
|
||||
@ -100,6 +105,14 @@ export default function EditInstanceDetails() {
|
||||
{/* Logo section */}
|
||||
<EditLogo />
|
||||
|
||||
<ToggleSwitch
|
||||
fieldName="hideViewerCount"
|
||||
useSubmit
|
||||
{...FIELD_PROPS_HIDE_VIEWER_COUNT}
|
||||
checked={formDataValues.hideViewerCount}
|
||||
onChange={handleHideViewerCountChange}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<p className="description">
|
||||
Increase your audience by appearing in the{' '}
|
||||
|
@ -40,12 +40,12 @@ export default function Statusbar(props: Props) {
|
||||
if (online && lastConnectTime) {
|
||||
const duration = makeDurationString(new Date(lastConnectTime));
|
||||
onlineMessage = online ? `Live for ${duration}` : 'Offline';
|
||||
rightSideMessage = (
|
||||
rightSideMessage = viewerCount > 0 && (
|
||||
<span>
|
||||
<EyeOutlined /> {viewerCount}
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
} else if (!online) {
|
||||
onlineMessage = 'Offline';
|
||||
if (lastDisconnectTime) {
|
||||
rightSideMessage = `Last live ${formatDistanceToNow(new Date(lastDisconnectTime))} ago.`;
|
||||
|
@ -152,4 +152,5 @@ export interface ConfigDetails {
|
||||
notifications: NotificationsConfig;
|
||||
chatJoinMessagesEnabled: boolean;
|
||||
chatEstablishedUserMode: boolean;
|
||||
hideViewerCount: boolean;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ export const API_VIDEO_SEGMENTS = '/video/streamlatencylevel';
|
||||
export const API_VIDEO_VARIANTS = '/video/streamoutputvariants';
|
||||
export const API_WEB_PORT = '/webserverport';
|
||||
export const API_YP_SWITCH = '/directoryenabled';
|
||||
export const API_HIDE_VIEWER_COUNT = '/hideviewercount';
|
||||
export const API_CHAT_DISABLE = '/chat/disable';
|
||||
export const API_CHAT_JOIN_MESSAGES_ENABLED = '/chat/joinmessagesenabled';
|
||||
export const API_CHAT_ESTABLISHED_MODE = '/chat/establishedusermode';
|
||||
@ -188,6 +189,13 @@ export const FIELD_PROPS_YP = {
|
||||
tip: 'Turn this ON to request to show up in the directory.',
|
||||
};
|
||||
|
||||
export const FIELD_PROPS_HIDE_VIEWER_COUNT = {
|
||||
apiPath: API_HIDE_VIEWER_COUNT,
|
||||
configPath: '',
|
||||
label: 'Hide viewer count',
|
||||
tip: 'Turn this ON to hide the viewer count the web page.',
|
||||
};
|
||||
|
||||
export const DEFAULT_VARIANT_STATE: VideoVariant = {
|
||||
framerate: 24,
|
||||
videoPassthrough: false,
|
||||
|
@ -75,6 +75,7 @@ export const initialServerConfigState: ConfigDetails = {
|
||||
chatDisabled: false,
|
||||
chatJoinMessagesEnabled: true,
|
||||
chatEstablishedUserMode: false,
|
||||
hideViewerCount: false,
|
||||
};
|
||||
|
||||
const initialServerStatusState = {
|
||||
@ -156,6 +157,7 @@ const ServerStatusProvider = ({ children }) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// eslint-disable-next-line react/jsx-no-constructed-context-values
|
||||
const providerValue = {
|
||||
...status,
|
||||
serverConfig: config,
|
||||
|
Loading…
x
Reference in New Issue
Block a user