global desktop mode feature
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
||||||
|
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||||
|
|
||||||
part 'desktop_mode.g.dart';
|
part 'desktop_mode.g.dart';
|
||||||
|
|
||||||
@@ -43,6 +44,11 @@ class DesktopMode extends _$DesktopMode {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
// Seed the initial value from the browser-wide default so a newly opened
|
||||||
|
// tab's menu checkbox matches the desktop mode it was actually created with
|
||||||
|
// natively (GeckoTabsApi seeds new tabs from BrowserState.desktopMode).
|
||||||
|
// Read (not watch) so toggling the global default never clobbers an
|
||||||
|
// existing tab's per-tab override.
|
||||||
|
return ref.read(generalSettingsWithDefaultsProvider).globalDesktopMode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ final class DesktopModeProvider extends $NotifierProvider<DesktopMode, bool> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$desktopModeHash() => r'18550009e95a23ff82d30206ce81daa859c57c26';
|
String _$desktopModeHash() => r'727c8a884de5c21499f4b3ae6835af1115f649f2';
|
||||||
|
|
||||||
final class DesktopModeFamily extends $Family
|
final class DesktopModeFamily extends $Family
|
||||||
with $ClassFamilyOverride<DesktopMode, bool, bool, bool, String> {
|
with $ClassFamilyOverride<DesktopMode, bool, bool, bool, String> {
|
||||||
|
|||||||
+32
@@ -25,6 +25,7 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
|||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:weblibre/core/logger.dart';
|
import 'package:weblibre/core/logger.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/domain/providers/desktop_mode.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/domain/services/browser_addon.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_observer.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_settings.dart';
|
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_settings.dart';
|
||||||
@@ -158,6 +159,37 @@ class EngineSettingsReplicationService
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ref.listen(
|
||||||
|
fireImmediately: true,
|
||||||
|
generalSettingsWithDefaultsProvider.select(
|
||||||
|
(settings) => settings.globalDesktopMode,
|
||||||
|
),
|
||||||
|
(previous, next) async {
|
||||||
|
// Only an actual toggle (not the initial startup fire) should rewrite
|
||||||
|
// existing tabs; the initial fire just sets the default for new tabs.
|
||||||
|
final isUserToggle = previous != null;
|
||||||
|
|
||||||
|
await _service.setGlobalDesktopMode(
|
||||||
|
next,
|
||||||
|
applyToExistingTabs: isUserToggle,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isUserToggle) {
|
||||||
|
// The native side applied the new value to all existing tabs.
|
||||||
|
// Invalidate the per-tab desktop-mode notifiers so their menu
|
||||||
|
// checkboxes re-seed and reflect it.
|
||||||
|
ref.invalidate(desktopModeProvider);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (error, stackTrace) {
|
||||||
|
logger.e(
|
||||||
|
'Error listening to globalDesktopMode',
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
ref.listen(
|
ref.listen(
|
||||||
fireImmediately: true,
|
fireImmediately: true,
|
||||||
engineSettingsRepositoryProvider,
|
engineSettingsRepositoryProvider,
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ final class EngineSettingsReplicationServiceProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$engineSettingsReplicationServiceHash() =>
|
String _$engineSettingsReplicationServiceHash() =>
|
||||||
r'8f37476c9beecd6cc70a07b8cd3a51864b077176';
|
r'36f43a382419203ec53cac71fe51b1d30df2a0c6';
|
||||||
|
|
||||||
abstract class _$EngineSettingsReplicationService extends $Notifier<void> {
|
abstract class _$EngineSettingsReplicationService extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
+9
@@ -64,6 +64,15 @@ class PreferenceSetting with FastEquatable {
|
|||||||
final String? description;
|
final String? description;
|
||||||
|
|
||||||
final bool requireUserOptIn;
|
final bool requireUserOptIn;
|
||||||
|
|
||||||
|
/// Marks this preference as an enforced hardening policy: it renders as a
|
||||||
|
/// locked, non-interactive row and cannot be toggled off in the UI.
|
||||||
|
///
|
||||||
|
/// This is a *policy* flag, not a claim that [value] equals Gecko's default.
|
||||||
|
/// Many locked preferences intentionally deviate from the engine default
|
||||||
|
/// (e.g. blanking the telemetry/crash-report/OHTTP endpoints), so auditing
|
||||||
|
/// locked values against Gecko defaults is expected to show differences —
|
||||||
|
/// those are deliberate overrides, not bugs.
|
||||||
final bool locked;
|
final bool locked;
|
||||||
final bool enforceOnStartup;
|
final bool enforceOnStartup;
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ const List<SettingsSectionDefinition> browsingSettingsSections = [
|
|||||||
keywords: ['app links', 'external apps'],
|
keywords: ['app links', 'external apps'],
|
||||||
child: _AppLinksModeSection(),
|
child: _AppLinksModeSection(),
|
||||||
),
|
),
|
||||||
|
SettingsEntryDefinition(
|
||||||
|
title: 'Always Request Desktop Site',
|
||||||
|
subtitle: 'Open new tabs in desktop mode by default',
|
||||||
|
keywords: ['desktop mode', 'user agent', 'mobile site', 'tablet'],
|
||||||
|
child: _GlobalDesktopModeTile(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsSectionDefinition(
|
SettingsSectionDefinition(
|
||||||
@@ -729,6 +735,35 @@ class _AppLinksModeSection extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _GlobalDesktopModeTile extends HookConsumerWidget {
|
||||||
|
const _GlobalDesktopModeTile();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final globalDesktopMode = ref.watch(
|
||||||
|
generalSettingsWithDefaultsProvider.select((s) => s.globalDesktopMode),
|
||||||
|
);
|
||||||
|
|
||||||
|
return SwitchListTile.adaptive(
|
||||||
|
title: const Text('Always Request Desktop Site'),
|
||||||
|
subtitle: const Text(
|
||||||
|
'Open new tabs in desktop mode by default. You can still toggle desktop '
|
||||||
|
'mode per tab from the page menu.',
|
||||||
|
),
|
||||||
|
secondary: const Icon(MdiIcons.monitor),
|
||||||
|
value: globalDesktopMode,
|
||||||
|
onChanged: (value) async {
|
||||||
|
await ref
|
||||||
|
.read(saveGeneralSettingsControllerProvider.notifier)
|
||||||
|
.save(
|
||||||
|
(currentSettings) =>
|
||||||
|
currentSettings.copyWith.globalDesktopMode(value),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _PullToRefreshTile extends HookConsumerWidget {
|
class _PullToRefreshTile extends HookConsumerWidget {
|
||||||
const _PullToRefreshTile();
|
const _PullToRefreshTile();
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,11 @@ class GeneralSettings with FastEquatable {
|
|||||||
/// Only takes effect when the effective brightness is dark. Defaults to false.
|
/// Only takes effect when the effective brightness is dark. Defaults to false.
|
||||||
final bool pureBlack;
|
final bool pureBlack;
|
||||||
|
|
||||||
|
/// Browser-wide default desktop mode. When true, newly opened tabs request
|
||||||
|
/// the desktop version of sites by default. The per-tab desktop-mode toggle
|
||||||
|
/// still overrides this for an individual tab. Defaults to false.
|
||||||
|
final bool globalDesktopMode;
|
||||||
|
|
||||||
GeneralSettings({
|
GeneralSettings({
|
||||||
required this.themeMode,
|
required this.themeMode,
|
||||||
required this.uiScaleFactor,
|
required this.uiScaleFactor,
|
||||||
@@ -214,6 +219,7 @@ class GeneralSettings with FastEquatable {
|
|||||||
required this.indexPrivateTabs,
|
required this.indexPrivateTabs,
|
||||||
required this.acceptSuggestionOnSubmit,
|
required this.acceptSuggestionOnSubmit,
|
||||||
required this.pureBlack,
|
required this.pureBlack,
|
||||||
|
required this.globalDesktopMode,
|
||||||
});
|
});
|
||||||
|
|
||||||
GeneralSettings.withDefaults({
|
GeneralSettings.withDefaults({
|
||||||
@@ -276,6 +282,7 @@ class GeneralSettings with FastEquatable {
|
|||||||
bool? indexPrivateTabs,
|
bool? indexPrivateTabs,
|
||||||
bool? acceptSuggestionOnSubmit,
|
bool? acceptSuggestionOnSubmit,
|
||||||
bool? pureBlack,
|
bool? pureBlack,
|
||||||
|
bool? globalDesktopMode,
|
||||||
}) : themeMode = themeMode ?? ThemeMode.dark,
|
}) : themeMode = themeMode ?? ThemeMode.dark,
|
||||||
uiScaleFactor = uiScaleFactor ?? defaultUiScaleFactor,
|
uiScaleFactor = uiScaleFactor ?? defaultUiScaleFactor,
|
||||||
disableAnimations = disableAnimations ?? false,
|
disableAnimations = disableAnimations ?? false,
|
||||||
@@ -346,7 +353,8 @@ class GeneralSettings with FastEquatable {
|
|||||||
enableLocalSearchIndex = enableLocalSearchIndex ?? true,
|
enableLocalSearchIndex = enableLocalSearchIndex ?? true,
|
||||||
indexPrivateTabs = indexPrivateTabs ?? false,
|
indexPrivateTabs = indexPrivateTabs ?? false,
|
||||||
acceptSuggestionOnSubmit = acceptSuggestionOnSubmit ?? false,
|
acceptSuggestionOnSubmit = acceptSuggestionOnSubmit ?? false,
|
||||||
pureBlack = pureBlack ?? false;
|
pureBlack = pureBlack ?? false,
|
||||||
|
globalDesktopMode = globalDesktopMode ?? false;
|
||||||
|
|
||||||
factory GeneralSettings.fromJson(Map<String, dynamic> json) {
|
factory GeneralSettings.fromJson(Map<String, dynamic> json) {
|
||||||
// Migrate legacy `newTabPosition` setting to direction settings.
|
// Migrate legacy `newTabPosition` setting to direction settings.
|
||||||
@@ -459,5 +467,6 @@ class GeneralSettings with FastEquatable {
|
|||||||
indexPrivateTabs,
|
indexPrivateTabs,
|
||||||
acceptSuggestionOnSubmit,
|
acceptSuggestionOnSubmit,
|
||||||
pureBlack,
|
pureBlack,
|
||||||
|
globalDesktopMode,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ abstract class _$GeneralSettingsCWProxy {
|
|||||||
|
|
||||||
GeneralSettings pureBlack(bool pureBlack);
|
GeneralSettings pureBlack(bool pureBlack);
|
||||||
|
|
||||||
|
GeneralSettings globalDesktopMode(bool globalDesktopMode);
|
||||||
|
|
||||||
/// Creates a new instance with the provided field values.
|
/// Creates a new instance with the provided field values.
|
||||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
||||||
///
|
///
|
||||||
@@ -214,6 +216,7 @@ abstract class _$GeneralSettingsCWProxy {
|
|||||||
bool indexPrivateTabs,
|
bool indexPrivateTabs,
|
||||||
bool acceptSuggestionOnSubmit,
|
bool acceptSuggestionOnSubmit,
|
||||||
bool pureBlack,
|
bool pureBlack,
|
||||||
|
bool globalDesktopMode,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,6 +477,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
|||||||
@override
|
@override
|
||||||
GeneralSettings pureBlack(bool pureBlack) => call(pureBlack: pureBlack);
|
GeneralSettings pureBlack(bool pureBlack) => call(pureBlack: pureBlack);
|
||||||
|
|
||||||
|
@override
|
||||||
|
GeneralSettings globalDesktopMode(bool globalDesktopMode) =>
|
||||||
|
call(globalDesktopMode: globalDesktopMode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
/// Creates a new instance with the provided field values.
|
/// Creates a new instance with the provided field values.
|
||||||
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
/// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`.
|
||||||
@@ -543,6 +550,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
|||||||
Object? indexPrivateTabs = const $CopyWithPlaceholder(),
|
Object? indexPrivateTabs = const $CopyWithPlaceholder(),
|
||||||
Object? acceptSuggestionOnSubmit = const $CopyWithPlaceholder(),
|
Object? acceptSuggestionOnSubmit = const $CopyWithPlaceholder(),
|
||||||
Object? pureBlack = const $CopyWithPlaceholder(),
|
Object? pureBlack = const $CopyWithPlaceholder(),
|
||||||
|
Object? globalDesktopMode = const $CopyWithPlaceholder(),
|
||||||
}) {
|
}) {
|
||||||
return GeneralSettings(
|
return GeneralSettings(
|
||||||
themeMode: themeMode == const $CopyWithPlaceholder() || themeMode == null
|
themeMode: themeMode == const $CopyWithPlaceholder() || themeMode == null
|
||||||
@@ -891,6 +899,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
|
|||||||
? _value.pureBlack
|
? _value.pureBlack
|
||||||
// ignore: cast_nullable_to_non_nullable
|
// ignore: cast_nullable_to_non_nullable
|
||||||
: pureBlack as bool,
|
: pureBlack as bool,
|
||||||
|
globalDesktopMode:
|
||||||
|
globalDesktopMode == const $CopyWithPlaceholder() ||
|
||||||
|
globalDesktopMode == null
|
||||||
|
? _value.globalDesktopMode
|
||||||
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
: globalDesktopMode as bool,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1019,6 +1033,7 @@ GeneralSettings _$GeneralSettingsFromJson(
|
|||||||
indexPrivateTabs: json['indexPrivateTabs'] as bool?,
|
indexPrivateTabs: json['indexPrivateTabs'] as bool?,
|
||||||
acceptSuggestionOnSubmit: json['acceptSuggestionOnSubmit'] as bool?,
|
acceptSuggestionOnSubmit: json['acceptSuggestionOnSubmit'] as bool?,
|
||||||
pureBlack: json['pureBlack'] as bool?,
|
pureBlack: json['pureBlack'] as bool?,
|
||||||
|
globalDesktopMode: json['globalDesktopMode'] as bool?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$GeneralSettingsToJson(
|
Map<String, dynamic> _$GeneralSettingsToJson(
|
||||||
@@ -1096,6 +1111,7 @@ Map<String, dynamic> _$GeneralSettingsToJson(
|
|||||||
'indexPrivateTabs': instance.indexPrivateTabs,
|
'indexPrivateTabs': instance.indexPrivateTabs,
|
||||||
'acceptSuggestionOnSubmit': instance.acceptSuggestionOnSubmit,
|
'acceptSuggestionOnSubmit': instance.acceptSuggestionOnSubmit,
|
||||||
'pureBlack': instance.pureBlack,
|
'pureBlack': instance.pureBlack,
|
||||||
|
'globalDesktopMode': instance.globalDesktopMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$ThemeModeEnumMap = {
|
const _$ThemeModeEnumMap = {
|
||||||
|
|||||||
@@ -273,6 +273,10 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository {
|
|||||||
DriftSqlType.bool,
|
DriftSqlType.bool,
|
||||||
db.typeMapping,
|
db.typeMapping,
|
||||||
),
|
),
|
||||||
|
'globalDesktopMode': settings['globalDesktopMode']?.readAs(
|
||||||
|
DriftSqlType.bool,
|
||||||
|
db.typeMapping,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+34
@@ -23,6 +23,8 @@ import eu.weblibre.flutter_mozilla_components.pigeons.HttpsOnlyMode
|
|||||||
import eu.weblibre.flutter_mozilla_components.pigeons.QueryParameterStripping
|
import eu.weblibre.flutter_mozilla_components.pigeons.QueryParameterStripping
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.TrackingScope
|
import eu.weblibre.flutter_mozilla_components.pigeons.TrackingScope
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.WebContentIsolationStrategy
|
import eu.weblibre.flutter_mozilla_components.pigeons.WebContentIsolationStrategy
|
||||||
|
import mozilla.components.browser.state.action.ContentAction
|
||||||
|
import mozilla.components.browser.state.action.DefaultDesktopModeAction
|
||||||
import mozilla.components.concept.engine.Engine
|
import mozilla.components.concept.engine.Engine
|
||||||
import mozilla.components.concept.engine.EngineSession
|
import mozilla.components.concept.engine.EngineSession
|
||||||
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
||||||
@@ -467,4 +469,36 @@ class GeckoEngineSettingsApiImpl : GeckoEngineSettingsApi {
|
|||||||
override fun getUseExternalDownloadManager(): Boolean {
|
override fun getUseExternalDownloadManager(): Boolean {
|
||||||
return GlobalComponents.useExternalDownloadManager
|
return GlobalComponents.useExternalDownloadManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setGlobalDesktopMode(enable: Boolean, applyToExistingTabs: Boolean) {
|
||||||
|
val store = components.core.store
|
||||||
|
|
||||||
|
// Updates BrowserState.desktopMode, the browser-wide default applied to
|
||||||
|
// newly created tabs/engine sessions.
|
||||||
|
store.dispatch(DefaultDesktopModeAction.DesktopModeUpdated(enable))
|
||||||
|
|
||||||
|
// Only an explicit user toggle should rewrite existing tabs. Skipping this
|
||||||
|
// on the initial replication fire (startup / service rebuild) avoids
|
||||||
|
// clobbering per-tab desktop/mobile overrides and reloading loaded tabs.
|
||||||
|
if (!applyToExistingTabs) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the new value to all existing regular tabs so the change takes
|
||||||
|
// effect immediately instead of only on tabs opened afterwards.
|
||||||
|
store.state.tabs.forEach { tab ->
|
||||||
|
if (tab.content.desktopMode == enable) return@forEach
|
||||||
|
|
||||||
|
if (tab.engineState.engineSession != null) {
|
||||||
|
// Loaded tab: toggle the engine session's desktop mode and reload
|
||||||
|
// it so the page re-renders with the new user agent / viewport.
|
||||||
|
components.useCases.sessionUseCases.requestDesktopSite(enable, tab.id)
|
||||||
|
} else {
|
||||||
|
// Suspended tab (no engine session yet): only update the content
|
||||||
|
// state so the value is applied when the tab is next loaded,
|
||||||
|
// without force-creating a session and waking the tab now.
|
||||||
|
store.dispatch(ContentAction.UpdateTabDesktopMode(tab.id, enable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
@@ -7274,6 +7274,17 @@ interface GeckoEngineSettingsApi {
|
|||||||
*/
|
*/
|
||||||
fun setUseExternalDownloadManager(enabled: Boolean)
|
fun setUseExternalDownloadManager(enabled: Boolean)
|
||||||
fun getUseExternalDownloadManager(): Boolean
|
fun getUseExternalDownloadManager(): Boolean
|
||||||
|
/**
|
||||||
|
* Sets the browser-wide default desktop mode (BrowserState.desktopMode).
|
||||||
|
* Newly opened tabs inherit this default; a per-tab requestDesktopSite
|
||||||
|
* still overrides it for that tab.
|
||||||
|
*
|
||||||
|
* When [applyToExistingTabs] is true, the new value is also applied to all
|
||||||
|
* currently open tabs (loaded tabs are reloaded, suspended tabs are updated
|
||||||
|
* in place). This should only be requested for an explicit user toggle, not
|
||||||
|
* during startup/replication restore, to avoid clobbering per-tab overrides.
|
||||||
|
*/
|
||||||
|
fun setGlobalDesktopMode(enable: Boolean, applyToExistingTabs: Boolean)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by GeckoEngineSettingsApi. */
|
/** The codec used by GeckoEngineSettingsApi. */
|
||||||
@@ -7422,6 +7433,25 @@ interface GeckoEngineSettingsApi {
|
|||||||
channel.setMessageHandler(null)
|
channel.setMessageHandler(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setGlobalDesktopMode$separatedMessageChannelSuffix", codec)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val enableArg = args[0] as Boolean
|
||||||
|
val applyToExistingTabsArg = args[1] as Boolean
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
api.setGlobalDesktopMode(enableArg, applyToExistingTabsArg)
|
||||||
|
listOf(null)
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
GeckoPigeonUtils.wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -216,4 +216,18 @@ class GeckoEngineSettingsService {
|
|||||||
Future<bool> getUseExternalDownloadManager() {
|
Future<bool> getUseExternalDownloadManager() {
|
||||||
return _api.getUseExternalDownloadManager();
|
return _api.getUseExternalDownloadManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the browser-wide default desktop mode (BrowserState.desktopMode).
|
||||||
|
/// Newly opened tabs inherit this default; a per-tab requestDesktopSite still
|
||||||
|
/// overrides it for that tab.
|
||||||
|
///
|
||||||
|
/// Set [applyToExistingTabs] to true only for an explicit user toggle so the
|
||||||
|
/// new value is also applied to currently open tabs. Leave it false during
|
||||||
|
/// startup/replication restore to avoid clobbering per-tab overrides.
|
||||||
|
Future<void> setGlobalDesktopMode(
|
||||||
|
bool enable, {
|
||||||
|
bool applyToExistingTabs = false,
|
||||||
|
}) {
|
||||||
|
return _api.setGlobalDesktopMode(enable, applyToExistingTabs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7360,6 +7360,32 @@ class GeckoEngineSettingsApi {
|
|||||||
;
|
;
|
||||||
return pigeonVar_replyValue! as bool;
|
return pigeonVar_replyValue! as bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the browser-wide default desktop mode (BrowserState.desktopMode).
|
||||||
|
/// Newly opened tabs inherit this default; a per-tab requestDesktopSite
|
||||||
|
/// still overrides it for that tab.
|
||||||
|
///
|
||||||
|
/// When [applyToExistingTabs] is true, the new value is also applied to all
|
||||||
|
/// currently open tabs (loaded tabs are reloaded, suspended tabs are updated
|
||||||
|
/// in place). This should only be requested for an explicit user toggle, not
|
||||||
|
/// during startup/replication restore, to avoid clobbering per-tab overrides.
|
||||||
|
Future<void> setGlobalDesktopMode(bool enable, bool applyToExistingTabs) async {
|
||||||
|
final pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setGlobalDesktopMode$pigeonVar_messageChannelSuffix';
|
||||||
|
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
|
pigeonVar_channelName,
|
||||||
|
pigeonChannelCodec,
|
||||||
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
|
);
|
||||||
|
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[enable, applyToExistingTabs]);
|
||||||
|
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||||
|
|
||||||
|
_extractReplyValueOrThrow(
|
||||||
|
pigeonVar_replyList,
|
||||||
|
pigeonVar_channelName,
|
||||||
|
isNullValid: true,
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeckoSessionApi {
|
class GeckoSessionApi {
|
||||||
|
|||||||
@@ -1561,6 +1561,16 @@ abstract class GeckoEngineSettingsApi {
|
|||||||
void setUseExternalDownloadManager(bool enabled);
|
void setUseExternalDownloadManager(bool enabled);
|
||||||
|
|
||||||
bool getUseExternalDownloadManager();
|
bool getUseExternalDownloadManager();
|
||||||
|
|
||||||
|
/// Sets the browser-wide default desktop mode (BrowserState.desktopMode).
|
||||||
|
/// Newly opened tabs inherit this default; a per-tab requestDesktopSite
|
||||||
|
/// still overrides it for that tab.
|
||||||
|
///
|
||||||
|
/// When [applyToExistingTabs] is true, the new value is also applied to all
|
||||||
|
/// currently open tabs (loaded tabs are reloaded, suspended tabs are updated
|
||||||
|
/// in place). This should only be requested for an explicit user toggle, not
|
||||||
|
/// during startup/replication restore, to avoid clobbering per-tab overrides.
|
||||||
|
void setGlobalDesktopMode(bool enable, bool applyToExistingTabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
|
|||||||
Reference in New Issue
Block a user