Browse Source

feat(calls): Allow to provide branded talk-backgrounds via themes

Signed-off-by: Joas Schilling <coding@schilljs.com>
pull/14987/head
Joas Schilling 6 months ago
committed by backportbot[bot]
parent
commit
522168a2c9
  1. 1
      docs/capabilities.md
  2. 3
      docs/settings.md
  3. 93
      lib/Capabilities.php
  4. 3
      lib/ResponseDefinitions.php
  5. 3
      src/__mocks__/capabilities.ts
  6. 5
      src/components/MediaSettings/VideoBackgroundEditor.vue
  7. 27
      tests/php/CapabilitiesTest.php

1
docs/capabilities.md

@ -182,3 +182,4 @@
## 21.1 ## 21.1
* `conversation-creation-all` - Whether the conversation creation endpoint allows to specify all attributes of a conversation * `conversation-creation-all` - Whether the conversation creation endpoint allows to specify all attributes of a conversation
* `important-conversations` (local) - Whether important conversations are supported * `important-conversations` (local) - Whether important conversations are supported
* `config => call => predefined-backgrounds-v2` (local) - Whether virtual backgrounds should be read from the theming directory

3
docs/settings.md

@ -122,3 +122,6 @@ Legend:
| `call_end_to_end_encryption` | string<br>`1` or `0` | `0` | No | 🖌️ | Whether clients should end-to-end encrypt streams in calls (Only supported with High-performance backend) | | `call_end_to_end_encryption` | string<br>`1` or `0` | `0` | No | 🖌️ | Whether clients should end-to-end encrypt streams in calls (Only supported with High-performance backend) |
| `inactivity_lock_after_days` | int | `0` | No | | A duration (in days) after which rooms are locked. Calculated from the last activity in the room. | | `inactivity_lock_after_days` | int | `0` | No | | A duration (in days) after which rooms are locked. Calculated from the last activity in the room. |
| `inactivity_enable_lobby` | string<br>`1` or `0` | `0` | No | | Additionally enable the lobby for inactive rooms so they can only be read by moderators. | | `inactivity_enable_lobby` | string<br>`1` or `0` | `0` | No | | Additionally enable the lobby for inactive rooms so they can only be read by moderators. |
| `backgrounds_branded_for_guests` | string<br>`1` or `0` | `0` | No | | Whether guests are allowed to use the virtual backgrounds provided via `themes/talk-backgrounds/` |
| `backgrounds_default_for_users` | string<br>`1` or `0` | `1` | No | | Whether users are allowed to use the default virtual backgrounds provided by the releases |
| `backgrounds_upload_users` | string<br>`1` or `0` | `1` | No | | Whether users are allowed to upload custom virtual backgrounds and choose from their Nextcloud Files |

93
lib/Capabilities.php

