ublock list management initial

This commit is contained in:
Fabian Freund
2026-04-30 10:44:49 +02:00
parent 28dc4e93f1
commit d2bd36b1ed
43 changed files with 2894 additions and 65 deletions
@@ -17,6 +17,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart' show ThemeMode;
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
@@ -26,6 +28,7 @@ import 'package:weblibre/core/logger.dart';
import 'package:weblibre/features/geckoview/features/browser/domain/services/browser_addon.dart';
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_observer.dart';
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_settings.dart';
import 'package:weblibre/features/user/data/models/engine_settings.dart';
import 'package:weblibre/features/user/domain/repositories/engine_settings.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
@@ -33,6 +36,7 @@ part 'engine_settings_replication.g.dart';
const _safeBrowsingMalwarePref = 'browser.safebrowsing.malware.enabled';
const _safeBrowsingPhishingPref = 'browser.safebrowsing.phishing.enabled';
const ublockFilterListsPref = 'browser.weblibre.uBO.filterLists';
/// Checks if any Custom ETP setting changed between two EngineSettings instances.
bool _customEtpSettingsChanged(
@@ -55,6 +59,22 @@ bool _customEtpSettingsChanged(
previous.allowListConvenience != current.allowListConvenience;
}
Future<void> syncUBlockFilterLists(
PreferenceFixator fixator,
EngineSettings settings,
) async {
if (!settings.ublockFilterListSettings.enabled) {
await fixator.unregister(ublockFilterListsPref);
await GeckoPrefService().resetPrefs([ublockFilterListsPref]);
return;
}
await fixator.register(
ublockFilterListsPref,
jsonEncode(settings.ublockFilterListSettings.resolveFinalList()),
);
}
@Riverpod(keepAlive: true)
class EngineSettingsReplicationService
extends _$EngineSettingsReplicationService {
@@ -296,6 +316,13 @@ class EngineSettingsReplicationService
if (previous.value?.lnaEnabled != settings.lnaEnabled) {
await _service.lnaEnabled(settings.lnaEnabled);
}
if (previous.value?.ublockFilterListSettings !=
settings.ublockFilterListSettings) {
await syncUBlockFilterLists(
ref.read(preferenceFixatorProvider.notifier),
settings,
);
}
} else {
await _service.setDefaultSettings(settings);
await ref
@@ -319,6 +346,10 @@ class EngineSettingsReplicationService
await ref
.read(preferenceFixatorProvider.notifier)
.register('intl.accept_languages', settings.locales.join(','));
await syncUBlockFilterLists(
ref.read(preferenceFixatorProvider.notifier),
settings,
);
// Initialize unsigned extensions fixator from Gecko pref
await ref.read(allowUnsignedExtensionsProvider.future);
@@ -44,7 +44,7 @@ final class EngineSettingsReplicationServiceProvider
}
String _$engineSettingsReplicationServiceHash() =>
r'061f0b32a9c49e3bd4b76cd99993620558e0d3b2';
r'71b611a99af83187e392d16288cec280ef44269f';
abstract class _$EngineSettingsReplicationService extends $Notifier<void> {
void build();
@@ -36,7 +36,6 @@ import 'package:skeletonizer/skeletonizer.dart';
import 'package:weblibre/core/design/app_colors.dart';
import 'package:weblibre/core/providers/persisted_bool.dart';
import 'package:weblibre/core/routing/routes.dart';
import 'package:weblibre/features/addons/presentation/screens/addon_internal_settings.dart';
import 'package:weblibre/features/geckoview/domain/controllers/bottom_sheet.dart';
import 'package:weblibre/features/geckoview/domain/entities/states/readerable.dart';
import 'package:weblibre/features/geckoview/domain/entities/tab_container_selection.dart';
@@ -1715,7 +1714,7 @@ class _ExtensionsCard extends HookConsumerWidget {
final rootContext = Navigator.of(context, rootNavigator: true).context;
Future<void> openExtensionSettings(String extensionId) async {
Navigator.pop(context);
await openAddonSettingsFlowById(rootContext, ref, extensionId);
await AddonDetailsRoute(addonId: extensionId).push<void>(rootContext);
}
return _buildMenuCard(
@@ -169,6 +169,7 @@ class CompactAppBarTitleView extends StatelessWidget {
Flexible(
child: UriBreadcrumb(
uri: tabState.url,
showHttpScheme: false,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurface,
),
@@ -546,6 +546,7 @@ class ListTabPreview extends HookConsumerWidget {
Expanded(
child: UriBreadcrumb(
uri: tabState.url,
showHttpScheme: false,
style: textTheme.bodySmall?.copyWith(
color: subtitleColor,
),
@@ -636,7 +637,7 @@ class SyncedListTabPreview extends StatelessWidget {
),
],
),
UriBreadcrumb(uri: url),
UriBreadcrumb(uri: url, showHttpScheme: false),
],
),
trailing: const Icon(Icons.open_in_new),
@@ -77,7 +77,10 @@ class BookmarkSearch extends HookConsumerWidget {
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
subtitle: UriBreadcrumb(uri: bookmark.url),
subtitle: UriBreadcrumb(
uri: bookmark.url,
showHttpScheme: false,
),
onTap: () => onUriSelected(bookmark.url),
);
},
@@ -112,7 +112,10 @@ class HistorySuggestions extends HookConsumerWidget {
),
subtitle:
uri.mapNotNull(
(uri) => UriBreadcrumb(uri: uri),
(uri) => UriBreadcrumb(
uri: uri,
showHttpScheme: false,
),
) ??
suggestion.description.mapNotNull(
(description) => Text(
@@ -244,7 +244,7 @@ class TabSearch extends HookConsumerWidget {
maxLines: 3,
overflow: TextOverflow.ellipsis,
)
: UriBreadcrumb(uri: result.url),
: UriBreadcrumb(uri: result.url, showHttpScheme: false),
onTap: () async {
await ref
.read(tabRepositoryProvider.notifier)
@@ -41,7 +41,7 @@ final class TabDataRepositoryProvider
}
}
String _$tabDataRepositoryHash() => r'c64a44c7d9de566617798a0a3bdcad51bf436658';
String _$tabDataRepositoryHash() => r'e6482b5408aa567f626d2f0a9455b2cc908ba84f';
abstract class _$TabDataRepository extends $Notifier<void> {
void build();