Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
dcb6609
Add a side panel for the snapshot diff tab based on release notes
lukechurch Mar 21, 2023
27e90b8
Remove release notes export
lukechurch Mar 21, 2023
8e6d8d1
Tidy up imports, set debug release notes to false
lukechurch Mar 21, 2023
a5d5573
Rename EdgePanel -> SidePanel like the other classes
lukechurch Mar 21, 2023
6bf6252
rename edgePanelController to sidePanelController
lukechurch Mar 21, 2023
3267d15
Fix failing tests due to new side panel
lukechurch Mar 26, 2023
f0b1056
Add next release notes entry
lukechurch Mar 26, 2023
b962466
Update memory diff goldens
lukechurch Mar 26, 2023
904e5ba
Merge remote-tracking branch 'upstream/master' into diff-snapshots-si…
lukechurch Mar 26, 2023
2c17540
Update memory diff goldens after merge
lukechurch Mar 26, 2023
1bf4f12
Address PR comment: move help button in the lhs group
lukechurch Mar 30, 2023
25c648d
Address PR comment: use enum to hold views info
lukechurch Mar 30, 2023
fdeeaef
Add emptyMarkdownFallback field to side panel type enum
lukechurch Mar 30, 2023
ff5a813
Make SidePanelController instantiable, add markdown setter
lukechurch Mar 30, 2023
cc3bc3a
Merge remote-tracking branch 'upstream/master' into diff-snapshots-si…
lukechurch Mar 30, 2023
e1316ff
Undo changes re memory diff help panel
lukechurch Apr 6, 2023
b09bd66
More diff panel help cleanup
lukechurch Apr 6, 2023
ab4279b
Merge branch 'master' into diff-snapshots-side-panel
lukechurch Apr 6, 2023
40831cb
Remove unused import
lukechurch Apr 6, 2023
1dacc3d
Merge upstream master into diff-snapshots-side-panel
lukechurch May 10, 2023
6b01b8a
Address PR feedback
lukechurch May 10, 2023
0513ec3
Address PR comments
lukechurch May 10, 2023
0744258
Move ReleaseNotes class back to its own file
lukechurch May 11, 2023
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
1 change: 1 addition & 0 deletions packages/devtools_app/lib/devtools_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export 'src/shared/primitives/utils.dart';
export 'src/shared/routing.dart';
export 'src/shared/screen.dart';
export 'src/shared/scripts/script_manager.dart';
export 'src/shared/side_panel.dart';
export 'src/shared/split.dart';
export 'src/shared/theme.dart';
export 'src/shared/ui/filter.dart';
Expand Down
1 change: 1 addition & 0 deletions packages/devtools_app/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
],
child: NotificationsView(
child: ReleaseNotesViewer(
controller: releaseNotesController,
child: child,
),
),
Expand Down
3 changes: 1 addition & 2 deletions packages/devtools_app/lib/src/framework/about_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ class DevToolsAboutDialog extends StatelessWidget {
'release notes',
style: theme.linkTextStyle,
),
onTap: () =>
releaseNotesController.toggleReleaseNotesVisible(true),
onTap: () => releaseNotesController.toggleVisibility(true),
),
],
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,182 +3,34 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:math';

import 'package:devtools_shared/devtools_shared.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';

import '../../../devtools.dart' as devtools;
import '../../shared/common_widgets.dart';
import '../../shared/config_specific/launch_url/launch_url.dart';
import '../../shared/config_specific/server/server.dart' as server;
import '../../shared/primitives/auto_dispose.dart';
import '../../shared/theme.dart';
import '../../shared/side_panel.dart';

final _log = Logger('release_notes');

const debugTestReleaseNotes = false;
const releaseNotesKey = Key('release_notes');

