Skip to content

Commit

Permalink
chore: disable link glancing on mobile browsers
Browse files Browse the repository at this point in the history
  • Loading branch information
Juliotati committed Aug 25, 2024
1 parent 7f5a1ee commit 1cb87ed
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 90 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/ci_tests_pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ jobs:
with:
cache: true
channel: 'stable'
cache-key: 'flutter-macos-stable-3.24.0-x64'
cache-path: '${{ runner.tool_cache }}/flutter-macos-stable-3.24.0-x64-hash'
pub-cache-key: 'flutter-pub-macos-stable-3.24.0-x64-hash'
pub-cache-path: '${{ runner.tool_cache }}/flutter/stable-3.24.0-x64'
flutter-version: '3.24.0'
cache-key: 'flutter-macos-stable-3.24.1-x64'
cache-path: '${{ runner.tool_cache }}/flutter-macos-stable-3.24.1-x64-hash'
pub-cache-key: 'flutter-pub-macos-stable-3.24.1-x64-hash'
pub-cache-path: '${{ runner.tool_cache }}/flutter/stable-3.24.1-x64'
flutter-version: '3.24.1'

- name: load-dependencies
run: dart pub get
Expand Down
8 changes: 8 additions & 0 deletions .run/TEST_LIBRARY.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="TEST_LIBRARY" type="FlutterTestConfigType" factoryName="Flutter Test">
<option name="testDir" value="$PROJECT_DIR$/test" />
<option name="useRegexp" value="false" />
<option name="additionalArgs" value="" />
<method v="2" />
</configuration>
</component>
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.1.0

* docs: Fixed issue tracker link on pub.dev
* chore: Disable target link glancing on mobile browsers

## 0.0.2

* docs: Update README.md guide with feature preview gif
Expand Down
6 changes: 3 additions & 3 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.0.1"
version: "0.1.0"
lints:
dependency: transitive
description:
Expand Down Expand Up @@ -227,10 +227,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.4"
version: "14.2.5"
sdks:
dart: ">=3.5.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
53 changes: 24 additions & 29 deletions lib/src/detector.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:link_target/src/platform_widget.dart';
import 'package:link_target/src/provider.dart';
import 'package:provider/provider.dart';

Expand Down Expand Up @@ -41,38 +39,35 @@ class _LinkTargetDetectorState extends State<LinkTargetDetector> {

@override
Widget build(BuildContext context) {
if (!kIsWeb) {
if (!Platform.environment.containsKey('FLUTTER_TEST')) {
return widget.child;
}
}

if (comparableTarget.isEmpty || comparableTarget == 'null') {
return widget.child;
}

return MouseRegion(
onHover: (_) {
if (_isHovered) return;
_isHovered = true;
return LinkTargetPlatformWidget(
onNoRegion: widget.child,
onApplyRegion: MouseRegion(
onHover: (_) {
if (_isHovered) return;
_isHovered = true;

final duration = context.read<LinkTargetProvider>().hasTarget
? const Duration(milliseconds: 0)
: const Duration(milliseconds: 550);
final duration = context.read<LinkTargetProvider>().hasTarget
? const Duration(milliseconds: 0)
: const Duration(milliseconds: 550);

Future.delayed(duration, () {
if (!(_isHovered && context.mounted)) return;
context.read<LinkTargetProvider>().onHover(target);
});
},
onExit: (_) {
Future.delayed(const Duration(milliseconds: 300), () {
_isHovered = false;
if (!context.mounted) return;
context.read<LinkTargetProvider>().onExit(target);
});
},
child: widget.child,
Future.delayed(duration, () {
if (!(_isHovered && context.mounted)) return;
context.read<LinkTargetProvider>().onHover(target);
});
},
onExit: (_) {
Future.delayed(const Duration(milliseconds: 300), () {
_isHovered = false;
if (!context.mounted) return;
context.read<LinkTargetProvider>().onExit(target);
});
},
child: widget.child,
),
);
}
}
12 changes: 12 additions & 0 deletions lib/src/helpers/browser_detection.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class BrowserDetection {
BrowserDetection._();

static final BrowserDetection instance = BrowserDetection._();

/// Returns the User Agent of the current browser.
///
/// This is made available for testing purposes and to enable the option of
/// disabling [LinkTargetRegion] on browser on mobile without breaking other
/// non web platform.
bool get isMobile => false;
}
38 changes: 38 additions & 0 deletions lib/src/platform_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:link_target/link_target.dart';

import 'package:link_target/src/helpers/browser_detection.dart'
if (dart.library.html) 'dart:ui_web';

@immutable
final class LinkTargetPlatformWidget extends StatelessWidget {
/// Decided whether the overlay should be applied or not depending on the
/// platform.
///
/// [LinkTargetRegion] should ever only be applied on web browsers with the
/// exception of web browsers running on mobile devices.
///
/// NOTE: Intended for internal use only.
const LinkTargetPlatformWidget({
required this.onNoRegion,
required this.onApplyRegion,
super.key,
});

final Widget onNoRegion;
final Widget onApplyRegion;

@override
Widget build(BuildContext context) {
if (!kIsWeb && !Platform.environment.containsKey('FLUTTER_TEST')) {
return onNoRegion;
}

if (BrowserDetection.instance.isMobile) return onNoRegion;

return onApplyRegion;
}
}
96 changes: 46 additions & 50 deletions lib/src/region.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:link_target/src/platform_widget.dart';
import 'package:link_target/src/provider.dart';
import 'package:provider/provider.dart';

Expand All @@ -21,58 +19,56 @@ final class LinkTargetRegion extends StatelessWidget {

@override
Widget build(BuildContext context) {
if (!kIsWeb) {
if (!Platform.environment.containsKey('FLUTTER_TEST')) {
return child;
}
}

return ListenableProvider(
create: (_) => LinkTargetProvider(),
child: Stack(
clipBehavior: Clip.none,
children: [
child,
Positioned(
left: 0.0,
bottom: 0.0,
child: Consumer<LinkTargetProvider>(
builder: (context, provider, _) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
reverseDuration: const Duration(milliseconds: 300),
child: !provider.hasTarget
? SizedBox.shrink(key: UniqueKey())
: Card(
elevation: 0.0,
margin: EdgeInsets.zero,
color: const Color.fromRGBO(40, 40, 40, 1.0),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(6.0),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 6.0,
horizontal: 8.0,
return LinkTargetPlatformWidget(
onNoRegion: child,
onApplyRegion: ListenableProvider(
create: (_) => LinkTargetProvider(),
child: Stack(
clipBehavior: Clip.none,
children: [
child,
Positioned(
left: 0.0,
bottom: 0.0,
child: Consumer<LinkTargetProvider>(
builder: (context, provider, _) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
reverseDuration: const Duration(milliseconds: 300),
child: !provider.hasTarget
? SizedBox.shrink(key: UniqueKey())
: Card(
elevation: 0.0,
margin: EdgeInsets.zero,
color: const Color.fromRGBO(40, 40, 40, 1.0),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(6.0),
),
),
child: Text(
provider.linkTarget,
maxLines: 1,
softWrap: false,
style: const TextStyle(
fontSize: 12,
color: Color.fromRGBO(240, 240, 240, 1.0),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 4.0,
horizontal: 10.0,
),
child: Text(
provider.linkTarget,
maxLines: 1,
softWrap: false,
style: const TextStyle(
fontSize: 11.5,
overflow: TextOverflow.ellipsis,
color: Color.fromRGBO(240, 240, 240, 1.0),
),
),
),
),
),
);
},
);
},
),
),
),
],
],
),
),
);
}
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: link_target
description: "Adds hyperlink glance behaviour on hover found on the bottom left of the browser page."
version: 0.0.2
version: 0.1.0
homepage: https://github.com/juliotati/link_target

issue_tracker: https://github.com/juliotati/link_targetissues
Expand Down
5 changes: 3 additions & 2 deletions test/src/region_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void main() {
);
expect(
(card.child as Padding).padding,
const EdgeInsets.symmetric(vertical: 6.0, horizontal: 8.0),
const EdgeInsets.symmetric(vertical: 4.0, horizontal: 10.0),
);

final text = (card.child as Padding).child as Text;
Expand All @@ -84,7 +84,8 @@ void main() {
expect(
text.style,
const TextStyle(
fontSize: 12,
fontSize: 11.5,
overflow: TextOverflow.ellipsis,
color: Color.fromRGBO(240, 240, 240, 1.0),
),
);
Expand Down

0 comments on commit 1cb87ed

Please sign in to comment.