From dffc992f4b725c30ced3acb5c4e5f75aff00decd Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Mon, 10 Nov 2025 19:45:06 +0100 Subject: [PATCH] [mirotalksfu] - add support us section --- .env.template | 1 + app/src/config.template.js | 1 + package-lock.json | 63 +++++++++++------ package.json | 4 +- public/css/landing.css | 140 +++++++++++++++++++++++++++++++++++++ public/js/Brand.js | 15 +++- public/views/landing.html | 100 ++++++++++++++++++++++++++ 7 files changed, 298 insertions(+), 26 deletions(-) diff --git a/.env.template b/.env.template index b6aa36e4..63dff9dc 100644 --- a/.env.template +++ b/.env.template @@ -288,6 +288,7 @@ SHOW_TRY_EASIER=true # Show "try easier" section (t SHOW_POWERED_BY=true # Show powered by (true|false) SHOW_SPONSORS=true # Show sponsors (true|false) SHOW_ADVERTISERS=true # Show advertisers (true|false) +SHOW_SUPPORT_US=true # Show support us section (true|false) SHOW_FOOTER=true # Show footer (true|false) # Who Are You diff --git a/app/src/config.template.js b/app/src/config.template.js index 28ce64ff..80fc1f1a 100644 --- a/app/src/config.template.js +++ b/app/src/config.template.js @@ -1060,6 +1060,7 @@ module.exports = { poweredBy: process.env.SHOW_POWERED_BY !== 'false', sponsors: process.env.SHOW_SPONSORS !== 'false', advertisers: process.env.SHOW_ADVERTISERS !== 'false', + supportUs: process.env.SHOW_SUPPORT_US !== 'false', footer: process.env.SHOW_FOOTER !== 'false', }, diff --git a/package-lock.json b/package-lock.json index 797ca658..a91a11f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@aws-sdk/lib-storage": "^3.927.0", "@mattermost/client": "11.0.4", "@ngrok/ngrok": "1.5.2", - "@sentry/node": "^10.23.0", + "@sentry/node": "^10.24.0", "async-mutex": "^0.5.0", "axios": "^1.13.2", "chokidar": "^4.0.3", @@ -33,7 +33,7 @@ "js-yaml": "^4.1.0", "jsdom": "^27.1.0", "jsonwebtoken": "^9.0.2", - "mediasoup": "3.19.7", + "mediasoup": "3.19.8", "mediasoup-client": "3.18.0", "nodemailer": "^7.0.10", "openai": "^6.8.1", @@ -341,6 +341,7 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.927.0.tgz", "integrity": "sha512-LwjZH7/WDFw2++ntRtJMMlkZy+BTMaQQv+S8m3amfRo4iF4KJKRE2q3+QOKX2Xpvnw5IEHkmLa+oEanGlk2t1g==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", @@ -1062,6 +1063,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2629,6 +2631,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2670,6 +2673,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -3202,6 +3206,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=8.0.0" } @@ -3223,6 +3228,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.2.0.tgz", "integrity": "sha512-qRkLWiUEZNAmYapZ7KGS5C4OmBLcP/H2foXeOEaowYCR0wi89fHejrfYfbuLVCMLp/dWZXKvQusdbUEZjERfwQ==", "license": "Apache-2.0", + "peer": true, "engines": { "node": "^18.19.0 || >=20.6.0" }, @@ -3235,6 +3241,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, @@ -3250,6 +3257,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.204.0.tgz", "integrity": "sha512-vV5+WSxktzoMP8JoYWKeopChy6G3HKk4UQ2hESCRDUUTZqQ3+nM3u8noVG0LmNfRWwcFBnbZ71GKC7vaYYdJ1g==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/api-logs": "0.204.0", "import-in-the-middle": "^1.8.1", @@ -3642,6 +3650,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" @@ -3673,6 +3682,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", @@ -3705,6 +3715,7 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz", "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==", "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=14" } @@ -3841,18 +3852,18 @@ "license": "Apache-2.0" }, "node_modules/@sentry/core": { - "version": "10.23.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.23.0.tgz", - "integrity": "sha512-4aZwu6VnSHWDplY5eFORcVymhfvS/P6BRfK81TPnG/ReELaeoykKjDwR+wC4lO7S0307Vib9JGpszjsEZw245g==", + "version": "10.24.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.24.0.tgz", + "integrity": "sha512-apJ1NtCK/Kt5uTytee+4rhhcTm4u3+z0bESH8GNMXMcuJ/A3Rvy3HUh+gqCx4BTOR0Sa44dbMvJcm/ewO+mzVg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/node": { - "version": "10.23.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.23.0.tgz", - "integrity": "sha512-5PwJJ1zZ89tB8hrjTVKNE4fIGtSXlR+Mdg2u1Nm2FJ2Vj1Ac6JArLiRzMqoq/pA7vwgZMoHwviDAA+PfpJ0Agg==", + "version": "10.24.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.24.0.tgz", + "integrity": "sha512-OsyMzemG+a1QHe9BXDduA0bL4r5dlViOpIocSL3atPNupYTxoSZqOP/wFwqTGE+M/2oIv0/VIIWoXJUd8BLUAg==", "license": "MIT", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -3885,9 +3896,9 @@ "@opentelemetry/sdk-trace-base": "^2.1.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@prisma/instrumentation": "6.15.0", - "@sentry/core": "10.23.0", - "@sentry/node-core": "10.23.0", - "@sentry/opentelemetry": "10.23.0", + "@sentry/core": "10.24.0", + "@sentry/node-core": "10.24.0", + "@sentry/opentelemetry": "10.24.0", "import-in-the-middle": "^1.14.2", "minimatch": "^9.0.0" }, @@ -3896,14 +3907,14 @@ } }, "node_modules/@sentry/node-core": { - "version": "10.23.0", - "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.23.0.tgz", - "integrity": "sha512-3vhttO19pta7zIuecSrLoPTVN7NdjKtb/WK241H8znwKxukx3fj3M6+upN+JQtC6pERO3HfQwBpMMT9RMCUr3Q==", + "version": "10.24.0", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.24.0.tgz", + "integrity": "sha512-OTvJSrPstEc0NydMDpdmyYeuOcOQxZ0ZT8rmdKkrw4odYs56pYS4euMHNler8Tw9j8mZxqyI/wjzl//xGI+F0w==", "license": "MIT", "dependencies": { "@apm-js-collab/tracing-hooks": "^0.3.1", - "@sentry/core": "10.23.0", - "@sentry/opentelemetry": "10.23.0", + "@sentry/core": "10.24.0", + "@sentry/opentelemetry": "10.24.0", "import-in-the-middle": "^1.14.2" }, "engines": { @@ -3920,12 +3931,12 @@ } }, "node_modules/@sentry/opentelemetry": { - "version": "10.23.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.23.0.tgz", - "integrity": "sha512-ZbSB5y8K8YXp5+sBp2w7xHsNLv9EglJRTRqWMi2ncovXy4jcvo+pSreiZu68nSGvxX25brYKDw19vl+tnmqZVg==", + "version": "10.24.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.24.0.tgz", + "integrity": "sha512-yOqeAUTnikx1eG8XMWvY4FWEU/aBp24sKlejxE0k7jmw5X2vCBd+4FUgDAwKsHwvEGOeD2XVfMqgLYjrNkm+Vg==", "license": "MIT", "dependencies": { - "@sentry/core": "10.23.0" + "@sentry/core": "10.24.0" }, "engines": { "node": ">=18" @@ -5209,6 +5220,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5266,6 +5278,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5614,6 +5627,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -6701,6 +6715,7 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", + "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", @@ -8138,9 +8153,9 @@ } }, "node_modules/mediasoup": { - "version": "3.19.7", - "resolved": "https://registry.npmjs.org/mediasoup/-/mediasoup-3.19.7.tgz", - "integrity": "sha512-/DLmAFf1Cv8pQddTn+Z5DksqiMWaKvEoQiZzHfnY3gNbz1QfNEel+kgyKGxWUzOPZDgLMkOdFXMuUGvNZwHS/Q==", + "version": "3.19.8", + "resolved": "https://registry.npmjs.org/mediasoup/-/mediasoup-3.19.8.tgz", + "integrity": "sha512-COaRp9JDx8sO7ojopWvWlSklRRZ1Ybr+0f1CcQQZr69q3bgSuvOmf9XCPvh7RYz9HbNkHH+CNDsug6XnNrzAdg==", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -10517,6 +10532,7 @@ "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -10566,6 +10582,7 @@ "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.6.1", "@webpack-cli/configtest": "^3.0.1", diff --git a/package.json b/package.json index 4178edc3..9e69ce7f 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@aws-sdk/lib-storage": "^3.927.0", "@mattermost/client": "11.0.4", "@ngrok/ngrok": "1.5.2", - "@sentry/node": "^10.23.0", + "@sentry/node": "^10.24.0", "async-mutex": "^0.5.0", "axios": "^1.13.2", "chokidar": "^4.0.3", @@ -81,7 +81,7 @@ "js-yaml": "^4.1.0", "jsdom": "^27.1.0", "jsonwebtoken": "^9.0.2", - "mediasoup": "3.19.7", + "mediasoup": "3.19.8", "mediasoup-client": "3.18.0", "nodemailer": "^7.0.10", "openai": "^6.8.1", diff --git a/public/css/landing.css b/public/css/landing.css index 3c39aefc..f4fe8643 100644 --- a/public/css/landing.css +++ b/public/css/landing.css @@ -2142,3 +2142,143 @@ main { pointer-events: none; opacity: 0.5; } + +/*-------------------------------------------------------------- +# Support Us Section +--------------------------------------------------------------*/ + +#supportUs .cta-inner { + background: linear-gradient(135deg, rgba(0, 0, 0, 0.95) 60%, rgba(36, 40, 48, 0.25) 100%); +} + +.support-us-content { + text-align: center; + padding: 32px 24px; +} + +.support-icon { + margin-bottom: 24px; +} + +.support-icon .fa-heart { + font-size: 48px; + color: #ff6b6b; +} + +.heartbeat { + animation: heartbeat 1.5s ease-in-out infinite; +} + +@keyframes heartbeat { + 0%, + 100% { + transform: scale(1); + } + 10%, + 30% { + transform: scale(1.1); + } + 20%, + 40% { + transform: scale(1); + } +} + +.support-options { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 20px; + max-width: 900px; + margin: 0 auto; +} + +.support-card { + display: flex; + flex-direction: column; + align-items: center; + padding: 28px 20px; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 12px; + text-decoration: none; + color: inherit; + transition: all 0.3s ease; + min-height: 160px; +} + +.support-card:hover { + background: rgba(255, 255, 255, 0.08); + border-color: rgba(255, 255, 255, 0.2); + transform: translateY(-4px); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3); +} + +.support-card-icon svg { + filter: brightness(0) invert(1); +} + +.support-card-icon { + margin-bottom: 12px; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.08); + border-radius: 50%; + transition: all 0.3s ease; +} + +.support-card:hover .support-card-icon { + background: rgba(255, 255, 255, 0.15); + transform: scale(1.1); +} + +.support-card-title-small { + margin: 0 0 8px 0; + font-size: 18px; + font-weight: 600; + color: #fff; + text-align: center; +} + +.support-card-description-small { + margin: 0; + font-size: 13px; + color: rgba(255, 255, 255, 0.7); + text-align: center; + line-height: 1.5; +} + +.support-footer { + margin-top: 32px; + padding-top: 24px; + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +@media (max-width: 768px) { + .support-options { + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } +} + +@media (max-width: 480px) { + .support-options { + grid-template-columns: 1fr; + gap: 16px; + } + + .support-icon .fa-heart { + font-size: 36px; + } + + .support-us-content { + padding: 24px 16px; + } + + .support-card { + padding: 24px 16px; + min-height: 140px; + } +} diff --git a/public/js/Brand.js b/public/js/Brand.js index 827dc789..1701875d 100644 --- a/public/js/Brand.js +++ b/public/js/Brand.js @@ -67,6 +67,7 @@ let BRAND = { poweredBy: true, sponsors: true, advertisers: true, + supportUs: true, footer: true, }, whoAreYou: { @@ -191,10 +192,21 @@ async function getBrand() { // BRAND configurations function setBrand(data) { - BRAND = data; + BRAND = mergeBrand(BRAND, data); console.log('Set Brand done'); } +function mergeBrand(current, updated) { + for (const key of Object.keys(updated)) { + if (!current.hasOwnProperty(key) || typeof updated[key] !== 'object') { + current[key] = updated[key]; + } else { + mergeBrand(current[key], updated[key]); + } + } + return current; +} + // BRAND check function checkBrand() { !BRAND.html.topSponsors && elementDisplay(topSponsors, false); @@ -204,6 +216,7 @@ function checkBrand() { !BRAND.html.poweredBy && elementDisplay(poweredBy, false); !BRAND.html.sponsors && elementDisplay(sponsors, false); !BRAND.html.advertisers && elementDisplay(advertisers, false); + !BRAND.html.supportUs && elementDisplay(supportUs, false); !BRAND.html.footer && elementDisplay(footer, false); } diff --git a/public/views/landing.html b/public/views/landing.html index 1a295812..44db12ef 100644 --- a/public/views/landing.html +++ b/public/views/landing.html @@ -675,6 +675,106 @@ + +
+
+
+
+
+ +
+

Support MiroTalk SFU

+

+ MiroTalk SFU is a free, open-source project under AGPLv3 license. Your support helps + us maintain servers, add new features, and keep the service free for everyone. Every + contribution matters! +

+ + + + + +
+
+
+