hide toolbar on scrool
This commit is contained in:
@@ -254,3 +254,15 @@ AsyncValue<String?> selectedTabContainerId(Ref ref) {
|
||||
|
||||
return const AsyncData(null);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<int> selectedTabScrollY(Ref ref, Duration sampleTime) {
|
||||
final tabId = ref.watch(selectedTabProvider);
|
||||
final eventService = ref.watch(eventServiceProvider);
|
||||
|
||||
return eventService.scrollEvent
|
||||
.where((event) => event.tabId == tabId)
|
||||
.sampleTime(sampleTime)
|
||||
.map((event) => event.scrollY)
|
||||
.asBroadcastStream();
|
||||
}
|
||||
|
||||
@@ -193,6 +193,128 @@ final selectedTabContainerIdProvider = Provider<AsyncValue<String?>>.internal(
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef SelectedTabContainerIdRef = ProviderRef<AsyncValue<String?>>;
|
||||
String _$selectedTabScrollYHash() =>
|
||||
r'7ca7cccfa7ebb7f13e0d7c096ce6c93f9e220cb5';
|
||||
|
||||
/// See also [selectedTabScrollY].
|
||||
@ProviderFor(selectedTabScrollY)
|
||||
const selectedTabScrollYProvider = SelectedTabScrollYFamily();
|
||||
|
||||
/// See also [selectedTabScrollY].
|
||||
class SelectedTabScrollYFamily extends Family<AsyncValue<int>> {
|
||||
/// See also [selectedTabScrollY].
|
||||
const SelectedTabScrollYFamily();
|
||||
|
||||
/// See also [selectedTabScrollY].
|
||||
SelectedTabScrollYProvider call(Duration sampleTime) {
|
||||
return SelectedTabScrollYProvider(sampleTime);
|
||||
}
|
||||
|
||||
@override
|
||||
SelectedTabScrollYProvider getProviderOverride(
|
||||
covariant SelectedTabScrollYProvider provider,
|
||||
) {
|
||||
return call(provider.sampleTime);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'selectedTabScrollYProvider';
|
||||
}
|
||||
|
||||
/// See also [selectedTabScrollY].
|
||||
class SelectedTabScrollYProvider extends AutoDisposeStreamProvider<int> {
|
||||
/// See also [selectedTabScrollY].
|
||||
SelectedTabScrollYProvider(Duration sampleTime)
|
||||
: this._internal(
|
||||
(ref) => selectedTabScrollY(ref as SelectedTabScrollYRef, sampleTime),
|
||||
from: selectedTabScrollYProvider,
|
||||
name: r'selectedTabScrollYProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$selectedTabScrollYHash,
|
||||
dependencies: SelectedTabScrollYFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
SelectedTabScrollYFamily._allTransitiveDependencies,
|
||||
sampleTime: sampleTime,
|
||||
);
|
||||
|
||||
SelectedTabScrollYProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.sampleTime,
|
||||
}) : super.internal();
|
||||
|
||||
final Duration sampleTime;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
Stream<int> Function(SelectedTabScrollYRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: SelectedTabScrollYProvider._internal(
|
||||
(ref) => create(ref as SelectedTabScrollYRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
sampleTime: sampleTime,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeStreamProviderElement<int> createElement() {
|
||||
return _SelectedTabScrollYProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is SelectedTabScrollYProvider &&
|
||||
other.sampleTime == sampleTime;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, sampleTime.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin SelectedTabScrollYRef on AutoDisposeStreamProviderRef<int> {
|
||||
/// The parameter `sampleTime` of this provider.
|
||||
Duration get sampleTime;
|
||||
}
|
||||
|
||||
class _SelectedTabScrollYProviderElement
|
||||
extends AutoDisposeStreamProviderElement<int>
|
||||
with SelectedTabScrollYRef {
|
||||
_SelectedTabScrollYProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
Duration get sampleTime => (origin as SelectedTabScrollYProvider).sampleTime;
|
||||
}
|
||||
|
||||
String _$tabStatesHash() => r'66cff6a7b36328ee23b89fdd53046987b346bfcd';
|
||||
|
||||
/// See also [TabStates].
|
||||
|
||||
@@ -99,7 +99,7 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
child: Scaffold(
|
||||
bottomNavigationBar: Consumer(
|
||||
bottomNavigationBar: HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final tabInFullScreen = ref.watch(
|
||||
selectedTabStateProvider.select(
|
||||
@@ -107,8 +107,30 @@ class BrowserScreen extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
|
||||
final hidden = useState(false);
|
||||
final diffAcc = useRef(0.0);
|
||||
|
||||
ref.listen(
|
||||
selectedTabScrollYProvider(const Duration(milliseconds: 250)),
|
||||
(previous, next) {
|
||||
if (previous?.valueOrNull != null &&
|
||||
next.valueOrNull != null) {
|
||||
final diff = previous!.value! - next.value!;
|
||||
if (diff < 0) {
|
||||
diffAcc.value += diff;
|
||||
if (diffAcc.value.abs() > kToolbarHeight * 2) {
|
||||
hidden.value = true;
|
||||
}
|
||||
} else if (diff > 0) {
|
||||
diffAcc.value = 0.0;
|
||||
hidden.value = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return Visibility(
|
||||
visible: !tabInFullScreen,
|
||||
visible: !tabInFullScreen && !hidden.value,
|
||||
child: BrowserBottomAppBar(displayedSheet: displayedSheet),
|
||||
);
|
||||
},
|
||||
|
||||
+9
@@ -133,6 +133,15 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
||||
) { _ -> }
|
||||
}
|
||||
}
|
||||
is ReaderAction.UpdateReaderScrollYAction -> {
|
||||
runOnUiThread {
|
||||
flutterEvents.onScrollChange(
|
||||
System.currentTimeMillis(),
|
||||
action.tabId,
|
||||
action.scrollY.toLong()
|
||||
) { _ -> }
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
//logger.debug("Event fired: " + action.javaClass.name)
|
||||
}
|
||||
|
||||
+17
@@ -3998,6 +3998,23 @@ class GeckoStateEvents(private val binaryMessenger: BinaryMessenger, private val
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onScrollChange(timestampArg: Long, tabIdArg: String, scrollYArg: Long, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onScrollChange$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(timestampArg, tabIdArg, scrollYArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(GeckoPigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */
|
||||
class GeckoLogging(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") {
|
||||
|
||||
@@ -19,6 +19,7 @@ typedef IconUpdateEvent = ({String url, Uint8List bytes});
|
||||
typedef ThumbnailEvent = ({String tabId, Uint8List? bytes});
|
||||
typedef FindResultsEvent = ({String tabId, List<FindResultState> results});
|
||||
typedef LongPressEvent = ({String tabId, HitResult hitResult});
|
||||
typedef ScrollEvent = ({String tabId, int scrollY});
|
||||
|
||||
class GeckoEventService extends GeckoStateEvents {
|
||||
// Stream controllers
|
||||
@@ -37,6 +38,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
final _thumbnailSubject = PublishSubject<ThumbnailEvent>();
|
||||
final _findResultsSubject = PublishSubject<FindResultsEvent>();
|
||||
final _longPressSubject = PublishSubject<LongPressEvent>();
|
||||
final _scrollEventSubject = PublishSubject<ScrollEvent>();
|
||||
|
||||
final _tabAddedSubject = PublishSubject<String>();
|
||||
|
||||
@@ -56,6 +58,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
Stream<ThumbnailEvent> get thumbnailEvents => _thumbnailSubject.stream;
|
||||
Stream<FindResultsEvent> get findResultsEvent => _findResultsSubject.stream;
|
||||
Stream<LongPressEvent> get longPressEvent => _longPressSubject.stream;
|
||||
Stream<ScrollEvent> get scrollEvent => _scrollEventSubject.stream;
|
||||
|
||||
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
||||
|
||||
@@ -166,6 +169,14 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
_tabAddedSubject.addWhenMoreRecent(timestamp, null, tabId);
|
||||
}
|
||||
|
||||
@override
|
||||
void onScrollChange(int timestamp, String tabId, int scrollY) {
|
||||
_scrollEventSubject.addWhenMoreRecent(timestamp, tabId, (
|
||||
tabId: tabId,
|
||||
scrollY: scrollY,
|
||||
));
|
||||
}
|
||||
|
||||
GeckoEventService.setUp({
|
||||
BinaryMessenger? binaryMessenger,
|
||||
String messageChannelSuffix = '',
|
||||
@@ -188,6 +199,7 @@ class GeckoEventService extends GeckoStateEvents {
|
||||
unawaited(_thumbnailSubject.close());
|
||||
unawaited(_findResultsSubject.close());
|
||||
unawaited(_longPressSubject.close());
|
||||
unawaited(_scrollEventSubject.close());
|
||||
unawaited(_tabAddedSubject.close());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4338,6 +4338,8 @@ abstract class GeckoStateEvents {
|
||||
|
||||
void onLongPress(int timestamp, String id, HitResult hitResult);
|
||||
|
||||
void onScrollChange(int timestamp, String tabId, int scrollY);
|
||||
|
||||
static void setUp(GeckoStateEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||
{
|
||||
@@ -4750,6 +4752,37 @@ abstract class GeckoStateEvents {
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onScrollChange$messageChannelSuffix', pigeonChannelCodec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
pigeonVar_channel.setMessageHandler(null);
|
||||
} else {
|
||||
pigeonVar_channel.setMessageHandler((Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onScrollChange was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_timestamp = (args[0] as int?);
|
||||
assert(arg_timestamp != null,
|
||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onScrollChange was null, expected non-null int.');
|
||||
final String? arg_tabId = (args[1] as String?);
|
||||
assert(arg_tabId != null,
|
||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onScrollChange was null, expected non-null String.');
|
||||
final int? arg_scrollY = (args[2] as int?);
|
||||
assert(arg_scrollY != null,
|
||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoStateEvents.onScrollChange was null, expected non-null int.');
|
||||
try {
|
||||
api.onScrollChange(arg_timestamp!, arg_tabId!, arg_scrollY!);
|
||||
return wrapResponse(empty: true);
|
||||
} on PlatformException catch (e) {
|
||||
return wrapResponse(error: e);
|
||||
} catch (e) {
|
||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1050,6 +1050,8 @@ abstract class GeckoStateEvents {
|
||||
|
||||
void onFindResults(int timestamp, String id, List<FindResultState> results);
|
||||
void onLongPress(int timestamp, String id, HitResult hitResult);
|
||||
|
||||
void onScrollChange(int timestamp, String tabId, int scrollY);
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
|
||||
Reference in New Issue
Block a user