Skip to content
Merged
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
4 changes: 3 additions & 1 deletion packages/devtools_app/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,12 @@ class DevToolsAppState extends State<DevToolsApp> with AutoDisposeMixin {
Provider<HoverCardController>.value(
value: hoverCardController,
),
Provider<ReleaseNotesController>.value(
value: releaseNotesController,
),
],
child: NotificationsView(
child: ReleaseNotesViewer(
releaseNotesController: releaseNotesController,
child: child,
),
),
Expand Down
24 changes: 22 additions & 2 deletions packages/devtools_app/lib/src/framework/about_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../../devtools.dart' as devtools;
import '../analytics/constants.dart' as analytics_constants;
import '../shared/common_widgets.dart';
import '../shared/dialogs.dart';
import '../shared/globals.dart';
import '../shared/theme.dart';
import 'release_notes/release_notes.dart';

class DevToolsAboutDialog extends StatelessWidget {
const DevToolsAboutDialog(this.releaseNotesController);

final ReleaseNotesController releaseNotesController;

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Expand All @@ -23,7 +29,20 @@ class DevToolsAboutDialog extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SelectableText('DevTools version ${devtools.version}'),
Row(
children: [
const SelectableText('DevTools version ${devtools.version}'),
const Text(' - '),
InkWell(
child: Text(
'release notes',
style: theme.linkTextStyle,
),
onTap: () =>
releaseNotesController.toggleReleaseNotesVisible(true),
),
],
),
const SizedBox(height: defaultSpacing),
...dialogSubHeader(theme, 'Feedback'),
Wrap(
Expand Down Expand Up @@ -88,14 +107,15 @@ class _DiscordLink extends StatelessWidget {
class OpenAboutAction extends StatelessWidget {
@override
Widget build(BuildContext context) {
final releaseNotesController = Provider.of<ReleaseNotesController>(context);
return DevToolsTooltip(
message: 'About DevTools',
child: InkWell(
onTap: () async {
unawaited(
showDialog(
context: context,
builder: (context) => DevToolsAboutDialog(),
builder: (context) => DevToolsAboutDialog(releaseNotesController),
),
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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:provider/provider.dart';

import '../../../devtools.dart' as devtools;
import '../../config_specific/launch_url/launch_url.dart';
Expand All @@ -24,12 +25,9 @@ const debugTestReleaseNotes = false;
class ReleaseNotesViewer extends StatefulWidget {
const ReleaseNotesViewer({
Key? key,
required this.releaseNotesController,
required this.child,
}) : super(key: key);

final ReleaseNotesController releaseNotesController;

final Widget? child;

@override
Expand All @@ -50,20 +48,23 @@ class _ReleaseNotesViewerState extends State<ReleaseNotesViewer>

late bool isVisible;

late ReleaseNotesController releaseNotesController;

@override
void initState() {
super.initState();
isVisible = widget.releaseNotesController.releaseNotesVisible.value;
markdownData = widget.releaseNotesController.releaseNotesMarkdown.value;
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(widget.releaseNotesController.releaseNotesVisible,
() {
addAutoDisposeListener(releaseNotesController.releaseNotesVisible, () {
setState(() {
isVisible = widget.releaseNotesController.releaseNotesVisible.value;
isVisible = releaseNotesController.releaseNotesVisible.value;
if (isVisible) {
visibilityController.forward();
} else {
Expand All @@ -72,11 +73,10 @@ class _ReleaseNotesViewerState extends State<ReleaseNotesViewer>
});
});

markdownData = widget.releaseNotesController.releaseNotesMarkdown.value;
addAutoDisposeListener(widget.releaseNotesController.releaseNotesMarkdown,
() {
markdownData = releaseNotesController.releaseNotesMarkdown.value;
addAutoDisposeListener(releaseNotesController.releaseNotesMarkdown, () {
setState(() {
markdownData = widget.releaseNotesController.releaseNotesMarkdown.value;
markdownData = releaseNotesController.releaseNotesMarkdown.value;
});
});
}
Expand All @@ -96,7 +96,7 @@ class _ReleaseNotesViewerState extends State<ReleaseNotesViewer>
children: [
if (child != null) child,
ReleaseNotes(
releaseNotesController: widget.releaseNotesController,
releaseNotesController: releaseNotesController,
visibilityAnimation: visibilityAnimation,
markdownData: markdownData,
width: width,
Expand Down Expand Up @@ -197,19 +197,19 @@ class ReleaseNotesController {
final _releaseNotesVisible = ValueNotifier<bool>(false);

void _init() {
if (server.isDevToolsServerAvailable) {
if (debugTestReleaseNotes || server.isDevToolsServerAvailable) {
_maybeFetchReleaseNotes();
}
}

void _maybeFetchReleaseNotes() async {
final lastReleaseNotesShownVersion =
await server.getLastShownReleaseNotesVersion();
SemanticVersion previousVersion;
if (debugTestReleaseNotes || lastReleaseNotesShownVersion.isEmpty) {
previousVersion = SemanticVersion();
} else {
previousVersion = SemanticVersion.parse(lastReleaseNotesShownVersion);
SemanticVersion previousVersion = SemanticVersion();
if (server.isDevToolsServerAvailable) {
final lastReleaseNotesShownVersion =
await server.getLastShownReleaseNotesVersion();
if (lastReleaseNotesShownVersion.isNotEmpty) {
previousVersion = SemanticVersion.parse(lastReleaseNotesShownVersion);
}
}
// Parse the current version instead of using [devtools.version] directly to
// strip off any build metadata (any characters following a '+' character).
Expand Down
4 changes: 3 additions & 1 deletion packages/devtools_app/test/shared/about_dialog_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:devtools_app/src/config_specific/ide_theme/ide_theme.dart';
import 'package:devtools_app/src/extension_points/extensions_base.dart';
import 'package:devtools_app/src/extension_points/extensions_external.dart';
import 'package:devtools_app/src/framework/about_dialog.dart';
import 'package:devtools_app/src/framework/release_notes/release_notes.dart';
import 'package:devtools_app/src/service/service_manager.dart';
import 'package:devtools_app/src/shared/globals.dart';
import 'package:devtools_test/devtools_test.dart';
Expand All @@ -18,7 +19,7 @@ void main() {

group('About Dialog', () {
setUp(() {
aboutDialog = DevToolsAboutDialog();
aboutDialog = DevToolsAboutDialog(ReleaseNotesController());
final fakeServiceManager = FakeServiceManager();
when(fakeServiceManager.vm.version).thenReturn('1.9.1');
mockConnectedApp(
Expand All @@ -41,6 +42,7 @@ void main() {
await tester.pumpWidget(wrap(aboutDialog));
expect(find.text('About DevTools'), findsOneWidget);
expect(findSubstring(aboutDialog, devtools.version), findsOneWidget);
expect(find.text('release notes'), findsOneWidget);
});

testWidgets('Feedback section', (WidgetTester tester) async {
Expand Down