Prefers non-explicit and option to expressly remember closed videos

This commit is contained in:
Noah 2023-10-14 12:24:30 -07:00
parent bdb5e6359b
commit fea1d1c7b9
6 changed files with 98 additions and 16 deletions

View File

@ -40,7 +40,7 @@ VideoFlag: {
Active: 1 << 0, // or 00000001 in binary Active: 1 << 0, // or 00000001 in binary
NSFW: 1 << 1, // or 00000010 NSFW: 1 << 1, // or 00000010
Muted: 1 << 2, // or 00000100, etc. Muted: 1 << 2, // or 00000100, etc.
IsTalking: 1 << 3, NonExplicit: 1 << 3,
MutualRequired: 1 << 4, MutualRequired: 1 << 4,
MutualOpen: 1 << 5, MutualOpen: 1 << 5,
} }

View File

@ -126,7 +126,7 @@ const (
VideoFlagActive int = 1 << iota // user's camera is enabled/broadcasting VideoFlagActive int = 1 << iota // user's camera is enabled/broadcasting
VideoFlagNSFW // viewer's camera is marked as NSFW VideoFlagNSFW // viewer's camera is marked as NSFW
VideoFlagMuted // user source microphone is muted VideoFlagMuted // user source microphone is muted
VideoFlagIsTalking // broadcaster seems to be talking VideoFlagNonExplicit // viewer prefers not to see NSFW cameras (don't auto-open red cams/auto-close blue cams going red)
VideoFlagMutualRequired // video wants viewers to share their camera too VideoFlagMutualRequired // video wants viewers to share their camera too
VideoFlagMutualOpen // viewer wants to auto-open viewers' cameras VideoFlagMutualOpen // viewer wants to auto-open viewers' cameras
VideoFlagOnlyVIP // can only shows as active to VIP members VideoFlagOnlyVIP // can only shows as active to VIP members

View File

@ -162,7 +162,9 @@ export default {
nsfw: false, // user has flagged their camera to be NSFW nsfw: false, // user has flagged their camera to be NSFW
mutual: false, // user wants viewers to share their own videos mutual: false, // user wants viewers to share their own videos
mutualOpen: false, // user wants to open video mutually mutualOpen: false, // user wants to open video mutually
nonExplicit: false, // user prefers not to see explicit cameras
vipOnly: false, // only show camera to fellow VIP users vipOnly: false, // only show camera to fellow VIP users
rememberExpresslyClosed: true, // remember cams we expressly closed
// Who all is watching me? map of users. // Who all is watching me? map of users.
watching: {}, watching: {},
@ -422,6 +424,12 @@ export default {
this.sendMe(); this.sendMe();
} }
}, },
"webcam.nonExplicit": function () {
LocalStorage.set('videoNonExplicit', this.webcam.nonExplicit);
if (this.webcam.active) {
this.sendMe();
}
},
"webcam.vipOnly": function () { "webcam.vipOnly": function () {
LocalStorage.set('videoVipOnly', this.webcam.vipOnly); LocalStorage.set('videoVipOnly', this.webcam.vipOnly);
if (this.webcam.active) { if (this.webcam.active) {
@ -437,6 +445,9 @@ export default {
} }
} }
}, },
"webcam.rememberExpresslyClosed": function() {
LocalStorage.set('rememberExpresslyClosed', this.webcam.rememberExpresslyClosed);
},
// Misc preference watches // Misc preference watches
"prefs.joinMessages": function () { "prefs.joinMessages": function () {
@ -559,6 +570,7 @@ export default {
if (this.webcam.nsfw) status |= this.VideoFlag.NSFW; if (this.webcam.nsfw) status |= this.VideoFlag.NSFW;
if (this.webcam.mutual) status |= this.VideoFlag.MutualRequired; if (this.webcam.mutual) status |= this.VideoFlag.MutualRequired;
if (this.webcam.mutualOpen) status |= this.VideoFlag.MutualOpen; if (this.webcam.mutualOpen) status |= this.VideoFlag.MutualOpen;
if (this.webcam.nonExplicit) status |= this.VideoFlag.NonExplicit;
if (this.webcam.vipOnly && this.isVIP) status |= this.VideoFlag.VipOnly; if (this.webcam.vipOnly && this.isVIP) status |= this.VideoFlag.VipOnly;
return status; return status;
}, },
@ -749,6 +761,12 @@ export default {
if (settings.videoExplicit === true) { if (settings.videoExplicit === true) {
this.webcam.nsfw = true; this.webcam.nsfw = true;
} }
if (settings.videoNonExplicit === true) {
this.webcam.nonExplicit = true;
}
if (settings.rememberExpresslyClosed === false) {
this.webcam.rememberExpresslyClosed = false;
}
// Misc preferences // Misc preferences
if (settings.joinMessages != undefined) { if (settings.joinMessages != undefined) {
@ -976,6 +994,15 @@ export default {
} }
for (let row of this.whoList) { for (let row of this.whoList) {
// If we were watching this user's (blue) camera and we prefer non-Explicit,
// and their camera is now becoming explicit (red), close it now.
if (this.webcam.nonExplicit && this.WebRTC.streams[row.username] != undefined) {
if (!(this.whoMap[row.username].video & this.VideoFlag.NSFW)
&& (row.video & this.VideoFlag.NSFW)) {
this.closeVideo(row.username, "offerer");
}
}
this.whoMap[row.username] = row; this.whoMap[row.username] = row;
this.whoOnline[row.username] = true; this.whoOnline[row.username] = true;
@ -996,6 +1023,17 @@ export default {
// are already watching them. // are already watching them.
this.unMutualVideo(); this.unMutualVideo();
// If we have any webcams open with users who are no longer in the Who List
// (e.g.: can happen during a server reboot when the Who List goes empty),
// close those video connections. Note: during normal room exit events this
// is done on the onUserExited function - this is an extra safety check especially
// in case of unexpected disconnect.
for (let username of Object.keys(this.WebRTC.pc)) {
if (this.whoOnline[username] == undefined) {
this.closeVideo(username);
}
}
// Has the back-end server forgotten we are on video? This can // Has the back-end server forgotten we are on video? This can
// happen if we disconnect/reconnect while we were streaming. // happen if we disconnect/reconnect while we were streaming.
if (this.webcam.active && !(this.whoMap[this.username]?.video & this.VideoFlag.Active)) { if (this.webcam.active && !(this.whoMap[this.username]?.video & this.VideoFlag.Active)) {
@ -1418,7 +1456,7 @@ export default {
// video enabled, and we 'X' out, and they reopen ours - we may be receiving their // video enabled, and we 'X' out, and they reopen ours - we may be receiving their
// video right now. If we had expressly closed it, do not accept their video // video right now. If we had expressly closed it, do not accept their video
// and hang up the connection. // and hang up the connection.
if (this.WebRTC.expresslyClosed[username]) { if (this.WebRTC.expresslyClosed[username] && this.webcam.rememberExpresslyClosed) {
if (!isOfferer) { if (!isOfferer) {
return; return;
} }
@ -1496,6 +1534,10 @@ export default {
&& this.webcam.active // Our camera is active (to add it) && this.webcam.active // Our camera is active (to add it)
&& !this.isBooted(username) // We had not booted them off ours before && !this.isBooted(username) // We had not booted them off ours before
&& !this.isMutedUser(username) // We had not muted them before && !this.isMutedUser(username) // We had not muted them before
// If our webcam is NSFW and the viewer prefers not to see explicit,
// do not send our camera on this offer.
&& (!this.webcam.nsfw || !(this.whoMap[username].video & this.VideoFlag.NonExplicit))
) { ) {
let stream = this.webcam.stream; let stream = this.webcam.stream;
stream.getTracks().forEach(track => { stream.getTracks().forEach(track => {
@ -3185,40 +3227,63 @@ export default {
<p class="block mb-1" v-if="config.permitNSFW"> <p class="block mb-1" v-if="config.permitNSFW">
<label class="label">Explicit</label> <label class="label">Explicit</label>
</p> </p>
<div class="field" v-if="config.permitNSFW">
<label class="checkbox" :class="{ 'cursor-notallowed': !webcam.active }"> <div class="field mb-1" v-if="config.permitNSFW">
<input type="checkbox" v-model="webcam.nsfw" :disabled="!webcam.active"> <label class="checkbox">
Mark my camera as featuring explicit content <input type="checkbox" v-model="webcam.nsfw">
Mark my camera as featuring Explicit content
</label> </label>
</div> </div>
<div class="field">
<label class="checkbox">
<input type="checkbox" v-model="webcam.nonExplicit">
I prefer not to see Explicit cameras from other chatters
</label>
<p class="help">
Don't auto-open explicit cameras when they open mine; and automatically
close a camera I am watching if it toggles to become explicit.
</p>
</div>
<p class="block mb-1"> <p class="block mb-1">
<label class="label">Mutual webcam options</label> <label class="label">Mutual webcam options</label>
</p> </p>
<div class="field mb-1"> <div class="field mb-1">
<label class="checkbox" :class="{ 'cursor-notallowed': !webcam.active }"> <label class="checkbox">
<input type="checkbox" v-model="webcam.mutual" :disabled="!webcam.active"> <input type="checkbox" v-model="webcam.mutual">
People must be sharing their own camera before they can open mine People must be sharing their own camera before they can open mine
</label> </label>
</div> </div>
<div class="field mb-1"> <div class="field mb-1">
<label class="checkbox" :class="{ 'cursor-notallowed': !webcam.active }"> <label class="checkbox">
<input type="checkbox" v-model="webcam.mutualOpen" :disabled="!webcam.active"> <input type="checkbox" v-model="webcam.mutualOpen">
When someone opens my camera, I also open their camera automatically When someone opens my camera, I also open their camera automatically
</label> </label>
</div> </div>
<div class="field" v-if="isVIP"> <div class="field mb-1" v-if="isVIP">
<label class="checkbox" :class="{ 'cursor-notallowed': !webcam.active }"> <label class="checkbox">
<input type="checkbox" v-model="webcam.vipOnly" :disabled="!webcam.active"> <input type="checkbox" v-model="webcam.vipOnly">
Only <span v-html="config.VIP.Branding"></span> <sup class="is-size-7" Only <span v-html="config.VIP.Branding"></span> <sup class="is-size-7"
:class="config.VIP.Icon"></sup> :class="config.VIP.Icon"></sup>
members can see that my camera is broadcasting members can see that my camera is broadcasting
</label> </label>
</div> </div>
<div class="field">
<label class="checkbox">
<input type="checkbox" v-model="webcam.rememberExpresslyClosed">
Don't (automatically) reopen cameras that I have expressly closed
</label>
<p class="help">
If I click the 'X' button to expressly close a webcam, that video won't
auto-open again in case that person reopened my camera.
</p>
</div>
<h3 class="subtitle mb-2" v-if="webcam.videoDevices.length > 0 || webcam.audioDevices.length > 0"> <h3 class="subtitle mb-2" v-if="webcam.videoDevices.length > 0 || webcam.audioDevices.length > 0">
Webcam Devices Webcam Devices
<button type="button" class="button is-primary is-small is-outlined ml-2" @click="getDevices()" <button type="button" class="button is-primary is-small is-outlined ml-2" @click="getDevices()"
@ -3365,13 +3430,24 @@ export default {
</label> </label>
</div> </div>
<div class="field"> <div class="field mb-1">
<label class="checkbox"> <label class="checkbox">
<input type="checkbox" v-model="webcam.mutualOpen"> <input type="checkbox" v-model="webcam.mutualOpen">
When someone opens my camera, I also open their camera automatically When someone opens my camera, I also open their camera automatically
</label> </label>
</div> </div>
<div class="field">
<label class="checkbox">
<input type="checkbox" v-model="webcam.nonExplicit">
I prefer not to see Explicit cameras from other chatters
</label>
<p class="help">
Don't auto-open explicit cameras when they open mine; and automatically
close a camera I am watching if it toggles to become explicit.
</p>
</div>
<div class="field" v-if="isVIP"> <div class="field" v-if="isVIP">
<label class="checkbox" :class="{ 'cursor-notallowed': !webcam.active }"> <label class="checkbox" :class="{ 'cursor-notallowed': !webcam.active }">
<input type="checkbox" v-model="webcam.vipOnly"> <input type="checkbox" v-model="webcam.vipOnly">

View File

@ -80,6 +80,10 @@ export default {
parts.push(`${this.vipConfig.Name} only`); parts.push(`${this.vipConfig.Name} only`);
} }
if (this.user.video & VideoFlag.NonExplicit) {
parts.push("prefers non-explicit video");
}
return parts.join("; "); return parts.join("; ");
}, },
avatarURL() { avatarURL() {

View File

@ -14,6 +14,8 @@ const keys = {
'videoAutoMute': Boolean, 'videoAutoMute': Boolean,
'videoVipOnly': Boolean, 'videoVipOnly': Boolean,
'videoExplicit': Boolean, // whether the user turns explicit on by default 'videoExplicit': Boolean, // whether the user turns explicit on by default
'videoNonExplicit': Boolean, // user prefers not to see explicit
'rememberExpresslyClosed': Boolean,
// Booleans // Booleans
'joinMessages': Boolean, 'joinMessages': Boolean,

View File

@ -3,7 +3,7 @@ const VideoFlag = {
Active: 1 << 0, Active: 1 << 0,
NSFW: 1 << 1, NSFW: 1 << 1,
Muted: 1 << 2, Muted: 1 << 2,
IsTalking: 1 << 3, NonExplicit: 1 << 3,
MutualRequired: 1 << 4, MutualRequired: 1 << 4,
MutualOpen: 1 << 5, MutualOpen: 1 << 5,
VipOnly: 1 << 6, VipOnly: 1 << 6,