diff --git a/app/src/server.js b/app/src/server.js index 1dcc7dca..3e3a6aa0 100755 --- a/app/src/server.js +++ b/app/src/server.js @@ -38,7 +38,7 @@ dependencies: { * @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.2.83 + * @version 1.2.84 * */ diff --git a/package.json b/package.json index 825d5b34..2519f582 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalk", - "version": "1.2.83", + "version": "1.2.84", "description": "A free WebRTC browser-based video call", "main": "server.js", "scripts": { @@ -37,8 +37,8 @@ "license": "AGPL-3.0", "homepage": "https://github.com/miroslavpejic85/mirotalk", "dependencies": { - "@sentry/integrations": "^7.99.0", - "@sentry/node": "^7.99.0", + "@sentry/integrations": "^7.100.1", + "@sentry/node": "^7.100.1", "axios": "^1.6.7", "body-parser": "^1.20.2", "colors": "^1.4.0", @@ -48,7 +48,7 @@ "dotenv": "^16.4.1", "express": "^4.18.2", "ngrok": "^4.3.3", - "openai": "^4.26.0", + "openai": "^4.26.1", "qs": "^6.11.2", "socket.io": "^4.7.4", "swagger-ui-express": "^5.0.0", diff --git a/public/css/client.css b/public/css/client.css index 16739ad2..95ed8406 100755 --- a/public/css/client.css +++ b/public/css/client.css @@ -35,7 +35,7 @@ --hover-color: grey; /* video elem border color */ - --elem-border-color: none; /* 1px solid rgb(255 255 255 / 32%) */ + --elem-border-color: none; --tab-btn-active: rgb(30 29 29); @@ -126,6 +126,7 @@ body { text-align: center; border-radius: 10px; background: rgba(0, 0, 0, 0.7); + box-shadow: var(--box-shadow); } #loadingDiv h1 { font-size: 60px; @@ -949,6 +950,32 @@ button:hover { /* font-weight: bold; */ } +.inline-check-box { + margin-bottom: 20px; + display: inline-flex; + justify-content: center; /* Vertical centering */ + align-items: center; /* Horizontal centering */ + text-align: left; + color: white; +} + +#themeColorPicker { + z-index: 6; + padding: 10px; + margin-top: 10px; + margin-bottom: 20px; + width: 130px; + border: var(--border); + border-radius: 5px; + background: var(--select-bg); + color: white; + cursor: pointer; +} + +#keepCustomTheme { + margin-bottom: 10px; +} + .buttons { padding: 10px; float: left; @@ -1785,6 +1812,7 @@ button { /* z-index +6 theme custom picker 7 video avatar img 8 video nav bar 8 peer name diff --git a/public/css/videoGrid.css b/public/css/videoGrid.css index 33d95a33..a99fb3d0 100644 --- a/public/css/videoGrid.css +++ b/public/css/videoGrid.css @@ -41,6 +41,7 @@ display: inline-block; background: var(--body-bg); border: var(--elem-border-color); + box-shadow: var(--box-shadow); border-radius: 10px; animation: show 0.4s ease; } diff --git a/public/js/client.js b/public/js/client.js index 89ed5cac..f66aa4ba 100644 --- a/public/js/client.js +++ b/public/js/client.js @@ -15,7 +15,7 @@ * @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.2.83 + * @version 1.2.84 * */ @@ -98,6 +98,7 @@ const icons = { fileSend: '', fileReceive: '', codecs: '', + theme: '', }; // Whiteboard and fileSharing @@ -502,6 +503,55 @@ const useAvatarSvg = true; // if false the cam-Off avatar = images.avatar const ZOOM_CENTER_MODE = false; const ZOOM_IN_OUT_ENABLED = true; // Video Zoom in/out default (true) +// Color Picker: + +const themeCustom = { + input: getId('themeColorPicker'), + check: getId('keepCustomTheme'), + color: lsSettings.theme_color ? lsSettings.theme_color : '#000000', + keep: lsSettings.theme_custom ? lsSettings.theme_custom : false, +}; + +const pickr = Pickr.create({ + el: themeCustom.input, + theme: 'classic', // or 'monolith', or 'nano' + default: themeCustom.color, + useAsButton: true, + swatches: [ + 'rgba(244, 67, 54, 1)', + 'rgba(233, 30, 99, 0.95)', + 'rgba(156, 39, 176, 0.9)', + 'rgba(103, 58, 183, 0.85)', + 'rgba(63, 81, 181, 0.8)', + 'rgba(33, 150, 243, 0.75)', + 'rgba(3, 169, 244, 0.7)', + 'rgba(0, 188, 212, 0.7)', + 'rgba(0, 150, 136, 0.75)', + 'rgba(76, 175, 80, 0.8)', + 'rgba(139, 195, 74, 0.85)', + 'rgba(205, 220, 57, 0.9)', + 'rgba(255, 235, 59, 0.95)', + 'rgba(255, 193, 7, 1)', + ], + components: { + preview: true, + opacity: true, + hue: true, + }, +}) + .on('init', (pickr) => { + themeCustom.input.value = pickr.getSelectedColor().toHEXA().toString(0); + }) + .on('change', (color) => { + themeCustom.color = color.toHEXA().toString(); + themeCustom.input.value = themeCustom.color; + setCustomTheme(); + }) + .on('changestop', () => { + lsSettings.theme_color = themeCustom.color; + lS.setSettings(lsSettings); + }); + // misc let swBg = 'rgba(0, 0, 0, 0.7)'; // swAlert background color let callElapsedTime; // count time @@ -2173,11 +2223,35 @@ function handleRemovePeer(config) { console.log('ALL PEERS', allPeers); } +/** + * Set custom theme + */ +function setCustomTheme() { + const color = themeCustom.color; + swBg = `radial-gradient(${color}, ${color})`; + setSP('--body-bg', `radial-gradient(${color}, ${color})`); + setSP('--msger-bg', `radial-gradient(${color}, ${color})`); + setSP('--msger-private-bg', `radial-gradient(${color}, ${color})`); + setSP('--wb-bg', `radial-gradient(${color}, ${color})`); + setSP('--elem-border-color', '0.5px solid rgb(255 255 255 / 32%)'); + setSP('--navbar-bg', 'rgba(0, 0, 0, 0.2)'); + setSP('--select-bg', `${color}`); + setSP('--tab-btn-active', `${color}`); + setSP('--box-shadow', '0px 8px 16px 0px rgba(0, 0, 0, 0.2)'); + setSP('--left-msg-bg', '#252d31'); + setSP('--right-msg-bg', `${color}`); + setSP('--private-msg-bg', '#6b1226'); + setSP('--btn-bar-bg-color', '#FFFFFF'); + setSP('--btn-bar-color', '#000000'); + document.body.style.background = `radial-gradient(${color}, ${color})`; +} + /** * Set mirotalk theme | dark | grey | ... - * @param {string} theme type */ function setTheme() { + if (themeCustom.keep) return setCustomTheme(); + mirotalkTheme.selectedIndex = lsSettings.theme; const theme = mirotalkTheme.value; switch (theme) { @@ -2188,6 +2262,7 @@ function setTheme() { setSP('--msger-bg', 'radial-gradient(#393939, #000000)'); setSP('--msger-private-bg', 'radial-gradient(#393939, #000000)'); setSP('--wb-bg', 'radial-gradient(#393939, #000000)'); + setSP('--elem-border-color', 'none'); setSP('--navbar-bg', 'rgba(0, 0, 0, 0.2)'); setSP('--select-bg', '#2c2c2c'); setSP('--tab-btn-active', 'rgb(30 29 29)'); @@ -2206,6 +2281,7 @@ function setTheme() { setSP('--body-bg', 'radial-gradient(#666, #333)'); setSP('--msger-bg', 'radial-gradient(#666, #333)'); setSP('--wb-bg', 'radial-gradient(#797979, #000)'); + setSP('--elem-border-color', 'none'); setSP('--navbar-bg', 'rgba(0, 0, 0, 0.2)'); setSP('--select-bg', '#2c2c2c'); setSP('--tab-btn-active', 'rgb(30 29 29)'); @@ -2225,6 +2301,7 @@ function setTheme() { setSP('--body-bg', 'radial-gradient(#003934, #001E1A)'); setSP('--msger-bg', 'radial-gradient(#003934, #001E1A)'); setSP('--wb-bg', 'radial-gradient(#003934, #001E1A)'); + setSP('--elem-border-color', 'none'); setSP('--navbar-bg', 'rgba(0, 0, 0, 0.2)'); setSP('--select-bg', '#001E1A'); setSP('--tab-btn-active', '#003934'); @@ -2244,6 +2321,7 @@ function setTheme() { setSP('--body-bg', 'radial-gradient(#306bac, #141B41)'); setSP('--msger-bg', 'radial-gradient(#306bac, #141B41)'); setSP('--wb-bg', 'radial-gradient(#306bac, #141B41)'); + setSP('--elem-border-color', 'none'); setSP('--navbar-bg', 'rgba(0, 0, 0, 0.2)'); setSP('--select-bg', '#141B41'); setSP('--tab-btn-active', '#306bac'); @@ -4626,6 +4704,18 @@ function setMySettingsBtn() { resumeRecBtn.addEventListener('click', (e) => { resumeRecording(); }); + // Styles + themeCustom.check.onchange = (e) => { + themeCustom.keep = e.currentTarget.checked; + themeSelect.disabled = themeCustom.keep; + lsSettings.theme_custom = themeCustom.keep; + lsSettings.theme_color = themeCustom.color; + lS.setSettings(lsSettings); + setTheme(); + userLog('toast', `${icons.theme} Custom theme keep ` + (themeCustom.keep ? 'ON' : 'OFF')); + playSound('switch'); + e.target.blur(); + }; } /** @@ -4876,6 +4966,10 @@ function loadSettingsFromLocalStorage() { switchAudioPitchBar.checked = isAudioPitchBar; switchH264Recording.checked = recPrioritizeH264; + themeCustom.check.checked = themeCustom.keep; + themeSelect.disabled = themeCustom.keep; + themeCustom.input.value = themeCustom.color; + switchAutoGainControl.checked = lsSettings.mic_auto_gain_control; switchEchoCancellation.checked = lsSettings.mic_echo_cancellations; switchNoiseSuppression.checked = lsSettings.mic_noise_suppression; diff --git a/public/js/localStorage.js b/public/js/localStorage.js index 748fd7b8..63bc0097 100644 --- a/public/js/localStorage.js +++ b/public/js/localStorage.js @@ -31,6 +31,8 @@ class LocalStorage { sounds: true, video_obj_fit: 2, // cover theme: 0, // dark + theme_color: '#000000', // custom theme color + theme_custom: false, // keep custom theme buttons_bar: 0, // vertical pin_grid: 0, // vertical }; diff --git a/public/views/client.html b/public/views/client.html index f301d2e5..0b682ff3 100755 --- a/public/views/client.html +++ b/public/views/client.html @@ -52,6 +52,15 @@ + + + + + + + + + @@ -712,6 +721,23 @@ access to use this app.
+
+ +

Custom theme

+
+
+ +
+
+
+
+ +

Keep custom

+
+
+ +
+

Buttons bar

@@ -889,6 +915,8 @@ access to use this app. - https://www.jsdelivr.com/package/npm/crypto-js (https://github.com/brix/crypto-js/) - https://www.npmjs.com/package/tippy.js (https://github.com/atomiks/tippyjs) - https://flatpickr.js.org/ (https://github.com/flatpickr/flatpickr) + - https://simonwep.github.io/pickr/ (https://github.com/simonwep/pickr) + --> @@ -904,6 +932,8 @@ access to use this app. + +