@ -149,6 +149,7 @@ class Capabilities implements IPublicCapability {
], ],
'call' => [ 'call' => [
'predefined-backgrounds', 'predefined-backgrounds',
'predefined-backgrounds-v2',
'can-upload-background', 'can-upload-background',
'start-without-media', 'start-without-media',
'blur-virtual-background', 'blur-virtual-background',
@ -222,6 +223,7 @@ class Capabilities implements IPublicCapability {
'recording-consent' => $this->talkConfig->recordingConsentRequired(), 'recording-consent' => $this->talkConfig->recordingConsentRequired(),
'supported-reactions' => ['❤️', '🎉', '👏', '👋', '👍', '👎', '🔥', '😂', '🤩', '🤔', '😲', '😥'], 'supported-reactions' => ['❤️', '🎉', '👏', '👋', '👍', '👎', '🔥', '😂', '🤩', '🤔', '😲', '😥'],
// 'predefined-backgrounds' => list<string>, // 'predefined-backgrounds' => list<string>,
// 'predefined-backgrounds-v2' => list<string>,
'can-upload-background' => false, 'can-upload-background' => false,
'sip-enabled' => $this->talkConfig->isSIPConfigured(), 'sip-enabled' => $this->talkConfig->isSIPConfigured(),
'sip-dialout-enabled' => $this->talkConfig->isSIPDialOutEnabled(), 'sip-dialout-enabled' => $this->talkConfig->isSIPDialOutEnabled(),
@ -292,9 +294,63 @@ class Capabilities implements IPublicCapability {
$capabilities['config']['signaling']['hello-v2-token-key'] = $pubKey; $capabilities['config']['signaling']['hello-v2-token-key'] = $pubKey;
} }
$includeBrandedBackgrounds = $user instanceof IUser || $this->appConfig->getAppValueBool('backgrounds_branded_for_guests');
$includeDefaultBackgrounds = !$user instanceof IUser || $this->appConfig->getAppValueBool('backgrounds_default_for_users', true);
$predefinedBackgrounds = [];
$defaultBackgrounds = $this->getBackgroundsFromDirectory(__DIR__ . '/../img/backgrounds', '_default');
if ($includeBrandedBackgrounds) {
$predefinedBackgrounds = $this->getBackgroundsFromDirectory(\OC::$SERVERROOT . '/themes/talk-backgrounds', '_branded');
$predefinedBackgrounds = array_map(static fn ($fileName) => '/themes/talk-backgrounds/' . $fileName, $predefinedBackgrounds);
}
if ($includeDefaultBackgrounds) {
$spreedWebPath = $this->appManager->getAppWebPath('spreed');
$prefixedDefaultBackgrounds = array_map(static fn ($fileName) => $spreedWebPath . '/img/backgrounds/' . $fileName, $defaultBackgrounds);
$predefinedBackgrounds = array_merge($predefinedBackgrounds, $prefixedDefaultBackgrounds);
}
$capabilities['config']['call']['predefined-backgrounds'] = $defaultBackgrounds;
$capabilities['config']['call']['predefined-backgrounds-v2'] = array_values($predefinedBackgrounds);
if ($user instanceof IUser) {
$userAllowedToUpload = $this->appConfig->getAppValueBool('backgrounds_upload_users', true);
if ($userAllowedToUpload) {
$quota = $user->getQuota();
if ($quota !== 'none') {
$quota = Util::computerFileSize($quota);
}
$capabilities['config']['call']['can-upload-background'] = $quota === 'none' || $quota > 0;
}
$capabilities['config']['call']['can-enable-sip'] = $this->talkConfig->canUserEnableSIP($user);
}
$supportedTaskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
if (isset($supportedTaskTypes[TextToTextSummary::ID])) {
$capabilities['features'][] = 'chat-summary-api';
}
if (isset($supportedTaskTypes[TextToTextTranslate::ID])) {
$capabilities['config']['chat']['has-translation-task-providers'] = true;
}
if ($this->talkConfig->getSignalingMode() === Config::SIGNALING_EXTERNAL) {
$capabilities['features'][] = 'call-end-to-end-encryption';
}
return [
'spreed' => $capabilities,
];
}
/**
* @return list<string>
*/
protected function getBackgroundsFromDirectory(string $directory, string $cacheSuffix): array {
$cacheKey = 'predefined_backgrounds' . $cacheSuffix;
/** @var ?list<string> $predefinedBackgrounds */ /** @var ?list<string> $predefinedBackgrounds */
$predefinedBackgrounds = null; $predefinedBackgrounds = null;
$cachedPredefinedBackgrounds = $this->talkCache->get('predefined_backgrounds');
$cachedPredefinedBackgrounds = $this->talkCache->get($cacheKey);
if ($cachedPredefinedBackgrounds !== null) { if ($cachedPredefinedBackgrounds !== null) {
// Try using cached value // Try using cached value
/** @var list<string>|null $predefinedBackgrounds */ /** @var list<string>|null $predefinedBackgrounds */
@ -302,11 +358,8 @@ class Capabilities implements IPublicCapability {
} }
if (!is_array($predefinedBackgrounds)) { if (!is_array($predefinedBackgrounds)) {
// Cache was empty or invalid, regenerate
/** @var list<string> $predefinedBackgrounds */
$predefinedBackgrounds = [];
if (file_exists(__DIR__ . '/../img/backgrounds')) {
$directoryIterator = new \DirectoryIterator(__DIR__ . '/../img/backgrounds');
if (file_exists($directory) && is_dir($directory)) {
$directoryIterator = new \DirectoryIterator($directory);
foreach ($directoryIterator as $file) { foreach ($directoryIterator as $file) {
if (!$file->isFile()) { if (!$file->isFile()) {
continue; continue;
@ -322,33 +375,9 @@ class Capabilities implements IPublicCapability {
sort($predefinedBackgrounds); sort($predefinedBackgrounds);
} }
$this->talkCache->set('predefined_backgrounds', json_encode($predefinedBackgrounds), 300);
}
$capabilities['config']['call']['predefined-backgrounds'] = $predefinedBackgrounds;
if ($user instanceof IUser) {
$quota = $user->getQuota();
if ($quota !== 'none') {
$quota = Util::computerFileSize($quota);
}
$capabilities['config']['call']['can-upload-background'] = $quota === 'none' || $quota > 0;
$capabilities['config']['call']['can-enable-sip'] = $this->talkConfig->canUserEnableSIP($user);
}
$supportedTaskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
if (isset($supportedTaskTypes[TextToTextSummary::ID])) {
$capabilities['features'][] = 'chat-summary-api';
}
if (isset($supportedTaskTypes[TextToTextTranslate::ID])) {
$capabilities['config']['chat']['has-translation-task-providers'] = true;
$this->talkCache->set($cacheKey, json_encode($predefinedBackgrounds), 300);
} }
if ($this->talkConfig->getSignalingMode() === Config::SIGNALING_EXTERNAL) {
$capabilities['features'][] = 'call-end-to-end-encryption';
}
return [
'spreed' => $capabilities,
];
return $predefinedBackgrounds ?? [];
} }
} }

3
lib/ResponseDefinitions.php

@ -354,7 +354,10 @@ namespace OCA\Talk;
* recording: bool, * recording: bool,
* recording-consent: int, * recording-consent: int,
* supported-reactions: list<string>, * supported-reactions: list<string>,
* // List of file names relative to the spreed/img/backgrounds/ web path, e.g. `2_home.jpg`
* predefined-backgrounds: list<string>, * predefined-backgrounds: list<string>,
* // List of file paths relative to the server web root with leading slash, e.g. `/apps/spreed/img/backgrounds/2_home.jpg`
* predefined-backgrounds-v2: list<string>,
* can-upload-background: bool, * can-upload-background: bool,
* sip-enabled: bool, * sip-enabled: bool,
* sip-dialout-enabled: bool, * sip-dialout-enabled: bool,

3
src/__mocks__/capabilities.ts

@ -125,7 +125,8 @@ export const mockedCapabilities: Capabilities = {
recording: true, recording: true,
'recording-consent': 0, 'recording-consent': 0,
'supported-reactions': ['❤️', '🎉', '👏', '👍', '👎', '😂', '🤩', '🤔', '😲', '😥'], 'supported-reactions': ['❤️', '🎉', '👏', '👍', '👎', '😂', '🤩', '🤔', '😲', '😥'],
'predefined-backgrounds': ['1_office', '2_home', '3_abstract'],
'predefined-backgrounds': ['1_office.jpg', '2_home.jpg', '3_abstract.jpg'],
'predefined-backgrounds-v2': ['/apps/spreed/img/backgrounds/1_office.jpg', '/apps/spreed/img/backgrounds/2_home.jpg', '/apps/spreed/img/backgrounds/3_abstract.jpg'],
'can-upload-background': true, 'can-upload-background': true,
'sip-enabled': true, 'sip-enabled': true,
'sip-dialout-enabled': true, 'sip-dialout-enabled': true,

5
src/components/MediaSettings/VideoBackgroundEditor.vue

@ -131,6 +131,7 @@ export default {
return { return {
canUploadBackgrounds: getTalkConfig('local', 'call', 'can-upload-background'), canUploadBackgrounds: getTalkConfig('local', 'call', 'can-upload-background'),
predefinedBackgrounds: getTalkConfig('local', 'call', 'predefined-backgrounds'), predefinedBackgrounds: getTalkConfig('local', 'call', 'predefined-backgrounds'),
predefinedBackgroundsV2: getTalkConfig('local', 'call', 'predefined-backgrounds-v2'),
settingsStore: useSettingsStore(), settingsStore: useSettingsStore(),
} }
}, },
@ -150,6 +151,10 @@ export default {
}, },
predefinedBackgroundsURLs() { predefinedBackgroundsURLs() {
if (this.predefinedBackgroundsV2) {
return this.predefinedBackgroundsV2
}
return this.predefinedBackgrounds.map(fileName => { return this.predefinedBackgrounds.map(fileName => {
return imagePath('spreed', 'backgrounds/' + fileName) return imagePath('spreed', 'backgrounds/' + fileName)
}) })

27
tests/php/CapabilitiesTest.php

@ -147,6 +147,16 @@ class CapabilitiesTest extends TestCase {
'7_library.jpg', '7_library.jpg',
'8_space_station.jpg', '8_space_station.jpg',
], ],
'predefined-backgrounds-v2' => [
'/img/backgrounds/1_office.jpg',
'/img/backgrounds/2_home.jpg',
'/img/backgrounds/3_abstract.jpg',
'/img/backgrounds/4_beach.jpg',
'/img/backgrounds/5_park.jpg',
'/img/backgrounds/6_theater.jpg',
'/img/backgrounds/7_library.jpg',
'/img/backgrounds/8_space_station.jpg',
],
], ],
'chat' => [ 'chat' => [
'max-length' => 32000, 'max-length' => 32000,
@ -246,6 +256,13 @@ class CapabilitiesTest extends TestCase {
['core', 'backgroundjobs_mode', 'ajax', 'cron'], ['core', 'backgroundjobs_mode', 'ajax', 'cron'],
]); ]);
$this->appConfig->expects($this->any())
->method('getAppValueBool')
->willReturnMap([
['backgrounds_default_for_users', true, true],
['backgrounds_upload_users', true, true],
]);
$this->assertInstanceOf(IPublicCapability::class, $capabilities); $this->assertInstanceOf(IPublicCapability::class, $capabilities);
$data = $capabilities->getCapabilities(); $data = $capabilities->getCapabilities();
$this->assertSame([ $this->assertSame([
@ -287,6 +304,16 @@ class CapabilitiesTest extends TestCase {
'7_library.jpg', '7_library.jpg',
'8_space_station.jpg', '8_space_station.jpg',
], ],
'predefined-backgrounds-v2' => [
'/img/backgrounds/1_office.jpg',
'/img/backgrounds/2_home.jpg',
'/img/backgrounds/3_abstract.jpg',
'/img/backgrounds/4_beach.jpg',
'/img/backgrounds/5_park.jpg',
'/img/backgrounds/6_theater.jpg',
'/img/backgrounds/7_library.jpg',
'/img/backgrounds/8_space_station.jpg',
],
], ],
'chat' => [ 'chat' => [
'max-length' => 32000, 'max-length' => 32000,

Loading…
Cancel
Save