Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions sites/docs/lib/_sass/components/_misc.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
.copy-page-toast {
position: fixed;
bottom: 1.5rem;
left: 50%;
transform: translateX(-50%);
background-color: var(--site-primary-color, #0175c2);
color: #fff;
padding: 0.65rem 1.25rem;
border-radius: var(--site-radius, 0.5rem);
font-size: 0.9rem;
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.2);
z-index: 1000;
animation: copy-page-toast-in 0.2s ease;
}

@keyframes copy-page-toast-in {
from { opacity: 0; transform: translateX(-50%) translateY(0.5rem); }
to { opacity: 1; transform: translateX(-50%) translateY(0); }
}

#page-content p.install-help {
text-align: right;
margin-block-start: -2.5rem;
Expand Down
1 change: 1 addition & 0 deletions sites/docs/lib/main.client.options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ ClientOptions get defaultClientOptions => ClientOptions(
title: p['title'] as String,
sourceUrl: p['sourceUrl'] as String?,
issueUrl: p['issueUrl'] as String?,
showCopyPage: p['showCopyPage'] as bool,
),
loader: _page_header_options.loadLibrary,
),
Expand Down
7 changes: 6 additions & 1 deletion sites/docs/lib/main.server.options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,12 @@ Map<String, Object?> __feedbackFeedbackComponent(
) => {'issueUrl': c.issueUrl};
Map<String, Object?> __page_header_optionsPageHeaderOptions(
_page_header_options.PageHeaderOptions c,
) => {'title': c.title, 'sourceUrl': c.sourceUrl, 'issueUrl': c.issueUrl};
) => {
'title': c.title,
'sourceUrl': c.sourceUrl,
'issueUrl': c.issueUrl,
'showCopyPage': c.showCopyPage,
};
Map<String, Object?> __simple_tooltipSimpleTooltip(
_simple_tooltip.SimpleTooltip c,
) => {'target': c.target.toId(), 'content': c.content.toId()};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:http/http.dart' as http;
import 'package:jaspr/dom.dart';
import 'package:jaspr/jaspr.dart';
import 'package:universal_web/js_interop.dart';
Expand All @@ -16,19 +17,22 @@ final class PageHeaderOptions extends StatefulComponent {
required this.title,
this.sourceUrl,
this.issueUrl,
this.showCopyPage = true,
super.key,
});

final String title;
final String? sourceUrl;
final String? issueUrl;
final bool showCopyPage;

@override
State<PageHeaderOptions> createState() => _PageHeaderOptionsState();
}

final class _PageHeaderOptionsState extends State<PageHeaderOptions> {
bool _isShareSupported = false;
bool _copied = false;

@override
void initState() {
Expand All @@ -51,13 +55,35 @@ final class _PageHeaderOptionsState extends State<PageHeaderOptions> {
String get _currentBaseUrl =>
web.window.location.origin + web.window.location.pathname;

String? get _rawMarkdownUrl {
final sourceUrl = component.sourceUrl;
if (sourceUrl == null) return null;
return sourceUrl
.replaceFirst('github.com', 'raw.githubusercontent.com')
.replaceFirst('/blob/', '/');
}

Future<void> _copyPageContent() async {
final rawUrl = _rawMarkdownUrl;
if (rawUrl == null) return;
final response = await http.get(Uri.parse(rawUrl));
if (response.statusCode == 200) {
await web.window.navigator.clipboard.writeText(response.body).toDart;
setState(() => _copied = true);
Future<void>.delayed(const Duration(seconds: 2), () {
if (mounted) setState(() => _copied = false);
});
}
}

web.ShareData get _shareData => web.ShareData(
url: _currentBaseUrl,
title: component.title,
);

@override
Component build(BuildContext _) => Dropdown(
Component build(BuildContext _) => .fragment([
Dropdown(
id: 'page-header-options',
toggle: const Button(icon: 'more_vert', title: 'View page options.'),
content: nav(
Expand Down Expand Up @@ -91,6 +117,16 @@ final class _PageHeaderOptionsState extends State<PageHeaderOptions> {
),
],
),
if (component.showCopyPage && _rawMarkdownUrl != null)
li(
[
Button(
icon: _copied ? 'check' : 'content_copy',
content: _copied ? 'Copied!' : 'Copy page',
onClick: () => _copyPageContent().ignore(),
),
],
),
if (component.sourceUrl case final sourceUrl?)
li(
[
Expand Down Expand Up @@ -123,5 +159,11 @@ final class _PageHeaderOptionsState extends State<PageHeaderOptions> {
),
],
),
);
),
if (_copied)
div(
classes: 'copy-page-toast',
[.text('Page copied to clipboard!')],
),
]);
}
3 changes: 3 additions & 0 deletions sites/docs/lib/src/components/common/page_header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ final class PageHeader extends StatelessComponent {
this.description,
this.wrap = true,
this.showBreadcrumbs = true,
this.showCopyPage = true,
});

final String title;
final String? description;
final bool wrap;
final bool showBreadcrumbs;
final bool showCopyPage;

@override
Component build(BuildContext context) {
Expand All @@ -49,6 +51,7 @@ final class PageHeader extends StatelessComponent {
title: title,
sourceUrl: sourceInfo.sourceUrl,
issueUrl: sourceInfo.issueUrl,
showCopyPage: showCopyPage,
),
],
);
Expand Down
9 changes: 9 additions & 0 deletions sites/docs/lib/src/layouts/doc_layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ class DocLayout extends FlutterDocsLayout {
);
}

static final _htmlTagPattern = RegExp(r'<[^>]+>');

bool _hasSubstantialContent(Page page) {
final text = page.content.replaceAll(_htmlTagPattern, ' ');
final wordCount = text.trim().split(RegExp(r'\s+')).where((w) => w.isNotEmpty).length;
return wordCount > 150;
}

@override
Component buildBody(Page page, Component child) {
final pageData = page.data.page;
Expand Down Expand Up @@ -94,6 +102,7 @@ class DocLayout extends FlutterDocsLayout {
showBreadcrumbs:
allowBreadcrumbs &&
(pageData['showBreadcrumbs'] as bool? ?? true),
showCopyPage: _hasSubstantialContent(page),
),

child,
Expand Down