class ReleaseNotesViewer extends StatefulWidget {
class ReleaseNotesViewer extends SidePanelViewer {
const ReleaseNotesViewer({
Key? key,
required this.child,
}) : super(key: key);

final Widget? child;

@override
State<ReleaseNotesViewer> createState() => _ReleaseNotesViewerState();
}

class _ReleaseNotesViewerState extends State<ReleaseNotesViewer>
with AutoDisposeMixin, SingleTickerProviderStateMixin {
static const maxViewerWidth = 600.0;

/// Animation controller for animating the opening and closing of the viewer.
late AnimationController visibilityController;

/// A curved animation that matches [visibilityController].
late Animation<double> visibilityAnimation;

String? markdownData;

late bool isVisible;

late ReleaseNotesController releaseNotesController;

@override
void didChangeDependencies() {
super.didChangeDependencies();
releaseNotesController = Provider.of<ReleaseNotesController>(context);

isVisible = releaseNotesController.releaseNotesVisible.value;
markdownData = releaseNotesController.releaseNotesMarkdown.value;

visibilityController = longAnimationController(this);
visibilityAnimation =
Tween<double>(begin: 1.0, end: 0).animate(visibilityController);

addAutoDisposeListener(releaseNotesController.releaseNotesVisible, () {
setState(() {
isVisible = releaseNotesController.releaseNotesVisible.value;
if (isVisible) {
visibilityController.forward();
} else {
visibilityController.reverse();
}
});
});

markdownData = releaseNotesController.releaseNotesMarkdown.value;
addAutoDisposeListener(releaseNotesController.releaseNotesMarkdown, () {
setState(() {
markdownData = releaseNotesController.releaseNotesMarkdown.value;
});
});
}

@override
Widget build(BuildContext context) {
final child = widget.child;
return Material(
child: LayoutBuilder(
builder: (context, constraints) {
final widthForSmallScreen = constraints.maxWidth - 2 * densePadding;
final width = min(
_ReleaseNotesViewerState.maxViewerWidth,
widthForSmallScreen,
);
return Stack(
children: [
if (child != null) child,
ReleaseNotes(
releaseNotesController: releaseNotesController,
visibilityAnimation: visibilityAnimation,
markdownData: markdownData,
width: width,
),
],
);
},
),
);
}
}

class ReleaseNotes extends AnimatedWidget {
const ReleaseNotes({
Key? key,
required this.releaseNotesController,
required Animation<double> visibilityAnimation,
required this.markdownData,
required this.width,
}) : super(key: key, listenable: visibilityAnimation);

final ReleaseNotesController releaseNotesController;

final String? markdownData;

final double width;

@override
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
final theme = Theme.of(context);
final displacement = width * animation.value;
final right = densePadding - displacement;
return Positioned(
top: densePadding,
bottom: densePadding,
right: right,
width: width,
child: Card(
elevation: defaultElevation,
color: theme.scaffoldBackgroundColor,
clipBehavior: Clip.hardEdge,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(defaultBorderRadius),
side: BorderSide(
color: theme.focusColor,
),
),
child: Column(
children: [
AreaPaneHeader(
title: const Text(
'What\'s new in DevTools?',
),
includeTopBorder: false,
actions: [
IconButton(
padding: const EdgeInsets.all(0.0),
onPressed: () =>
releaseNotesController.toggleReleaseNotesVisible(false),
icon: const Icon(Icons.close),
),
],
),
markdownData == null
? const Text('Stay tuned for updates.')
: Expanded(
child: Markdown(
data: markdownData!,
onTapLink: (_, href, __) => unawaited(launchUrl(href!)),
),
),
],
),
),
);
}
required super.controller,
Widget? child,
}) : super(
key: releaseNotesKey,
title: 'What\'s new in DevTools?',
textIfMarkdownDataEmpty: 'Stay tuned for updates.',
child: child,
);
}

class ReleaseNotesController {
class ReleaseNotesController extends SidePanelController {
ReleaseNotesController() {
_init();
}
Expand All @@ -189,14 +41,6 @@ class ReleaseNotesController {
? 'https://flutter-website-dt-staging.web.app'
: 'https://docs.flutter.dev';

ValueListenable<String?> get releaseNotesMarkdown => _releaseNotesMarkdown;

final _releaseNotesMarkdown = ValueNotifier<String?>(null);

ValueListenable<bool> get releaseNotesVisible => _releaseNotesVisible;

final _releaseNotesVisible = ValueNotifier<bool>(false);

void _init() {
if (debugTestReleaseNotes || server.isDevToolsServerAvailable) {
_maybeFetchReleaseNotes();
Expand Down Expand Up @@ -224,8 +68,8 @@ class ReleaseNotesController {
} catch (e) {
// Fail gracefully if we cannot find release notes for the current
// version of DevTools.
_releaseNotesMarkdown.value = null;
toggleReleaseNotesVisible(false);
markdownText = null;
toggleVisibility(false);
_log.warning(
'Warning: could not find release notes for DevTools version '
'$parsedCurrentVersionStr. $e',
Expand Down Expand Up @@ -255,8 +99,8 @@ class ReleaseNotesController {
_flutterDocsSite,
);

_releaseNotesMarkdown.value = releaseNotesMarkdown;
toggleReleaseNotesVisible(true);
markdownText = releaseNotesMarkdown;
toggleVisibility(true);
unawaited(
server.setLastShownReleaseNotesVersion(currentVersionString),
);
Expand All @@ -271,10 +115,6 @@ class ReleaseNotesController {
}
}

void toggleReleaseNotesVisible(bool visible) {
_releaseNotesVisible.value = visible;
}

String _releaseNotesUrl(String currentVersion) {
return '$_flutterDocsSite/development/tools/devtools/release-notes/'
'release-notes-$currentVersion-src.md';
Expand Down
Loading