Update to Bulma CSS 1.0

* Update the CSS and add a theme selector to the Chat Settings to force a
  light or dark mode theme (default is automatic).
This commit is contained in:
Noah 2024-04-06 14:35:52 -07:00
parent f0dd1d952c
commit 92a376786d
14 changed files with 17472 additions and 15573 deletions

View File

@ -5,8 +5,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="/static/css/bulma.min.css"> <link rel="stylesheet" type="text/css" href="/static/css/bulma.min.css?{{.CacheHash}}">
<link rel="stylesheet" type="text/css" href="/static/css/bulma-prefers-dark.css?{{.CacheHash}}">
<link rel="stylesheet" href="/static/fontawesome-free-6.1.2-web/css/all.css"> <link rel="stylesheet" href="/static/fontawesome-free-6.1.2-web/css/all.css">
<link rel="stylesheet" type="text/css" href="/static/css/chat.css?{{.CacheHash}}"> <link rel="stylesheet" type="text/css" href="/static/css/chat.css?{{.CacheHash}}">
<title>{{.Config.Title}}</title> <title>{{.Config.Title}}</title>
@ -40,6 +39,7 @@
const UserJWTValid = {{if .JWTAuthOK}}true{{else}}false{{end}}; const UserJWTValid = {{if .JWTAuthOK}}true{{else}}false{{end}};
const UserJWTClaims = {{.JWTClaims.ToJSON}}; const UserJWTClaims = {{.JWTClaims.ToJSON}};
const CachedBlocklist = {{.CachedBlocklist}}; const CachedBlocklist = {{.CachedBlocklist}};
const CacheHash = {{.CacheHash}};
// Show the photo detail modal. // Show the photo detail modal.
function setModalImage(url) { function setModalImage(url) {

View File

@ -0,0 +1,54 @@
/* Forced dark theme for Bulma (custom created for BareRTC) */
/* BareRTC custom overrides */
@import url("chat-dark.css");
/* Copied from bulma.css - original dark theme styles */
:root {
--bulma-white-on-scheme-l: 100%;
--bulma-white-on-scheme: hsla(var(--bulma-white-h), var(--bulma-white-s), var(--bulma-white-on-scheme-l), 1);
--bulma-black-on-scheme-l: 0%;
--bulma-black-on-scheme: hsla(var(--bulma-black-h), var(--bulma-black-s), var(--bulma-black-on-scheme-l), 1);
--bulma-light-on-scheme-l: 96%;
--bulma-light-on-scheme: hsla(var(--bulma-light-h), var(--bulma-light-s), var(--bulma-light-on-scheme-l), 1);
--bulma-dark-on-scheme-l: 56%;
--bulma-dark-on-scheme: hsla(var(--bulma-dark-h), var(--bulma-dark-s), var(--bulma-dark-on-scheme-l), 1);
--bulma-text-on-scheme-l: 54%;
--bulma-text-on-scheme: hsla(var(--bulma-text-h), var(--bulma-text-s), var(--bulma-text-on-scheme-l), 1);
--bulma-primary-on-scheme-l: 41%;
--bulma-primary-on-scheme: hsla(var(--bulma-primary-h), var(--bulma-primary-s), var(--bulma-primary-on-scheme-l), 1);
--bulma-link-on-scheme-l: 73%;
--bulma-link-on-scheme: hsla(var(--bulma-link-h), var(--bulma-link-s), var(--bulma-link-on-scheme-l), 1);
--bulma-info-on-scheme-l: 70%;
--bulma-info-on-scheme: hsla(var(--bulma-info-h), var(--bulma-info-s), var(--bulma-info-on-scheme-l), 1);
--bulma-success-on-scheme-l: 53%;
--bulma-success-on-scheme: hsla(var(--bulma-success-h), var(--bulma-success-s), var(--bulma-success-on-scheme-l), 1);
--bulma-warning-on-scheme-l: 53%;
--bulma-warning-on-scheme: hsla(var(--bulma-warning-h), var(--bulma-warning-s), var(--bulma-warning-on-scheme-l), 1);
--bulma-danger-on-scheme-l: 70%;
--bulma-danger-on-scheme: hsla(var(--bulma-danger-h), var(--bulma-danger-s), var(--bulma-danger-on-scheme-l), 1);
--bulma-scheme-brightness: dark;
--bulma-scheme-main-l: 9%;
--bulma-scheme-main-bis-l: 11%;
--bulma-scheme-main-ter-l: 13%;
--bulma-soft-l: 20%;
--bulma-bold-l: 90%;
--bulma-soft-invert-l: 90%;
--bulma-bold-invert-l: 20%;
--bulma-background-l: 14%;
--bulma-border-weak-l: 21%;
--bulma-border-l: 24%;
--bulma-text-weak-l: 53%;
--bulma-text-l: 71%;
--bulma-text-strong-l: 93%;
--bulma-text-title-l: 100%;
--bulma-hover-background-l-delta: 5%;
--bulma-active-background-l-delta: 10%;
--bulma-hover-border-l-delta: 10%;
--bulma-active-border-l-delta: 20%;
--bulma-hover-color-l-delta: 5%;
--bulma-active-color-l-delta: 10%;
--bulma-shadow-h: 0deg;
--bulma-shadow-s: 0%;
--bulma-shadow-l: 100%;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,51 @@
/* Custom color overrides for Bulma's dark theme */
.chat-container {
background: rgb(39, 39, 39) !important;
background: linear-gradient(0deg, rgb(39, 39, 39) 0%, rgb(66, 66, 66) 100%) !important;
}
.has-background-primary-light {
background-color: rgba(28, 166, 76, 0.25) !important;
}
.has-background-info-light, .has-background-info {
background-color: rgb(26, 79, 95) !important
}
.has-background-success-light, .has-background-success {
background-color: rgba(19, 71, 37, 0.685) !important
}
.has-background-warning-light, .has-background-warning {
background-color: rgb(100, 90, 41) !important;
}
/* note: this css file otherwise didn't override this, dark's always dark, brighten it! */
.has-text-dark, .button.is-grey {
color: #b5b5b5 !important;
}
.button.is-dark {
color: #b5b5b5 !important;
border-color: #b5b5b5 !important;
}
/* adjust some background colors darker */
.notification.is-success.is-light {
background-color: #232e29 !important;
color: #56cf98 !important;
}
.notification.is-warning.is-light {
background-color: rgb(51, 46, 21) !important;
color: rgb(253, 227, 97) !important;
}
.has-background-dm {
background-color: #100010 !important;
}
.emoji-button button {
background-color: rgba(0, 0, 0, 0.5) !important;
color: rgba(255, 255, 255, 0.5) !important;
}

View File

@ -0,0 +1,3 @@
/* Custom nonshy color overrides for Bulma's dark theme
(prefers-dark edition) */
@import url("chat-dark.css") screen and (prefers-color-scheme: dark);

View File

@ -87,13 +87,6 @@ img {
grid-template-rows: auto 1fr auto; grid-template-rows: auto 1fr auto;
} }
@media (prefers-color-scheme: dark) {
.chat-container {
background: rgb(39, 39, 39);
background: linear-gradient(0deg, rgb(39, 39, 39) 0%, rgb(66, 66, 66) 100%);
}
}
/* Header row */ /* Header row */
.chat-container > .chat-header { .chat-container > .chat-header {
grid-column: 1 / 4; grid-column: 1 / 4;
@ -145,7 +138,7 @@ img {
/* Responsive CSS styles */ /* Responsive CSS styles */
@media screen and (min-width: 1024px) { @media screen and (min-width: 1024px) {
.mobile-only { .mobile-only {
display: none; display: none !important;
} }
} }
@media screen and (max-width: 1024px) { @media screen and (max-width: 1024px) {

View File

@ -78,6 +78,7 @@ export default {
website: WebsiteURL, website: WebsiteURL,
permitNSFW: PermitNSFW, permitNSFW: PermitNSFW,
webhookURLs: WebhookURLs, webhookURLs: WebhookURLs,
cacheHash: CacheHash,
VIP: VIP, VIP: VIP,
fontSizeClasses: [ fontSizeClasses: [
["x-2", "Very small chat room text"], ["x-2", "Very small chat room text"],
@ -153,6 +154,7 @@ export default {
watchNotif: true, // notify in chat about cameras being watched watchNotif: true, // notify in chat about cameras being watched
closeDMs: false, // ignore unsolicited DMs closeDMs: false, // ignore unsolicited DMs
muteSounds: false, // mute all sound effects muteSounds: false, // mute all sound effects
theme: "auto", // auto, light, dark theme
appleCompat: isAppleWebkit(), // Apple browser compatibility mode appleCompat: isAppleWebkit(), // Apple browser compatibility mode
}, },
@ -515,6 +517,9 @@ export default {
"prefs.appleCompat": function () { "prefs.appleCompat": function () {
LocalStorage.set('appleCompat', this.prefs.appleCompat); LocalStorage.set('appleCompat', this.prefs.appleCompat);
}, },
"prefs.theme": function() {
LocalStorage.set('theme', this.prefs.theme);
},
}, },
computed: { computed: {
connected() { connected() {
@ -892,6 +897,9 @@ export default {
if (settings.whoSort != undefined) { if (settings.whoSort != undefined) {
this.whoSort = settings.whoSort; this.whoSort = settings.whoSort;
} }
if (settings.theme != undefined) {
this.prefs.theme = settings.theme;
}
}, },
signIn(username) { signIn(username) {
@ -3384,6 +3392,36 @@ export default {
<!-- Display preferences --> <!-- Display preferences -->
<div v-if="settingsModal.tab === 'prefs'"> <div v-if="settingsModal.tab === 'prefs'">
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Theme</label>
</div>
<div class="field-body">
<div class="field">
<div class="control">
<label class="radio">
<input type="radio"
v-model="prefs.theme"
value="auto">
Automatic
</label>
<label class="radio">
<input type="radio"
v-model="prefs.theme"
value="light">
Light
</label>
<label class="radio">
<input type="radio"
v-model="prefs.theme"
value="dark">
Dark
</label>
</div>
</div>
</div>
</div>
<div class="field is-horizontal"> <div class="field is-horizontal">
<div class="field-label is-normal"> <div class="field-label is-normal">
<label class="label">Video size</label> <label class="label">Video size</label>
@ -3796,7 +3834,7 @@ export default {
<div class="modal-content"> <div class="modal-content">
<div class="card"> <div class="card">
<header class="card-header has-background-info"> <header class="card-header has-background-info">
<p class="card-header-title has-text-light">Broadcast my webcam</p> <p class="card-header-title">Select Webcam Options</p>
</header> </header>
<div class="card-content"> <div class="card-content">
<p class="block mb-1"> <p class="block mb-1">
@ -3878,7 +3916,7 @@ export default {
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select v-model="webcam.videoDeviceID"> <select v-model="webcam.videoDeviceID">
<option :value="null" disabled selected>Select default camera</option> <option :value="null" disabled selected>Select default camera</option>
<option v-for="(d, i) in webcam.videoDevices" :value="d.id"> <option v-for="(d, i) in webcam.videoDevices" :value="d.id" v-bind:key="i">
{{ d.label || `Camera ${i}` }} {{ d.label || `Camera ${i}` }}
</option> </option>
</select> </select>
@ -3890,7 +3928,7 @@ export default {
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select v-model="webcam.audioDeviceID"> <select v-model="webcam.audioDeviceID">
<option :value="null" disabled selected>Select default microphone</option> <option :value="null" disabled selected>Select default microphone</option>
<option v-for="(d, i) in webcam.audioDevices" :value="d.id"> <option v-for="(d, i) in webcam.audioDevices" :value="d.id" v-bind:key="i">
{{ d.label || `Microphone ${i}` }} {{ d.label || `Microphone ${i}` }}
</option> </option>
</select> </select>
@ -3900,9 +3938,9 @@ export default {
<div class="field"> <div class="field">
<div class="control has-text-centered"> <div class="control has-text-centered">
<button type="button" class="button is-link mr-4"
@click="startVideo({ force: true }); nsfwModalCast.visible = false">Start webcam</button>
<button type="button" class="button" @click="nsfwModalCast.visible = false">Cancel</button> <button type="button" class="button" @click="nsfwModalCast.visible = false">Cancel</button>
<button type="button" class="button is-success ml-2"
@click="startVideo({ force: true }); nsfwModalCast.visible = false">Start webcam</button>
</div> </div>
</div> </div>
</div> </div>
@ -4019,8 +4057,8 @@ export default {
<!-- Left Column: Channels & DMs --> <!-- Left Column: Channels & DMs -->
<div class="left-column"> <div class="left-column">
<div class="card grid-card"> <div class="card grid-card">
<header class="card-header has-background-success-dark"> <header class="card-header has-background-success">
<div class="columns is-mobile card-header-title has-text-light"> <div class="columns is-mobile card-header-title">
<div class="column is-narrow mobile-only"> <div class="column is-narrow mobile-only">
<button type="button" class="button is-success px-2" @click="openChatPanel"> <button type="button" class="button is-success px-2" @click="openChatPanel">
<i class="fa fa-arrow-left"></i> <i class="fa fa-arrow-left"></i>
@ -4128,7 +4166,7 @@ export default {
<i class="fa fa-gear"></i> <i class="fa fa-gear"></i>
</button> </button>
<button type="button" class="button is-small is-outlined" :disabled="webcam.videoScale === 'x4'" <button type="button" class="button is-small is-outlined mr-1" :disabled="webcam.videoScale === 'x4'"
@click="scaleVideoSize(true)"> @click="scaleVideoSize(true)">
<i class="fa fa-magnifying-glass-plus"></i> <i class="fa fa-magnifying-glass-plus"></i>
</button> </button>
@ -4353,8 +4391,8 @@ export default {
<!-- Right Column: Who Is Online --> <!-- Right Column: Who Is Online -->
<div class="right-column"> <div class="right-column">
<div class="card grid-card"> <div class="card grid-card">
<header class="card-header has-background-success-dark"> <header class="card-header has-background-success">
<div class="columns is-mobile card-header-title has-text-light"> <div class="columns is-mobile card-header-title">
<div class="column">Who Is Online</div> <div class="column">Who Is Online</div>
<div class="column is-narrow mobile-only"> <div class="column is-narrow mobile-only">
<button type="button" class="button is-success px-2" @click="openChatPanel"> <button type="button" class="button is-success px-2" @click="openChatPanel">
@ -4424,8 +4462,8 @@ export default {
</div> </div>
<!-- Who Is Online --> <!-- Who Is Online -->
<ul class="menu-list" v-if="whoTab === 'online'"> <div v-if="whoTab === 'online'">
<li v-for="(u, i) in sortedWhoList" v-bind:key="i"> <div v-for="(u, i) in sortedWhoList" v-bind:key="i">
<WhoListRow <WhoListRow
:user="u" :user="u"
:username="username" :username="username"
@ -4443,12 +4481,12 @@ export default {
@open-video="openVideo" @open-video="openVideo"
@open-profile="showProfileModal"> @open-profile="showProfileModal">
</WhoListRow> </WhoListRow>
</li> </div>
</ul> </div>
<!-- Watching My Webcam --> <!-- Watching My Webcam -->
<ul class="menu-list" v-if="whoTab === 'watching'"> <div v-if="whoTab === 'watching'">
<li v-for="(u, i) in sortedWatchingList" v-bind:key="username"> <div v-for="(u, i) in sortedWatchingList" v-bind:key="i">
<WhoListRow <WhoListRow
:is-watching-tab="true" :is-watching-tab="true"
:user="u" :user="u"
@ -4468,13 +4506,23 @@ export default {
@boot-user="bootUser" @boot-user="bootUser"
@open-profile="showProfileModal"> @open-profile="showProfileModal">
</WhoListRow> </WhoListRow>
</li> </div>
</ul> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Theme CSS (light/dark) -->
<link v-if="prefs.theme === 'light'"
rel="stylesheet" type="text/css"
href="/static/css/bulma-no-dark-mode.min.css?{{.config.cacheHash}}">
<link v-else-if="prefs.theme === 'dark'"
rel="stylesheet" type="text/css"
href="/static/css/bulma-dark-theme.css?{{.config.cacheHash}}">
<link v-else rel="stylesheet" type="text/css"
href="/static/css/chat-prefers-dark.css?{{.config.cacheHash}}">
</template> </template>
<style> <style>

View File

@ -192,7 +192,7 @@ export default {
<div v-if="user.username !== username" class="mt-4"> <div v-if="user.username !== username" class="mt-4">
<!-- DMs button --> <!-- DMs button -->
<button type="button" <button type="button"
class="button is-grey is-outlined is-small px-2 mb-1" class="button is-dark is-outlined is-small px-2 mb-1"
@click="openDMs()" @click="openDMs()"
:title="isDnd ? 'This person is not accepting new DMs' : 'Open a Direct Message (DM) thread'" :title="isDnd ? 'This person is not accepting new DMs' : 'Open a Direct Message (DM) thread'"
:disabled="isDnd"> :disabled="isDnd">
@ -202,7 +202,7 @@ export default {
<!-- Mute button --> <!-- Mute button -->
<button type="button" <button type="button"
class="button is-grey is-outlined is-small px-2 ml-1 mb-1" class="button is-dark is-outlined is-small px-2 ml-1 mb-1"
@click="muteUser()" title="Mute user"> @click="muteUser()" title="Mute user">
<i class="fa fa-comment-slash mr-1" :class="{ <i class="fa fa-comment-slash mr-1" :class="{
'has-text-success': isMuted, 'has-text-success': isMuted,
@ -213,7 +213,7 @@ export default {
<!-- Boot button --> <!-- Boot button -->
<button type="button" <button type="button"
class="button is-grey is-outlined is-small px-2 ml-1 mb-1" class="button is-dark is-outlined is-small px-2 ml-1 mb-1"
@click="bootUser()" title="Boot user off your webcam"> @click="bootUser()" title="Boot user off your webcam">
<i class="fa fa-user-xmark mr-1" :class="{ <i class="fa fa-user-xmark mr-1" :class="{
'has-text-danger': !isBooted, 'has-text-danger': !isBooted,

View File

@ -7,6 +7,7 @@ const keys = {
'scrollback': Number, // Scrollback buffer (int) 'scrollback': Number, // Scrollback buffer (int)
'preferredDeviceNames': Object, // Webcam/mic device names (object, keys video,audio) 'preferredDeviceNames': Object, // Webcam/mic device names (object, keys video,audio)
'whoSort': String, // user's preferred sort order for the Who List 'whoSort': String, // user's preferred sort order for the Who List
'theme': String, // light, dark, or auto theme
// Webcam settings (booleans) // Webcam settings (booleans)
'videoMutual': Boolean, 'videoMutual': Boolean,