Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

preserve query params when navigating #2704

Closed
wants to merge 1 commit into from
Closed
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
19 changes: 15 additions & 4 deletions pkgs/samples/tool/samples.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,15 @@ import 'package:collection/collection.dart';

class Sample {
final String category;
final String name;
final String id;
final String source;
final String? name;

Sample({
required this.category,
required this.name,
required this.id,
required this.source,
this.name,
});

bool get isDart => category == 'Dart';
Expand All @@ -180,9 +180,20 @@ class Samples {
${categories.map((category) => _mapForCategory(category)).join(',\n ')},
};

static Sample? getById(String? id) => all.firstWhereOrNull((s) => s.id == id);
static Sample? getById(String? id) {
final sample = all.firstWhereOrNull((s) => s.id == id);
if (sample != null) {
return sample;
}

if (_defaults.containsKey(id)) {
return Sample(category: id!, id: id, source: _defaults[id]!);
}

return null;
}

static String getDefault({required String type}) => _defaults[type]!;
static String? getDefault({required String type}) => _defaults[type];
}

''');
Expand Down
62 changes: 50 additions & 12 deletions pkgs/sketch_pad/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// 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.

// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;

import 'package:dartpad_shared/services.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -37,6 +40,8 @@ const appName = 'DartPad';

final GoRouter router = _createRouter();

const exclusiveQueryParams = ['id', 'sample'];

void main() async {
setPathUrlStrategy();

Expand Down Expand Up @@ -70,10 +75,13 @@ GoRouter _createRouter() {
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) {
final idParam = state.uri.queryParameters['id'];
final sampleParam = state.uri.queryParameters['sample'];
final themeParam = state.uri.queryParameters['theme'] ?? 'dark';
final channelParam = state.uri.queryParameters['channel'];
final idParam = state.uri.queryParameters['id'];
var sampleParam = state.uri.queryParameters['sample'];
if (idParam == null && sampleParam == null) {
sampleParam = 'dart';
}

final bool darkMode = themeParam == 'dark';
final colorScheme = ColorScheme.fromSwatch(
Expand Down Expand Up @@ -147,7 +155,6 @@ class _DartPadMainPageState extends State<DartPadMainPage> {
appServices.performInitialLoad(
sampleId: widget.sampleId,
gistId: widget.gistId,
fallbackSnippet: Samples.getDefault(type: 'dart'),
);
}

Expand Down Expand Up @@ -308,7 +315,6 @@ class _DartPadMainPageState extends State<DartPadMainPage> {
SizedBox(
height: domHeight,
child: ExecutionWidget(
// useMinHeight: mode.domIsVisible ? false : true,
appServices: appServices,
),
),
Expand Down Expand Up @@ -576,10 +582,11 @@ class NewSnippetWidget extends StatelessWidget {
icon: const Icon(Icons.add_circle),
label: const Text('New'),
onPressed: () async {
final router = GoRouter.of(context);
final selection =
await _showMenu(context, calculatePopupMenuPosition(context));
if (selection != null) {
_handleSelection(appServices, selection);
_handleSelection(appServices, selection, router);
}
},
),
Expand Down Expand Up @@ -613,8 +620,18 @@ class NewSnippetWidget extends StatelessWidget {
);
}

void _handleSelection(AppServices appServices, bool dartSample) {
void _handleSelection(
AppServices appServices,
bool dartSample,
GoRouter router,
) {
appServices.resetTo(type: dartSample ? 'dart' : 'flutter');

final params = Map.of(Uri.parse(html.window.location.href).queryParameters);
params.remove('id');
params['sample'] = dartSample ? 'dart' : 'flutter';

router.go(Uri(path: '/', queryParameters: params).toString());
}
}

Expand Down Expand Up @@ -660,7 +677,7 @@ class ListSamplesWidget extends StatelessWidget {
child: PointerInterceptor(
child: ListTile(
leading: sample.isDart ? dartLogo() : flutterLogo(),
title: Text(sample.name),
title: Text(sample.name!),
),
),
);
Expand All @@ -676,8 +693,10 @@ class ListSamplesWidget extends StatelessWidget {
}

void _handleSelection(BuildContext context, String sampleId) {
context.go(
Uri(path: '/', queryParameters: {'sample': sampleId}).toString(),
context.goRetainQueryParams(
path: '/',
params: {'sample': sampleId},
removeAny: exclusiveQueryParams,
);
}
}
Expand Down Expand Up @@ -747,9 +766,9 @@ class SelectChannelWidget extends StatelessWidget {
appServices.setChannel(channel);

// update the url
// TODO: preserve id? sample? theme?
context.go(
Uri(path: '/', queryParameters: {'channel': channel.name}).toString(),
context.goRetainQueryParams(
path: '/',
params: {'channel': channel.name},
);
}
}
Expand Down Expand Up @@ -909,3 +928,22 @@ class _VersionInfoWidgetState extends State<VersionInfoWidget> {
);
}
}

extension GoRouterExtension on BuildContext {
void goRetainQueryParams({
required String path,
required Map<String, String> params,
List<String> removeAny = const [],
}) {
final existingParams = Uri.parse(html.window.location.href).queryParameters;
Copy link
Member

@parlough parlough Nov 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you instead be able to use GoRouterState.of(this) and use the URI exposed from that state?

I haven't used go_router really, so not sure :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to not have to reach directly to the window's url here. Happy to make changes here (and, John knows go_router well).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the version I came up with. It gets the current URI from the GoRouter's routeInformationProvider instead.


final newMap = Map.of(existingParams);
for (final key in removeAny) {
newMap.remove(key);
}
newMap.addAll(params);

final uri = Uri(path: path, queryParameters: newMap);
go(uri.toString());
}
}
30 changes: 17 additions & 13 deletions pkgs/sketch_pad/lib/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ class AppServices {

void resetTo({String? type}) {
type ??= 'dart';
final source = Samples.getDefault(type: type);

final source = Samples.getDefault(type: type)!;

// reset the source
appModel.sourceCodeController.text = source;
Expand Down Expand Up @@ -178,22 +179,25 @@ class AppServices {
Future<void> performInitialLoad({
String? sampleId,
String? gistId,
required String fallbackSnippet,
}) async {
final fallbackSource = Samples.getDefault(type: 'dart')!;

// Delay a bit for codemirror to initialize.
await Future<void>.delayed(const Duration(milliseconds: 1));

final sample = Samples.getById(sampleId);
if (sample != null) {
appModel.title.value = sample.name;
appModel.sourceCodeController.text = sample.source;
appModel.appReady.value = true;
return;
}

if (gistId == null) {
appModel.sourceCodeController.text = fallbackSnippet;
final sample = Samples.getById(sampleId);

if (sample == null) {
appModel.editorStatus.showToast('Error loading sample');
appModel.sourceCodeController.text = fallbackSource;
} else {
appModel.title.value = sample.name ?? generateSnippetName();
appModel.sourceCodeController.text = sample.source;
}

appModel.appReady.value = true;

return;
}

Expand All @@ -210,7 +214,7 @@ class AppServices {
final source = gist.mainDartSource;
if (source == null) {
appModel.editorStatus.showToast('main.dart not found');
appModel.sourceCodeController.text = fallbackSnippet;
appModel.sourceCodeController.text = fallbackSource;
} else {
appModel.sourceCodeController.text = source;
}
Expand All @@ -222,7 +226,7 @@ class AppServices {

appModel.appendLineToConsole('Error loading gist: $e');

appModel.sourceCodeController.text = fallbackSnippet;
appModel.sourceCodeController.text = fallbackSource;
appModel.appReady.value = true;
} finally {
gistLoader.dispose();
Expand Down
27 changes: 19 additions & 8 deletions pkgs/sketch_pad/lib/samples.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.