[web] feature -> new installation option 'allow protected content'

This commit is contained in:
Vinicius Moreira
2020-12-07 18:18:38 -03:00
parent 358d704149
commit 8d761c35e9
19 changed files with 127 additions and 51 deletions

View File

@@ -4,6 +4,31 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.9.10]
### Features
- Web
- allowing generated apps to interact with protected/encrypted content (DRM) through a new installation option:
<p align="center">
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.10/widevine.png">
</p>
- this new installation option uses an alternative Electron implementation provided by [castLabs](https://github.com/castlabs/electron-releases).
- **nativefier** handles the switch between the official Electron and the custom provided by castLabs.
### Improvements
- Web
- upgraded the default environment tools (settings are now retrieved from this new [URL](https://github.com/vinifmor/bauh-files/blob/master/web/env/v1/environment.yml)):
```
- nodejs: 12.18.0 -> 14.15.1
- nativefier: 7.7.1 -> 42.0.1
- electron: 5.0.13 -> 11.0.3
```
### Fixes
- Web:
- installation options window size
## [0.9.9] 2020-12-02
### Features
- Themes (stylesheets)

View File

@@ -215,7 +215,7 @@ suggest_optdep_uninstall: false # if the optional dependencies associated with
- **git**: allows to retrieve packages release history and downgrading
- **aria2** or **axel**: provides faster, multi-threaded downloads for required source files
#### Native Web Applications ( web )
#### Native Web Applications (web)
- It allows the installation of native Web applications by typing their addresses/URLs on the search bar
<p align="center">
@@ -231,7 +231,7 @@ suggest_optdep_uninstall: false # if the optional dependencies associated with
- It provides some suggestions coming with predefined settings, and they also can be retrieved by their names. They are
defined at [suggestions.yml](https://github.com/vinifmor/bauh-files/blob/master/web/suggestions.yml), and downloaded during the application usage.
defined at [suggestions.yml](https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/env/v1/suggestions.yml), and downloaded during the application usage.
<p align="center">
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/web/suggestions.gif">
@@ -240,7 +240,8 @@ defined at [suggestions.yml](https://github.com/vinifmor/bauh-files/blob/master/
- It relies on [NodeJS](https://nodejs.org/en/), [Electron](https://electronjs.org/) and [nativefier](https://github.com/jiahaog/nativefier) to do all the magic, but you do not need them installed on your system. An isolated installation environment
will be generated at **~/.local/share/bauh/web/env**.
- The isolated environment is created based on the settings defined in [environment.yml](https://github.com/vinifmor/bauh-files/blob/master/web/environment.yml)
- It supports DRM protected content through a custom Electron implementation provided by [castLabs](https://github.com/castlabs/electron-releases). nativefier handles the switch between the official Electron and the custom.
- The isolated environment is created based on the settings defined in [environment.yml](https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/env/v1/environment.yml)
(downloaded during runtime).
- Some applications require Javascript fixes to properly work. If there is a known fix, bauh will download the file from [fix](https://github.com/vinifmor/bauh-files/tree/master/web/fix) and
attach it to the generated app.

View File

@@ -1,4 +1,4 @@
__version__ = '0.9.9'
__version__ = '0.9.10'
__app_name__ = 'bauh'
import os

View File

@@ -106,7 +106,7 @@ class SoftwareManager(ABC):
pass
@abstractmethod
def read_installed(self, disk_loader: DiskCacheLoader, limit: int, only_apps: bool, pkg_types: Set[Type[SoftwarePackage]], internet_available: bool) -> SearchResult:
def read_installed(self, disk_loader: Optional[DiskCacheLoader], limit: int, only_apps: bool, pkg_types: Set[Type[SoftwarePackage]], internet_available: bool) -> SearchResult:
"""
:param disk_loader: a running disk loader thread that loads application data from the disk asynchronously
:param limit: the max number of packages to be retrieved. <= 1 should retrieve everything
@@ -234,7 +234,7 @@ class SoftwareManager(ABC):
if pkg.supports_disk_cache():
self.serialize_to_disk(pkg, icon_bytes, only_icon)
def serialize_to_disk(self, pkg: SoftwarePackage, icon_bytes: bytes, only_icon: bool):
def serialize_to_disk(self, pkg: SoftwarePackage, icon_bytes: Optional[bytes], only_icon: bool):
"""
Sames as above, but does not check if disk cache is enabled or supported by the package instance
:param pkg:

View File

@@ -1,4 +1,4 @@
from typing import List, Tuple
from typing import List, Tuple, Optional
from bauh.api.abstract.view import MessageType, ViewComponent
@@ -17,7 +17,7 @@ class ProcessWatcher:
"""
pass
def request_confirmation(self, title: str, body: str, components: List[ViewComponent] = None, confirmation_label: str = None,
def request_confirmation(self, title: str, body: Optional[str], components: List[ViewComponent] = None, confirmation_label: str = None,
deny_label: str = None, deny_button: bool = True, window_cancel: bool = False,
confirmation_button: bool = True) -> bool:
"""
@@ -95,11 +95,11 @@ class TaskManager:
"""
pass
def update_progress(self, task_id: str, progress: float, substatus: str):
def update_progress(self, task_id: str, progress: float, substatus: Optional[str]):
"""
:param task_id:
:param progress: a float between 0 and 100.
:param substatus: a substatus string representing the current state
:param substatus: optional substatus string representing the current state
:return:
"""
pass

View File

@@ -108,7 +108,7 @@ class SingleSelectComponent(InputViewComponent):
class MultipleSelectComponent(InputViewComponent):
def __init__(self, label: str, options: List[InputOption], default_options: Set[InputOption] = None,
def __init__(self, label: Optional[str], options: List[InputOption], default_options: Set[InputOption] = None,
max_per_line: int = 1, tooltip: str = None, spaces: bool = True, max_width: int = -1,
max_height: int = -1, id_: str = None):
super(MultipleSelectComponent, self).__init__(id_=id_)

View File

@@ -18,10 +18,12 @@ NATIVEFIER_BIN_PATH = '{}/.bin/nativefier'.format(NODE_MODULES_PATH)
ELECTRON_PATH = '{}/.cache/electron'.format(str(Path.home()))
ELECTRON_DOWNLOAD_URL = 'https://github.com/electron/electron/releases/download/v{version}/electron-v{version}-linux-{arch}.zip'
ELECTRON_SHA256_URL = 'https://github.com/electron/electron/releases/download/v{version}/SHASUMS256.txt'
URL_ENVIRONMENT_SETTINGS = 'https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/environment.yml'
ELECTRON_WIDEVINE_URL = 'https://github.com/castlabs/electron-releases/releases/download/v{version}-wvvmp/electron-v{version}-wvvmp-linux-{arch}.zip'
ELECTRON_WIDEVINE_SHA256_URL = 'https://github.com/castlabs/electron-releases/releases/download/v{version}-wvvmp/SHASUMS256.txt'
URL_ENVIRONMENT_SETTINGS = 'https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/env/v1/environment.yml'
DESKTOP_ENTRY_PATH_PATTERN = DESKTOP_ENTRIES_DIR + '/bauh.web.{name}.desktop'
URL_FIX_PATTERN = "https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/fix/{url}.js"
URL_SUGGESTIONS = "https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/suggestions.yml"
URL_SUGGESTIONS = "https://raw.githubusercontent.com/vinifmor/bauh-files/master/web/env/v1/suggestions.yml"
UA_CHROME = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
TEMP_PATH = '{}/web'.format(TEMP_DIR)
SEARCH_INDEX_FILE = '{}/index.yml'.format(TEMP_PATH)

View File

@@ -461,7 +461,7 @@ class WebApplicationManager(SoftwareManager):
break
inp_cat = SingleSelectComponent(label=self.i18n['category'], type_=SelectViewType.COMBO, options=cat_ops, default_option=def_cat)
op_wv = InputOption(id_='widevine', label=self.i18n['web.install.option.widevine.label'] + ' (DRM)', value="--widevine", tooltip=self.i18n['web.install.option.widevine.tip'])
tray_op_off = InputOption(id_='tray_off', label=self.i18n['web.install.option.tray.off.label'], value=0, tooltip=self.i18n['web.install.option.tray.off.tip'])
tray_op_default = InputOption(id_='tray_def', label=self.i18n['web.install.option.tray.default.label'], value='--tray', tooltip=self.i18n['web.install.option.tray.default.tip'])
tray_op_min = InputOption(id_='tray_min', label=self.i18n['web.install.option.tray.min.label'], value='--tray=start-in-tray', tooltip=self.i18n['web.install.option.tray.min.tip'])
@@ -503,7 +503,7 @@ class WebApplicationManager(SoftwareManager):
op_insecure = InputOption(id_='insecure', label=self.i18n['web.install.option.insecure.label'], value="--insecure", tooltip=self.i18n['web.install.option.insecure.tip'])
op_igcert = InputOption(id_='ignore_certs', label=self.i18n['web.install.option.ignore_certificate.label'], value="--ignore-certificate", tooltip=self.i18n['web.install.option.ignore_certificate.tip'])
adv_opts = [op_single, op_allow_urls, op_max, op_fs, op_nframe, op_ncache, op_insecure, op_igcert]
adv_opts = [op_single, op_allow_urls, op_wv, op_max, op_fs, op_nframe, op_ncache, op_insecure, op_igcert]
def_adv_opts = {op_single, op_allow_urls}
if app.preset_options:
@@ -621,6 +621,7 @@ class WebApplicationManager(SoftwareManager):
def install(self, pkg: WebApplication, root_password: str, disk_loader: DiskCacheLoader, watcher: ProcessWatcher) -> TransactionResult:
continue_install, install_options = self._ask_install_options(pkg, watcher)
widevine_support = '--widevine' in install_options
if not continue_install:
return TransactionResult(success=False, installed=[], removed=[])
@@ -637,7 +638,9 @@ class WebApplicationManager(SoftwareManager):
type_=MessageType.ERROR)
return TransactionResult(success=False, installed=[], removed=[])
env_components = self.env_updater.check_environment(app=pkg, local_config=local_config, env=env_settings, is_x86_x64_arch=self.context.is_system_x86_64())
env_components = self.env_updater.check_environment(app=pkg, local_config=local_config, env=env_settings,
is_x86_x64_arch=self.context.is_system_x86_64(),
widevine=widevine_support)
comps_to_update = [c for c in env_components if c.update]
@@ -690,7 +693,7 @@ class WebApplicationManager(SoftwareManager):
electron_version = str(next((c for c in env_components if c.id == 'electron')).version)
installed = handler.handle_simple(nativefier.install(url=pkg.url, name=app_id, output_dir=app_dir,
electron_version=electron_version,
electron_version=electron_version if not widevine_support else None,
system=bool(local_config['environment']['system']),
cwd=INSTALLED_PATH,
extra_options=install_options))

View File

@@ -1,3 +1,4 @@
import glob
import logging
import os
import shutil
@@ -5,7 +6,7 @@ import tarfile
import traceback
from pathlib import Path
from threading import Thread
from typing import Dict, List
from typing import Dict, List, Optional
import requests
import yaml
@@ -19,20 +20,21 @@ from bauh.commons.html import bold
from bauh.commons.system import SimpleProcess, ProcessHandler
from bauh.gems.web import ENV_PATH, NODE_DIR_PATH, NODE_BIN_PATH, NODE_MODULES_PATH, NATIVEFIER_BIN_PATH, \
ELECTRON_PATH, ELECTRON_DOWNLOAD_URL, ELECTRON_SHA256_URL, URL_ENVIRONMENT_SETTINGS, NPM_BIN_PATH, NODE_PATHS, \
nativefier, URL_NATIVEFIER, get_icon_path
nativefier, URL_NATIVEFIER, get_icon_path, ELECTRON_WIDEVINE_URL, ELECTRON_WIDEVINE_SHA256_URL
from bauh.gems.web.model import WebApplication
from bauh.view.util.translation import I18n
class EnvironmentComponent:
def __init__(self, id: str, name: str, size: str, version: str, url: str, update: bool = False):
def __init__(self, id: str, name: str, size: str, version: str, url: str, update: bool = False, properties: Optional[dict] = None):
self.id = id
self.name = name
self.size = size
self.version = version
self.url = url
self.update = update
self.properties = properties
class EnvironmentUpdater:
@@ -186,10 +188,11 @@ class EnvironmentUpdater:
def _is_nativefier_installed(self) -> bool:
return os.path.exists(NATIVEFIER_BIN_PATH)
def download_electron(self, version: str, url: str, watcher: ProcessWatcher) -> bool:
def download_electron(self, version: str, url: str, widevine: bool, watcher: ProcessWatcher) -> bool:
Path(ELECTRON_PATH).mkdir(parents=True, exist_ok=True)
self.logger.info("Downloading Electron {}".format(version))
electron_path = '{}/{}'.format(ELECTRON_PATH, url.split('/')[-1])
electron_path = self._get_electron_file_path(url=url, relative=False)
if not self.http_client.exists(url):
self.logger.warning("The file {} seems not to exist".format(url))
@@ -200,9 +203,10 @@ class EnvironmentUpdater:
return self.file_downloader.download(file_url=url, watcher=watcher, output_path=electron_path, cwd=ELECTRON_PATH)
def download_electron_sha256(self, version: str, url: str, watcher: ProcessWatcher) -> bool:
def download_electron_sha256(self, version: str, url: str, widevine: bool, watcher: ProcessWatcher) -> bool:
self.logger.info("Downloading Electron {} sha526".format(version))
sha256_path = '{}/{}'.format(ELECTRON_PATH, url.split('/')[-1]) + '-{}'.format(version)
sha256_path = self._get_electron_file_path(url=url, relative=False)
if not self.http_client.exists(url):
self.logger.warning("The file {} seems not to exist".format(url))
@@ -213,27 +217,44 @@ class EnvironmentUpdater:
return self.file_downloader.download(file_url=url, watcher=watcher, output_path=sha256_path, cwd=ELECTRON_PATH)
def _get_electron_url(self, version: str, is_x86_x64_arch: bool) -> str:
return ELECTRON_DOWNLOAD_URL.format(version=version, arch='x64' if is_x86_x64_arch else 'ia32')
def _get_electron_url(self, version: str, is_x86_x64_arch: bool, widevine: bool) -> str:
arch = 'x64' if is_x86_x64_arch else 'ia32'
if widevine:
return ELECTRON_WIDEVINE_URL.format(version=version, arch=arch)
else:
return ELECTRON_DOWNLOAD_URL.format(version=version, arch=arch)
def check_electron_installed(self, version: str, is_x86_x64_arch: bool) -> Dict[str, bool]:
self.logger.info("Checking if Electron {} is installed".format(version))
def _get_electron_sha256_url(self, version: str, widevine: bool) -> str:
if widevine:
return ELECTRON_WIDEVINE_SHA256_URL.format(version=version)
else:
return ELECTRON_SHA256_URL.format(version=version)
def _get_electron_file_path(self, url: str, relative: bool) -> str:
file_path = url.replace(':', '').replace('/', '') + '/' + url.split('/')[-1]
return '{}/{}'.format(ELECTRON_PATH, file_path) if not relative else file_path
def check_electron_installed(self, version: str, is_x86_x64_arch: bool, widevine: bool) -> Dict[str, bool]:
self.logger.info("Checking if Electron {} (widevine={}) is installed".format(version, widevine))
res = {'electron': False, 'sha256': False}
if not os.path.exists(ELECTRON_PATH):
self.logger.info("The Electron folder {} was not found".format(ELECTRON_PATH))
else:
files = os.listdir(ELECTRON_PATH)
files = {f.split(ELECTRON_PATH + '/')[1] for f in glob.glob(ELECTRON_PATH + '/**', recursive=True) if os.path.isfile(f)}
if files:
file_name = self._get_electron_url(version, is_x86_x64_arch).split('/')[-1]
res['electron'] = bool([f for f in files if f == file_name])
electron_url = self._get_electron_url(version, is_x86_x64_arch, widevine)
file_path = self._get_electron_file_path(url=electron_url, relative=True)
res['electron'] = file_path in files
if not res['electron']:
res['sha256'] = True
else:
file_name = ELECTRON_SHA256_URL.split('/')[-1] + '-{}'.format(version)
res['sha256'] = bool([f for f in files if f == file_name])
sha_url = self._get_electron_sha256_url(version=version, widevine=widevine)
sha_path = self._get_electron_file_path(url=sha_url, relative=True)
res['sha256'] = sha_path in files
else:
self.logger.info('No Electron file found in {}'.format(ELECTRON_PATH))
@@ -248,7 +269,7 @@ class EnvironmentUpdater:
task_man.update_progress('web_down_sets', 100, None)
task_man.finish_task('web_down_sets')
def read_settings(self, task_man: TaskManager = None) -> dict:
def read_settings(self, task_man: TaskManager = None) -> Optional[dict]:
try:
if task_man:
task_man.register_task('web_down_sets', self.i18n['web.task.download_settings'], get_icon_path())
@@ -272,34 +293,37 @@ class EnvironmentUpdater:
self._finish_task_download_settings(task_man)
return
def _check_and_fill_electron(self, pkg: WebApplication, env: dict, local_config: dict, x86_x64: bool, output: List[EnvironmentComponent]):
electron_version = env['electron']['version']
def _check_and_fill_electron(self, pkg: WebApplication, env: dict, local_config: dict, x86_x64: bool, widevine: bool, output: List[EnvironmentComponent]):
electron_version = env['electron-wvvmp' if widevine else 'electron']['version']
if pkg.version and pkg.version != electron_version:
if not widevine and pkg.version and pkg.version != electron_version: # this feature does not support custom widevine electron at the moment
self.logger.info('A preset Electron version is defined for {}: {}'.format(pkg.url, pkg.version))
electron_version = pkg.version
if local_config['environment']['electron']['version']:
if not widevine and local_config['environment']['electron']['version']:
self.logger.warning("A custom Electron version will be used {} to install {}".format(electron_version, pkg.url))
electron_version = local_config['environment']['electron']['version']
electron_status = self.check_electron_installed(version=electron_version, is_x86_x64_arch=x86_x64)
electron_status = self.check_electron_installed(version=electron_version, is_x86_x64_arch=x86_x64, widevine=widevine)
electron_url = self._get_electron_url(version=electron_version, is_x86_x64_arch=x86_x64)
electron_url = self._get_electron_url(version=electron_version, is_x86_x64_arch=x86_x64, widevine=widevine)
output.append(EnvironmentComponent(name=electron_url.split('/')[-1],
version=electron_version,
url=electron_url,
size=self.http_client.get_content_length(electron_url),
id='electron',
update=not electron_status['electron']))
update=not electron_status['electron'],
properties={'widevine': widevine}))
sha_url = self._get_electron_sha256_url(version=electron_version, widevine=widevine)
sha_url = ELECTRON_SHA256_URL.format(version=electron_version)
output.append(EnvironmentComponent(name=sha_url.split('/')[-1],
version=electron_version,
url=sha_url,
size=self.http_client.get_content_length(sha_url),
id='electron_sha256',
update=not electron_status['electron'] or not electron_status['sha256']))
update=not electron_status['electron'] or not electron_status['sha256'],
properties={'widevine': widevine}))
def _check_and_fill_node(self, env: dict, output: List[EnvironmentComponent]):
node = EnvironmentComponent(name=env['nodejs']['url'].split('/')[-1],
@@ -348,7 +372,8 @@ class EnvironmentUpdater:
version=nativefier_settings['version'],
id='nativefier')
def check_environment(self, env: dict, local_config: dict, app: WebApplication, is_x86_x64_arch: bool) -> List[EnvironmentComponent]:
def check_environment(self, env: dict, local_config: dict, app: WebApplication,
is_x86_x64_arch: bool, widevine: bool) -> List[EnvironmentComponent]:
"""
:param app:
:param is_x86_x64_arch:
@@ -365,7 +390,7 @@ class EnvironmentUpdater:
node_check.start()
check_threads.append(node_check)
elec_check = Thread(target=self._check_and_fill_electron, args=(app, env, local_config, is_x86_x64_arch, components))
elec_check = Thread(target=self._check_and_fill_electron, args=(app, env, local_config, is_x86_x64_arch, widevine, components))
elec_check.start()
check_threads.append(elec_check)
@@ -396,13 +421,13 @@ class EnvironmentUpdater:
electron_data = comp_map.get('electron')
if electron_data:
if not self.download_electron(version=electron_data.version, url=electron_data.url, watcher=handler.watcher):
if not self.download_electron(version=electron_data.version, url=electron_data.url, watcher=handler.watcher, widevine=electron_data.properties['widevine']):
return False
sha256_data = comp_map.get('electron_sha256')
if sha256_data:
if not self.download_electron_sha256(version=sha256_data.version, url=sha256_data.url, watcher=handler.watcher):
if not self.download_electron_sha256(version=sha256_data.version, url=sha256_data.url, watcher=handler.watcher, widevine=sha256_data.properties['widevine']):
return False
self.logger.info('Environment successfully updated')

View File

@@ -1,11 +1,15 @@
from typing import List
from typing import List, Optional
from bauh.commons.system import SimpleProcess, run_cmd
from bauh.gems.web import NATIVEFIER_BIN_PATH, NODE_PATHS
def install(url: str, name: str, output_dir: str, electron_version: str, cwd: str, system: bool, extra_options: List[str] = None) -> SimpleProcess:
cmd = [NATIVEFIER_BIN_PATH if not system else 'nativefier', url, '--name', name, '-e', electron_version, output_dir]
def install(url: str, name: str, output_dir: str, electron_version: Optional[str], cwd: str, system: bool, extra_options: List[str] = None) -> SimpleProcess:
cmd = [NATIVEFIER_BIN_PATH if not system else 'nativefier', url, '--name', name, output_dir]
if electron_version:
cmd.append('-e')
cmd.append(electron_version)
if extra_options:
cmd.extend(extra_options)

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=The icon will be deducted by {} during the
web.install.option.wicon.displayed.label=Displayed
web.install.option.wicon.displayed.tip=The icon displayed on the table will be used for the installation
web.install.option.wicon.label=Icon
web.install.option.widevine.label=Allow protected content
web.install.option.widevine.tip=It allows the interaction with protected/encrypted content commonly used by streaming services (like videos, music, ...). It uses and alternative Electron version developed by castLabs.
web.install.options.advanced=advanced
web.install.options.basic=basic
web.install.options_dialog.title=Installation options

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=The icon will be deducted by {} during the
web.install.option.wicon.displayed.label=Displayed
web.install.option.wicon.displayed.tip=The icon displayed on the table will be used for the installation
web.install.option.wicon.label=Icon
web.install.option.widevine.label=Allow protected content
web.install.option.widevine.tip=It allows the interaction with protected/encrypted content commonly used by streaming services (like videos, music, ...). It uses and alternative Electron version developed by castLabs.
web.install.options.advanced=advanced
web.install.options.basic=basic
web.install.options_dialog.title=Installation options

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=El {} deducirá el icono durante la instal
web.install.option.wicon.displayed.label=Mostrado
web.install.option.wicon.displayed.tip=El icono mostrado en la tabla será utilizado para la instalación
web.install.option.wicon.label=Icono
web.install.option.widevine.label=Permitir contenido protegido
web.install.option.widevine.tip=Permite la interacción con contenido protegido/encriptado comúnmente utilizado por los servicios de transmisión (como videos, música, ...). Utiliza una versión alternativa de Electron desarrollada por castLabs.
web.install.options.advanced=avanzadas
web.install.options.basic=básicas
web.install.options_dialog.title=Opciones de instalación

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=L'icône sera déduite par {} durant l'ins
web.install.option.wicon.displayed.label=Affichée
web.install.option.wicon.displayed.tip=L'icône affichée sur la table sera utilisée pour l'installation
web.install.option.wicon.label=Icône
web.install.option.widevine.label=Allow protected content
web.install.option.widevine.tip=It allows the interaction with protected/encrypted content commonly used by streaming services (like videos, music, ...). It uses and alternative Electron version developed by castLabs.
web.install.options.advanced=avancée
web.install.options.basic=basique
web.install.options_dialog.title=Options d'installation

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=The icon will be deducted by {} during the
web.install.option.wicon.displayed.label=Displayed
web.install.option.wicon.displayed.tip=The icon displayed on the table will be used for the installation
web.install.option.wicon.label=Icon
web.install.option.widevine.label=Allow protected content
web.install.option.widevine.tip=It allows the interaction with protected/encrypted content commonly used by streaming services (like videos, music, ...). It uses and alternative Electron version developed by castLabs.
web.install.options.advanced=advanced
web.install.options.basic=basic
web.install.options_dialog.title=Installation options

View File

@@ -52,6 +52,8 @@ web.install.option.wicon.deducted.tip=O ícone será deduzido pelo {} durante a
web.install.option.wicon.displayed.label=Exibido
web.install.option.wicon.displayed.tip=O ícone exibido na tabela será utilizado para a instalação
web.install.option.wicon.label=Ícone
web.install.option.widevine.label=Permitir conteúdo protegido
web.install.option.widevine.tip=Permite a interação com conteúdo protegido/criptografado comumente utilizados por serviços de streaming (como videos, música, ...). Utiliza uma versão alternativa do Electron desenvolvida pela castLabs.
web.install.options.advanced=avançadas
web.install.options.basic=básicas
web.install.options_dialog.title=Opções de instalação

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=Значок будет взят из {}
web.install.option.wicon.displayed.label=Отображать
web.install.option.wicon.displayed.tip=Значок, отображаемый на столе, будет использоваться для установки
web.install.option.wicon.label=Значок
web.install.option.widevine.label=Allow protected content
web.install.option.widevine.tip=It allows the interaction with protected/encrypted content commonly used by streaming services (like videos, music, ...). It uses and alternative Electron version developed by castLabs.
web.install.options.advanced=расширенные
web.install.options.basic=базовые
web.install.options_dialog.title=опции установки

View File

@@ -53,6 +53,8 @@ web.install.option.wicon.deducted.tip=Kurulum sırasında simge {} tarafından k
web.install.option.wicon.displayed.label=Görüntülenen
web.install.option.wicon.displayed.tip=Tabloda görüntülenen simge kurulum için kullanılacaktır
web.install.option.wicon.label=Simge
web.install.option.widevine.label=Allow protected content
web.install.option.widevine.tip=It allows the interaction with protected/encrypted content commonly used by streaming services (like videos, music, ...). It uses and alternative Electron version developed by castLabs.
web.install.options.advanced=gelişmiş
web.install.options.basic=basit
web.install.options_dialog.title=Kurulum seçenekleri

View File

@@ -75,6 +75,7 @@ QCustomToolbar QWidget[spacer = "true"] {
}
FormQt {
min-width: 600px;
font-weight: bold;
font-size: 12px;
border-radius: 6px;
@@ -377,4 +378,3 @@ SettingsWindow TabGroupQt#settings {
QMenu QPushButton[current = "true"] {
font-weight: bold;
}