mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 12:35:14 +00:00
LibWebView: Add autoplay settings to about:settings
The idea with the UI here is that it will serve as a generic component for all site settings, such as autoplay, notifications, etc. When the site settings dialog is opened, it is filled with the requested setting data, and messages sent to the browser process are based on the setting. This patch only implements the UI and persisted settings. It does not apply autoplay changes to the WebContent process.
This commit is contained in:
parent
9c9dca4dc8
commit
42691cb80b
6 changed files with 614 additions and 10 deletions
|
@ -80,6 +80,18 @@
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.permission-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.forcibly-enabled {
|
||||
font-size: 14px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
|
@ -87,6 +99,7 @@
|
|||
font-size: 14px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="url"],
|
||||
select {
|
||||
background-color: var(--input-background-color);
|
||||
|
@ -95,14 +108,145 @@
|
|||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
input[type="text"].success,
|
||||
input[type="url"].success {
|
||||
border: 1px solid green;
|
||||
}
|
||||
|
||||
input[type="text"].error,
|
||||
input[type="url"].error {
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
dialog {
|
||||
background-color: var(--card-background-color);
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
|
||||
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
dialog::backdrop {
|
||||
/* FIXME: This doesn't work in Ladybird. */
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
dialog .dialog-header {
|
||||
background-color: var(--card-header-background-color);
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
dialog .dialog-body {
|
||||
height: 450px;
|
||||
|
||||
border-top: 1px solid var(--border-color);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
dialog .dialog-body label {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
dialog .dialog-body hr {
|
||||
height: 1px;
|
||||
background-color: var(--border-color);
|
||||
border: none;
|
||||
|
||||
margin: 8px 4px 10px 4px;
|
||||
}
|
||||
|
||||
dialog .dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
padding: 15px 20px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
dialog .dialog-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
dialog .dialog-close {
|
||||
background: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
|
||||
padding: 0;
|
||||
|
||||
font-size: 22px;
|
||||
opacity: 0.8;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
dialog .dialog-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
dialog .dialog-site-list {
|
||||
outline: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
|
||||
margin: 10px 0;
|
||||
|
||||
font-size: 14px;
|
||||
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
dialog .dialog-site-item {
|
||||
padding: 10px;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
dialog .dialog-site-item:hover {
|
||||
background-color: var(--card-header-background-color);
|
||||
}
|
||||
|
||||
dialog .dialog-site-item-placeholder {
|
||||
padding: 10px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
dialog .dialog-site-item .filter {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
dialog .dialog-add-site {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
margin-top: auto;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
dialog .dialog-add-site input {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
@ -146,7 +290,7 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="search-engine-list" class="card-group" style="display: none">
|
||||
<div id="search-engine-list" class="card-group hidden">
|
||||
<label for="search-engine">Default Search Engine</label>
|
||||
<select id="search-engine">
|
||||
<option value="">Please Select a Search Engine</option>
|
||||
|
@ -156,15 +300,65 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<button id="restore-defaults" class="primary-button">Restore Defaults</button>
|
||||
<div class="card">
|
||||
<div class="card-header">Permissions</div>
|
||||
<div class="card-body">
|
||||
<div class="card-group permission-container">
|
||||
<span>Autoplay</span>
|
||||
<span id="autoplay-forcibly-enabled" class="forcibly-enabled hidden">
|
||||
This setting is controlled via the command line
|
||||
</span>
|
||||
<button id="autoplay-settings" class="secondary-button">Settings...</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<button id="restore-defaults" class="primary-button">Restore Defaults</button>
|
||||
</div>
|
||||
|
||||
<dialog id="site-settings">
|
||||
<div class="dialog-header">
|
||||
<h3 id="site-settings-title" class="dialog-title"></h3>
|
||||
<button id="site-settings-close" class="close-button dialog-close">×</button>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<div class="toggle-container">
|
||||
<label for="site-settings-global">Enable on all sites</label>
|
||||
<label class="toggle">
|
||||
<input id="site-settings-global" type="checkbox" />
|
||||
<span class="toggle-button"></span>
|
||||
</label>
|
||||
</div>
|
||||
<hr />
|
||||
<label>Allowlist</label>
|
||||
<div id="site-settings-list" class="dialog-site-list"></div>
|
||||
<div class="dialog-add-site">
|
||||
<input id="site-settings-input" type="text" placeholder="example.com" />
|
||||
<button id="site-settings-add" class="primary-button">Add Site</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button id="site-settings-remove-all" class="secondary-button">
|
||||
Remove All Sites
|
||||
</button>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<script>
|
||||
const newTabPageURL = document.querySelector("#new-tab-page-url");
|
||||
const searchEngineList = document.querySelector("#search-engine-list");
|
||||
const searchEnabled = document.querySelector("#search-enabled");
|
||||
const searchEngine = document.querySelector("#search-engine");
|
||||
const autoplaySettings = document.querySelector("#autoplay-settings");
|
||||
const siteSettings = document.querySelector("#site-settings");
|
||||
const siteSettingsAdd = document.querySelector("#site-settings-add");
|
||||
const siteSettingsClose = document.querySelector("#site-settings-close");
|
||||
const siteSettingsGlobal = document.querySelector("#site-settings-global");
|
||||
const siteSettingsList = document.querySelector("#site-settings-list");
|
||||
const siteSettingsInput = document.querySelector("#site-settings-input");
|
||||
const siteSettingsRemoveAll = document.querySelector("#site-settings-remove-all");
|
||||
const siteSettingsTitle = document.querySelector("#site-settings-title");
|
||||
const restoreDefaults = document.querySelector("#restore-defaults");
|
||||
|
||||
window.settings = {};
|
||||
|
@ -188,6 +382,12 @@
|
|||
}
|
||||
|
||||
renderSearchEngine();
|
||||
|
||||
const siteSetting = currentSiteSetting();
|
||||
|
||||
if (siteSetting === "autoplay") {
|
||||
showSiteSettings("Autoplay", window.settings.autoplay);
|
||||
}
|
||||
};
|
||||
|
||||
const loadSearchEngines = engines => {
|
||||
|
@ -201,7 +401,11 @@
|
|||
};
|
||||
|
||||
const renderSearchEngine = () => {
|
||||
searchEngineList.style.display = searchEnabled.checked ? "block" : "none";
|
||||
if (searchEnabled.checked) {
|
||||
searchEngineList.classList.remove("hidden");
|
||||
} else {
|
||||
searchEngineList.classList.add("hidden");
|
||||
}
|
||||
|
||||
if (searchEnabled.checked && searchEngine.selectedIndex !== 0) {
|
||||
searchEngine.item(0).disabled = true;
|
||||
|
@ -241,13 +445,140 @@
|
|||
searchEnabled.addEventListener("change", saveSearchEngine);
|
||||
searchEngine.addEventListener("change", saveSearchEngine);
|
||||
|
||||
const forciblyEnableSiteSettings = settings => {
|
||||
settings.forEach(setting => {
|
||||
const label = document.querySelector(`#${setting}-forcibly-enabled`);
|
||||
label.classList.remove("hidden");
|
||||
|
||||
const button = document.querySelector(`#${setting}-settings`);
|
||||
button.classList.add("hidden");
|
||||
});
|
||||
};
|
||||
|
||||
const currentSiteSetting = () => {
|
||||
if (!siteSettings.open) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return siteSettingsTitle.innerText.toLowerCase();
|
||||
};
|
||||
|
||||
const showSiteSettings = (title, settings) => {
|
||||
siteSettingsTitle.innerText = title;
|
||||
siteSettingsGlobal.checked = settings.enabledGlobally;
|
||||
siteSettingsList.innerHTML = "";
|
||||
|
||||
siteSettingsGlobal.onchange = () => {
|
||||
ladybird.sendMessage("setSiteSettingEnabledGlobally", {
|
||||
setting: currentSiteSetting(),
|
||||
enabled: siteSettingsGlobal.checked,
|
||||
});
|
||||
};
|
||||
|
||||
if (settings.siteFilters.length === 0) {
|
||||
const placeholder = document.createElement("div");
|
||||
placeholder.className = "dialog-site-item-placeholder";
|
||||
placeholder.textContent = "No sites added";
|
||||
|
||||
siteSettingsList.appendChild(placeholder);
|
||||
}
|
||||
|
||||
settings.siteFilters.forEach(site => {
|
||||
const filter = document.createElement("span");
|
||||
filter.className = "filter";
|
||||
filter.textContent = site;
|
||||
|
||||
const remove = document.createElement("button");
|
||||
remove.className = "dialog-close";
|
||||
remove.innerHTML = "×";
|
||||
remove.title = `Remove ${site}`;
|
||||
|
||||
remove.addEventListener("click", () => {
|
||||
ladybird.sendMessage("removeSiteSettingFilter", {
|
||||
setting: currentSiteSetting(),
|
||||
filter: site,
|
||||
});
|
||||
});
|
||||
|
||||
const item = document.createElement("div");
|
||||
item.className = "dialog-site-item";
|
||||
item.appendChild(filter);
|
||||
item.appendChild(remove);
|
||||
|
||||
siteSettingsList.appendChild(item);
|
||||
});
|
||||
|
||||
if (!siteSettings.open) {
|
||||
setTimeout(() => siteSettingsInput.focus());
|
||||
siteSettings.showModal();
|
||||
}
|
||||
};
|
||||
|
||||
const addSiteSettingFilter = () => {
|
||||
ladybird.sendMessage("addSiteSettingFilter", {
|
||||
setting: currentSiteSetting(),
|
||||
filter: siteSettingsInput.value,
|
||||
});
|
||||
|
||||
siteSettingsInput.classList.add("success");
|
||||
siteSettingsInput.value = "";
|
||||
|
||||
setTimeout(() => {
|
||||
siteSettingsInput.classList.remove("success");
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => siteSettingsInput.focus());
|
||||
};
|
||||
|
||||
siteSettingsAdd.addEventListener("click", addSiteSettingFilter);
|
||||
|
||||
siteSettingsInput.addEventListener("keydown", event => {
|
||||
if (event.key === "Enter") {
|
||||
addSiteSettingFilter();
|
||||
}
|
||||
});
|
||||
|
||||
siteSettingsClose.addEventListener("click", () => {
|
||||
siteSettings.close();
|
||||
});
|
||||
|
||||
siteSettingsRemoveAll.addEventListener("click", () => {
|
||||
ladybird.sendMessage("removeAllSiteSettingFilters", {
|
||||
setting: currentSiteSetting(),
|
||||
});
|
||||
});
|
||||
|
||||
autoplaySettings.addEventListener("click", event => {
|
||||
showSiteSettings("Autoplay", window.settings.autoplay);
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
restoreDefaults.addEventListener("click", () => {
|
||||
ladybird.sendMessage("restoreDefaultSettings");
|
||||
});
|
||||
|
||||
// FIXME: Once we support `dialog::backdrop`, this event listener should be on `siteSettings`.
|
||||
document.addEventListener("click", event => {
|
||||
if (!siteSettings.open) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rect = siteSettings.getBoundingClientRect();
|
||||
|
||||
if (
|
||||
event.clientX < rect.left ||
|
||||
event.clientX > rect.right ||
|
||||
event.clientY < rect.top ||
|
||||
event.clientY > rect.bottom
|
||||
) {
|
||||
siteSettings.close();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("WebUILoaded", () => {
|
||||
ladybird.sendMessage("loadAvailableSearchEngines");
|
||||
ladybird.sendMessage("loadCurrentSettings");
|
||||
ladybird.sendMessage("loadForciblyEnabledSiteSettings");
|
||||
});
|
||||
|
||||
document.addEventListener("WebUIMessage", event => {
|
||||
|
@ -255,6 +586,8 @@
|
|||
loadSettings(event.detail.data);
|
||||
} else if (event.detail.name === "loadSearchEngines") {
|
||||
loadSearchEngines(event.detail.data);
|
||||
} else if (event.detail.name === "forciblyEnableSiteSettings") {
|
||||
forciblyEnableSiteSettings(event.detail.data);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
:root {
|
||||
--text-color: #2f3640;
|
||||
--toggle-background-color: #cccccc;
|
||||
--secondary-button-color: #dddddd;
|
||||
--secondary-button-hover: #e1e1e1;
|
||||
--secondary-button-active: #e9e9e9;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,26 +53,35 @@
|
|||
:root {
|
||||
--text-color: #e0e0e0;
|
||||
--toggle-background-color: #555555;
|
||||
--secondary-button-color: #555555;
|
||||
--secondary-button-hover: #505050;
|
||||
--secondary-button-active: #444444;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
color-scheme: light dark;
|
||||
font-family: sans-serif;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic form controls.
|
||||
*/
|
||||
|
||||
button.primary-button {
|
||||
color: white;
|
||||
background-color: var(--violet-100);
|
||||
|
||||
button.primary-button,
|
||||
button.secondary-button {
|
||||
font-size: 14px;
|
||||
|
||||
border: none;
|
||||
|
@ -79,14 +91,39 @@ button.primary-button {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.primary-button:hover,
|
||||
button.secondary-button:hover {
|
||||
filter: unset;
|
||||
}
|
||||
|
||||
button.primary-button:active,
|
||||
button.secondary-button:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button.primary-button {
|
||||
color: white;
|
||||
background-color: var(--violet-100);
|
||||
}
|
||||
|
||||
button.primary-button:hover {
|
||||
background-color: var(--violet-500);
|
||||
filter: unset;
|
||||
}
|
||||
|
||||
button.primary-button:active {
|
||||
background-color: var(--violet-900);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button.secondary-button {
|
||||
background-color: var(--secondary-button-color);
|
||||
}
|
||||
|
||||
button.secondary-button:hover {
|
||||
background-color: var(--secondary-button-hover);
|
||||
}
|
||||
|
||||
button.secondary-button:active {
|
||||
background-color: var(--secondary-button-active);
|
||||
}
|
||||
|
||||
input[type="search"],
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/JsonArray.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
|
@ -19,9 +20,15 @@
|
|||
namespace WebView {
|
||||
|
||||
static constexpr auto new_tab_page_url_key = "newTabPageURL"sv;
|
||||
|
||||
static constexpr auto search_engine_key = "searchEngine"sv;
|
||||
static constexpr auto search_engine_name_key = "name"sv;
|
||||
|
||||
static constexpr auto site_setting_enabled_globally_key = "enabledGlobally"sv;
|
||||
static constexpr auto site_setting_site_filters_key = "siteFilters"sv;
|
||||
|
||||
static constexpr auto autoplay_key = "autoplay"sv;
|
||||
|
||||
static ErrorOr<JsonObject> read_settings_file(StringView settings_path)
|
||||
{
|
||||
auto settings_file = Core::File::open(settings_path, Core::File::OpenMode::Read);
|
||||
|
@ -74,6 +81,26 @@ Settings Settings::create(Badge<Application>)
|
|||
settings.m_search_engine = find_search_engine_by_name(*search_engine_name);
|
||||
}
|
||||
|
||||
auto load_site_setting = [&](SiteSetting& site_setting, StringView key) {
|
||||
auto saved_settings = settings_json.value().get_object(key);
|
||||
if (!saved_settings.has_value())
|
||||
return;
|
||||
|
||||
if (auto enabled_globally = saved_settings->get_bool(site_setting_enabled_globally_key); enabled_globally.has_value())
|
||||
site_setting.enabled_globally = *enabled_globally;
|
||||
|
||||
if (auto site_filters = saved_settings->get_array(site_setting_site_filters_key); site_filters.has_value()) {
|
||||
site_setting.site_filters.clear();
|
||||
|
||||
site_filters->for_each([&](auto const& site_filter) {
|
||||
if (site_filter.is_string())
|
||||
site_setting.site_filters.set(site_filter.as_string());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
load_site_setting(settings.m_autoplay, autoplay_key);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
@ -95,6 +122,22 @@ JsonValue Settings::serialize_json() const
|
|||
settings.set(search_engine_key, move(search_engine));
|
||||
}
|
||||
|
||||
auto save_site_setting = [&](SiteSetting const& site_setting, StringView key) {
|
||||
JsonArray site_filters;
|
||||
site_filters.ensure_capacity(site_setting.site_filters.size());
|
||||
|
||||
for (auto const& site_filter : site_setting.site_filters)
|
||||
site_filters.must_append(site_filter);
|
||||
|
||||
JsonObject setting;
|
||||
setting.set("enabledGlobally"sv, site_setting.enabled_globally);
|
||||
setting.set("siteFilters"sv, move(site_filters));
|
||||
|
||||
settings.set(key, move(setting));
|
||||
};
|
||||
|
||||
save_site_setting(m_autoplay, autoplay_key);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
@ -102,6 +145,7 @@ void Settings::restore_defaults()
|
|||
{
|
||||
m_new_tab_page_url = URL::about_newtab();
|
||||
m_search_engine.clear();
|
||||
m_autoplay = SiteSetting {};
|
||||
|
||||
persist_settings();
|
||||
|
||||
|
@ -131,6 +175,46 @@ void Settings::set_search_engine(Optional<StringView> search_engine_name)
|
|||
observer.search_engine_changed();
|
||||
}
|
||||
|
||||
void Settings::set_autoplay_enabled_globally(bool enabled_globally)
|
||||
{
|
||||
m_autoplay.enabled_globally = enabled_globally;
|
||||
persist_settings();
|
||||
|
||||
for (auto& observer : m_observers)
|
||||
observer.autoplay_settings_changed();
|
||||
}
|
||||
|
||||
void Settings::add_autoplay_site_filter(String const& site_filter)
|
||||
{
|
||||
auto trimmed_site_filter = MUST(site_filter.trim_whitespace());
|
||||
if (trimmed_site_filter.is_empty())
|
||||
return;
|
||||
|
||||
m_autoplay.site_filters.set(move(trimmed_site_filter));
|
||||
persist_settings();
|
||||
|
||||
for (auto& observer : m_observers)
|
||||
observer.autoplay_settings_changed();
|
||||
}
|
||||
|
||||
void Settings::remove_autoplay_site_filter(String const& site_filter)
|
||||
{
|
||||
m_autoplay.site_filters.remove(site_filter);
|
||||
persist_settings();
|
||||
|
||||
for (auto& observer : m_observers)
|
||||
observer.autoplay_settings_changed();
|
||||
}
|
||||
|
||||
void Settings::remove_all_autoplay_site_filters()
|
||||
{
|
||||
m_autoplay.site_filters.clear();
|
||||
persist_settings();
|
||||
|
||||
for (auto& observer : m_observers)
|
||||
observer.autoplay_settings_changed();
|
||||
}
|
||||
|
||||
void Settings::persist_settings()
|
||||
{
|
||||
auto settings = serialize_json();
|
||||
|
@ -162,4 +246,9 @@ SettingsObserver::~SettingsObserver()
|
|||
Settings::remove_observer({}, *this);
|
||||
}
|
||||
|
||||
SiteSetting::SiteSetting()
|
||||
{
|
||||
site_filters.set("file://"_string);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Badge.h>
|
||||
#include <AK/HashTable.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <LibURL/URL.h>
|
||||
|
@ -15,6 +16,13 @@
|
|||
|
||||
namespace WebView {
|
||||
|
||||
struct SiteSetting {
|
||||
SiteSetting();
|
||||
|
||||
bool enabled_globally { false };
|
||||
OrderedHashTable<String> site_filters;
|
||||
};
|
||||
|
||||
class SettingsObserver {
|
||||
public:
|
||||
SettingsObserver();
|
||||
|
@ -22,6 +30,7 @@ public:
|
|||
|
||||
virtual void new_tab_page_url_changed() { }
|
||||
virtual void search_engine_changed() { }
|
||||
virtual void autoplay_settings_changed() { }
|
||||
};
|
||||
|
||||
class Settings {
|
||||
|
@ -38,6 +47,12 @@ public:
|
|||
Optional<SearchEngine> const& search_engine() const { return m_search_engine; }
|
||||
void set_search_engine(Optional<StringView> search_engine_name);
|
||||
|
||||
SiteSetting const& autoplay_settings() const { return m_autoplay; }
|
||||
void set_autoplay_enabled_globally(bool);
|
||||
void add_autoplay_site_filter(String const&);
|
||||
void remove_autoplay_site_filter(String const&);
|
||||
void remove_all_autoplay_site_filters();
|
||||
|
||||
static void add_observer(Badge<SettingsObserver>, SettingsObserver&);
|
||||
static void remove_observer(Badge<SettingsObserver>, SettingsObserver&);
|
||||
|
||||
|
@ -50,6 +65,7 @@ private:
|
|||
|
||||
URL::URL m_new_tab_page_url;
|
||||
Optional<SearchEngine> m_search_engine;
|
||||
SiteSetting m_autoplay;
|
||||
|
||||
Vector<SettingsObserver&> m_observers;
|
||||
};
|
||||
|
|
|
@ -29,6 +29,21 @@ void SettingsUI::register_interfaces()
|
|||
register_interface("setSearchEngine"sv, [this](auto const& data) {
|
||||
set_search_engine(data);
|
||||
});
|
||||
register_interface("loadForciblyEnabledSiteSettings"sv, [this](auto const&) {
|
||||
load_forcibly_enabled_site_settings();
|
||||
});
|
||||
register_interface("setSiteSettingEnabledGlobally"sv, [this](auto const& data) {
|
||||
set_site_setting_enabled_globally(data);
|
||||
});
|
||||
register_interface("addSiteSettingFilter"sv, [this](auto const& data) {
|
||||
add_site_setting_filter(data);
|
||||
});
|
||||
register_interface("removeSiteSettingFilter"sv, [this](auto const& data) {
|
||||
remove_site_setting_filter(data);
|
||||
});
|
||||
register_interface("removeAllSiteSettingFilters"sv, [this](auto const& data) {
|
||||
remove_all_site_setting_filters(data);
|
||||
});
|
||||
}
|
||||
|
||||
void SettingsUI::load_current_settings()
|
||||
|
@ -72,4 +87,113 @@ void SettingsUI::set_search_engine(JsonValue const& search_engine)
|
|||
WebView::Application::settings().set_search_engine(search_engine.as_string());
|
||||
}
|
||||
|
||||
enum class SiteSettingType {
|
||||
Autoplay,
|
||||
};
|
||||
|
||||
static constexpr StringView site_setting_type_to_string(SiteSettingType setting)
|
||||
{
|
||||
switch (setting) {
|
||||
case SiteSettingType::Autoplay:
|
||||
return "autoplay"sv;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
static Optional<SiteSettingType> site_setting_type(JsonValue const& settings)
|
||||
{
|
||||
if (!settings.is_object())
|
||||
return {};
|
||||
|
||||
auto setting_type = settings.as_object().get_string("setting"sv);
|
||||
if (!setting_type.has_value())
|
||||
return {};
|
||||
|
||||
if (*setting_type == "autoplay"sv)
|
||||
return SiteSettingType::Autoplay;
|
||||
return {};
|
||||
}
|
||||
|
||||
void SettingsUI::load_forcibly_enabled_site_settings()
|
||||
{
|
||||
JsonArray site_settings;
|
||||
|
||||
if (Application::web_content_options().enable_autoplay == EnableAutoplay::Yes)
|
||||
site_settings.must_append(site_setting_type_to_string(SiteSettingType::Autoplay));
|
||||
|
||||
async_send_message("forciblyEnableSiteSettings"sv, move(site_settings));
|
||||
}
|
||||
|
||||
void SettingsUI::set_site_setting_enabled_globally(JsonValue const& site_setting)
|
||||
{
|
||||
auto setting = site_setting_type(site_setting);
|
||||
if (!setting.has_value())
|
||||
return;
|
||||
|
||||
auto enabled = site_setting.as_object().get_bool("enabled"sv);
|
||||
if (!enabled.has_value())
|
||||
return;
|
||||
|
||||
switch (*setting) {
|
||||
case SiteSettingType::Autoplay:
|
||||
WebView::Application::settings().set_autoplay_enabled_globally(*enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
load_current_settings();
|
||||
}
|
||||
|
||||
void SettingsUI::add_site_setting_filter(JsonValue const& site_setting)
|
||||
{
|
||||
auto setting = site_setting_type(site_setting);
|
||||
if (!setting.has_value())
|
||||
return;
|
||||
|
||||
auto filter = site_setting.as_object().get_string("filter"sv);
|
||||
if (!filter.has_value())
|
||||
return;
|
||||
|
||||
switch (*setting) {
|
||||
case SiteSettingType::Autoplay:
|
||||
WebView::Application::settings().add_autoplay_site_filter(*filter);
|
||||
break;
|
||||
}
|
||||
|
||||
load_current_settings();
|
||||
}
|
||||
|
||||
void SettingsUI::remove_site_setting_filter(JsonValue const& site_setting)
|
||||
{
|
||||
auto setting = site_setting_type(site_setting);
|
||||
if (!setting.has_value())
|
||||
return;
|
||||
|
||||
auto filter = site_setting.as_object().get_string("filter"sv);
|
||||
if (!filter.has_value())
|
||||
return;
|
||||
|
||||
switch (*setting) {
|
||||
case SiteSettingType::Autoplay:
|
||||
WebView::Application::settings().remove_autoplay_site_filter(*filter);
|
||||
break;
|
||||
}
|
||||
|
||||
load_current_settings();
|
||||
}
|
||||
|
||||
void SettingsUI::remove_all_site_setting_filters(JsonValue const& site_setting)
|
||||
{
|
||||
auto setting = site_setting_type(site_setting);
|
||||
if (!setting.has_value())
|
||||
return;
|
||||
|
||||
switch (*setting) {
|
||||
case SiteSettingType::Autoplay:
|
||||
WebView::Application::settings().remove_all_autoplay_site_filters();
|
||||
break;
|
||||
}
|
||||
|
||||
load_current_settings();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ private:
|
|||
void set_new_tab_page_url(JsonValue const&);
|
||||
void load_available_search_engines();
|
||||
void set_search_engine(JsonValue const&);
|
||||
void load_forcibly_enabled_site_settings();
|
||||
void set_site_setting_enabled_globally(JsonValue const&);
|
||||
void add_site_setting_filter(JsonValue const&);
|
||||
void remove_site_setting_filter(JsonValue const&);
|
||||
void remove_all_site_setting_filters(JsonValue const&);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue