From d31de8ba70ae799b600455f5830e6453106a22ce Mon Sep 17 00:00:00 2001 From: Ebenezer Nikabou Date: Wed, 13 Dec 2023 22:49:34 +0200 Subject: [PATCH 1/2] added functional full install script code copy --- .gitignore | 5 +++ .../templates/views/pkg/info_box.dart | 6 +++ .../views/pkg/one_click_install.dart | 38 +++++++++++++++++++ pkg/web_app/lib/src/hoverable.dart | 16 ++++++++ pkg/web_css/lib/src/_pkg.scss | 27 ++++++++----- 5 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 app/lib/frontend/templates/views/pkg/one_click_install.dart diff --git a/.gitignore b/.gitignore index e8793163da..9aa4a57259 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,8 @@ build/ key.json node_modules/ + +# test profile files are also not needed + +/app/dev-data-file.jsonl +test-profile.yml \ No newline at end of file diff --git a/app/lib/frontend/templates/views/pkg/info_box.dart b/app/lib/frontend/templates/views/pkg/info_box.dart index e6a303e588..f2c370ee53 100644 --- a/app/lib/frontend/templates/views/pkg/info_box.dart +++ b/app/lib/frontend/templates/views/pkg/info_box.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:pana/pana.dart'; +import 'package:pub_dev/frontend/templates/views/pkg/one_click_install.dart'; import 'package:pubspec_parse/pubspec_parse.dart' as pubspek; import '../../../../package/models.dart'; @@ -67,6 +68,7 @@ d.Node packageInfoBoxNode({ } } return d.fragment([ + _oneClickInstall(package.name!), imageCarousel(), labeledScores, if (thumbnailUrl != null) @@ -105,6 +107,10 @@ d.Node packageInfoBoxNode({ ]); } +d.Node _oneClickInstall(String packageName) { + return oneClickInstallNode(packageName: packageName); +} + d.Node _publisher(String? publisherId) { return _block( 'Publisher', diff --git a/app/lib/frontend/templates/views/pkg/one_click_install.dart b/app/lib/frontend/templates/views/pkg/one_click_install.dart new file mode 100644 index 0000000000..a204deebff --- /dev/null +++ b/app/lib/frontend/templates/views/pkg/one_click_install.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../../../dom/dom.dart' as d; +import '../../../static_files.dart'; + +d.Node oneClickInstallNode({required String packageName}) { + return d.fragment([ + d.text('dart pub add $packageName'), + d.span( + classes: ['pkg-page-install-copy'], + children: [ + d.img( + classes: ['pkg-page-install-copy-icon'], + attributes: { + 'data-copy-content': 'dart pub add $packageName', + 'data-ga-click-event': 'copy-package-version', + }, + image: d.Image( + src: staticUrls.getAssetUrl('/static/img/content-copy-icon.svg'), + alt: 'copy "dart pub add $packageName" to clipboard', + width: 18, + height: 18, + ), + title: 'Copy "dart pub add $packageName" to clipboard', + ), + d.div( + classes: ['pkg-page-install-copy-feedback'], + children: [ + d.span(classes: ['code'], text: '$packageName'), + d.text(' copied to clipboard'), + ], + ), + ], + ), + ]); +} diff --git a/pkg/web_app/lib/src/hoverable.dart b/pkg/web_app/lib/src/hoverable.dart index 62f25e371a..0b92df2202 100644 --- a/pkg/web_app/lib/src/hoverable.dart +++ b/pkg/web_app/lib/src/hoverable.dart @@ -10,6 +10,7 @@ import 'package:_pub_shared/format/x_ago_format.dart'; void setupHoverable() { _setEventForHoverable(); _setEventForPackageTitleCopyToClipboard(); + _setEventForPackageInstallCopyToClipboard(); _setEventForPreCodeCopyToClipboard(); _updateXAgoLabels(); _setEventForXAgo(); @@ -72,6 +73,21 @@ void _setEventForPackageTitleCopyToClipboard() { }); } +void _setEventForPackageInstallCopyToClipboard() { + final root = document.querySelector('.pkg-page-install-copy'); + final icon = root?.querySelector('.pkg-page-install-copy-icon'); + final feedback = root?.querySelector('.pkg-page-install-copy-feedback'); + if (root == null || icon == null || feedback == null) return; + + final copyContent = icon.dataset['copy-content']; + if (copyContent == null || copyContent.isEmpty) return; + + icon.onClick.listen((_) async { + _copyToClipboard(copyContent); + await _animateCopyFeedback(feedback); + }); +} + Future _animateCopyFeedback(Element feedback) async { feedback.classes.add('visible'); await window.animationFrame; diff --git a/pkg/web_css/lib/src/_pkg.scss b/pkg/web_css/lib/src/_pkg.scss index 990247df6a..7be698cc67 100644 --- a/pkg/web_css/lib/src/_pkg.scss +++ b/pkg/web_css/lib/src/_pkg.scss @@ -49,7 +49,8 @@ width: 100%; border-spacing: 0; - td, th { + td, + th { border-bottom: 1px solid #c8c8ca; padding: 8px 4px; text-align: left; @@ -199,7 +200,7 @@ min-width: 40px; max-width: 40px; - >.pkg-report-icon { + > .pkg-report-icon { width: 18px; } } @@ -225,7 +226,7 @@ } &.-is-yellow { - color: #FFA500; + color: #ffa500; } .foldable-icon { @@ -233,7 +234,7 @@ width: 12px; transform: rotate(180deg); - transition: transform .3s linear; + transition: transform 0.3s linear; } } @@ -243,7 +244,6 @@ } } - .pkg-report-content { padding-left: 40px; @@ -278,14 +278,16 @@ } } -.pkg-page-title-copy { +.pkg-page-title-copy, +.pkg-page-install-copy { position: relative; display: inline-block; height: 20px; width: 20px; margin-left: 12px; - .pkg-page-title-copy-icon { + .pkg-page-title-copy-icon, + .pkg-page-install-copy-icon { display: block; width: 20px; height: 20px; @@ -298,7 +300,8 @@ } } - .pkg-page-title-copy-feedback { + .pkg-page-title-copy-feedback, + .pkg-page-install-copy-feedback { position: absolute; top: -12px; left: 32px; @@ -312,7 +315,7 @@ display: none; transition: opacity $copy-feedback-transition-opacity-delay; - >.code { + > .code { font-family: $font-family-google-sans-mono; display: block; } @@ -327,6 +330,10 @@ } } +.pkg-page-install-copy { + top: 5px; +} + .tool-env-info { margin-top: 40px; font-size: 14px; @@ -346,7 +353,7 @@ // // The scaling breaks down on smaller screens, keeping it for // desktop only. - font-size: 1.0vw; + font-size: 1vw; } } } From 1c2cdf2282986c68174ba4f1dd7d11d7ea956050 Mon Sep 17 00:00:00 2001 From: Ebenezer Nikabou Date: Thu, 14 Dec 2023 16:32:31 +0200 Subject: [PATCH 2/2] added styles --- .../templates/views/pkg/info_box.dart | 2 +- .../views/pkg/one_click_install.dart | 61 ++++++++++++------- pkg/web_css/lib/src/_pkg.scss | 36 +++++++++-- pkg/web_css/lib/src/_variables.scss | 2 + 4 files changed, 73 insertions(+), 28 deletions(-) diff --git a/app/lib/frontend/templates/views/pkg/info_box.dart b/app/lib/frontend/templates/views/pkg/info_box.dart index f2c370ee53..06b9edc8ec 100644 --- a/app/lib/frontend/templates/views/pkg/info_box.dart +++ b/app/lib/frontend/templates/views/pkg/info_box.dart @@ -68,9 +68,9 @@ d.Node packageInfoBoxNode({ } } return d.fragment([ - _oneClickInstall(package.name!), imageCarousel(), labeledScores, + _oneClickInstall(package.name!), if (thumbnailUrl != null) d.div(classes: [ 'detail-screenshot-thumbnail' diff --git a/app/lib/frontend/templates/views/pkg/one_click_install.dart b/app/lib/frontend/templates/views/pkg/one_click_install.dart index a204deebff..21f8caba7a 100644 --- a/app/lib/frontend/templates/views/pkg/one_click_install.dart +++ b/app/lib/frontend/templates/views/pkg/one_click_install.dart @@ -7,31 +7,46 @@ import '../../../static_files.dart'; d.Node oneClickInstallNode({required String packageName}) { return d.fragment([ - d.text('dart pub add $packageName'), - d.span( - classes: ['pkg-page-install-copy'], + d.div( + classes: ['pkg-page-install-wrapper'], children: [ - d.img( - classes: ['pkg-page-install-copy-icon'], - attributes: { - 'data-copy-content': 'dart pub add $packageName', - 'data-ga-click-event': 'copy-package-version', - }, - image: d.Image( - src: staticUrls.getAssetUrl('/static/img/content-copy-icon.svg'), - alt: 'copy "dart pub add $packageName" to clipboard', - width: 18, - height: 18, + d.h3(classes: ['title'], child: d.text('Install command')), + d.div(classes: [ + 'pkg-page-install' + ], children: [ + d.span(classes: [ + 'pkg-page-install-code' + ], children: [ + d.pre(children: [d.text('dart pub add $packageName')]) + ]), + d.span( + classes: ['pkg-page-install-copy'], + children: [ + d.img( + classes: ['pkg-page-install-copy-icon'], + attributes: { + 'data-copy-content': 'dart pub add $packageName', + 'data-ga-click-event': 'copy-package-version', + }, + image: d.Image( + src: staticUrls + .getAssetUrl('/static/img/content-copy-icon.svg'), + alt: 'copy "dart pub add $packageName" to clipboard', + width: 18, + height: 18, + ), + title: 'Copy "dart pub add $packageName" to clipboard', + ), + d.div( + classes: ['pkg-page-install-copy-feedback'], + children: [ + d.span(classes: ['code'], text: '$packageName'), + d.text(' copied to clipboard'), + ], + ), + ], ), - title: 'Copy "dart pub add $packageName" to clipboard', - ), - d.div( - classes: ['pkg-page-install-copy-feedback'], - children: [ - d.span(classes: ['code'], text: '$packageName'), - d.text(' copied to clipboard'), - ], - ), + ]), ], ), ]); diff --git a/pkg/web_css/lib/src/_pkg.scss b/pkg/web_css/lib/src/_pkg.scss index 7be698cc67..67575154a5 100644 --- a/pkg/web_css/lib/src/_pkg.scss +++ b/pkg/web_css/lib/src/_pkg.scss @@ -278,6 +278,38 @@ } } +.pkg-page-install-wrapper { + h3.title { + font-size: 16px; + } + .pkg-page-install { + background: $color-grey-bg; + border-radius: 5px; + padding: 10px 5px; + display: flex; + align-items: center; + + .pkg-page-install-code { + font-size: 13px; + pre { + background: inherit; + line-height: inherit; + padding: 0px; + overflow-x: inherit; + white-space: pre-wrap; + word-wrap: break-word; + color: #d14; + } + } + + &:hover { + .pkg-page-install-copy-icon { + opacity: 0.5; + } + } + } +} + .pkg-page-title-copy, .pkg-page-install-copy { position: relative; @@ -330,10 +362,6 @@ } } -.pkg-page-install-copy { - top: 5px; -} - .tool-env-info { margin-top: 40px; font-size: 14px; diff --git a/pkg/web_css/lib/src/_variables.scss b/pkg/web_css/lib/src/_variables.scss index b7c8e9df06..5eaefbcd64 100644 --- a/pkg/web_css/lib/src/_variables.scss +++ b/pkg/web_css/lib/src/_variables.scss @@ -33,5 +33,7 @@ $color-input-primary: #0175C2; $color-input-danger: #ff4242; $color-link: $color-input-primary; +$color-grey-bg: #f5f5f7; + // NOTE: keep in sync with hoverable.dart 900ms delay $copy-feedback-transition-opacity-delay: 0.9s;