From 9d052ddf1380c578c85617620a0553ebb705d5b4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 20 Feb 2025 11:53:52 -0800 Subject: [PATCH] use more subtle progress when reloading (#3147) --- pkgs/dartpad_ui/lib/execution/frame.dart | 24 +++++---- pkgs/dartpad_ui/lib/main.dart | 28 +++++----- pkgs/dartpad_ui/lib/model.dart | 67 +++++++++++++++--------- 3 files changed, 71 insertions(+), 48 deletions(-) diff --git a/pkgs/dartpad_ui/lib/execution/frame.dart b/pkgs/dartpad_ui/lib/execution/frame.dart index 2e8dd2b0a..d36972531 100644 --- a/pkgs/dartpad_ui/lib/execution/frame.dart +++ b/pkgs/dartpad_ui/lib/execution/frame.dart @@ -37,11 +37,13 @@ class ExecutionServiceImpl implements ExecutionService { } return _send(reload ? 'executeReload' : 'execute', { - 'js': _decorateJavaScript(javaScript, - modulesBaseUrl: modulesBaseUrl, - isNewDDC: isNewDDC, - reload: reload, - isFlutter: isFlutter), + 'js': _decorateJavaScript( + javaScript, + modulesBaseUrl: modulesBaseUrl, + isNewDDC: isNewDDC, + reload: reload, + isFlutter: isFlutter, + ), if (engineVersion != null) 'canvasKitBaseUrl': _canvasKitUrl(engineVersion), }); @@ -61,11 +63,13 @@ class ExecutionServiceImpl implements ExecutionService { @override Future tearDown() => _reset(); - String _decorateJavaScript(String javaScript, - {String? modulesBaseUrl, - required bool isNewDDC, - required bool reload, - required bool isFlutter}) { + String _decorateJavaScript( + String javaScript, { + String? modulesBaseUrl, + required bool isNewDDC, + required bool reload, + required bool isFlutter, + }) { if (reload) return javaScript; final script = StringBuffer(); diff --git a/pkgs/dartpad_ui/lib/main.dart b/pkgs/dartpad_ui/lib/main.dart index be6406e07..004f25af6 100644 --- a/pkgs/dartpad_ui/lib/main.dart +++ b/pkgs/dartpad_ui/lib/main.dart @@ -442,12 +442,12 @@ class _DartPadMainPageState extends State child: CallbackShortcuts( bindings: { keys.runKeyActivator1: () { - if (!appModel.compilingBusy.value) { + if (!appModel.compilingBusy.value.busy) { appServices.performCompileAndRun(); } }, keys.runKeyActivator2: () { - if (!appModel.compilingBusy.value) { + if (!appModel.compilingBusy.value.busy) { appServices.performCompileAndRun(); } }, @@ -513,7 +513,7 @@ class _DartPadMainPageState extends State void _handleRunStarted() { setState(() { // Switch to the application output tab.] - if (appModel.compilingBusy.value) { + if (appModel.compilingBusy.value != CompilingState.none) { tabController.animateTo(1); } }); @@ -531,19 +531,20 @@ class LoadingOverlay extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); - return ValueListenableBuilder( + return ValueListenableBuilder( valueListenable: appModel.compilingBusy, - builder: (_, bool compiling, __) { + builder: (_, compiling, __) { final color = theme.colorScheme.surface; + // If reloading, show a progress spinner. If restarting, also display a + // semi-opaque overlay. return AnimatedContainer( - color: color.withValues(alpha: compiling ? 0.8 : 0), + color: color.withValues( + alpha: compiling == CompilingState.compiling ? 0.8 : 0), duration: animationDelay, curve: animationCurve, - child: compiling - ? const GoldenRatioCenter( - child: CircularProgressIndicator(), - ) + child: compiling.busy + ? const GoldenRatioCenter(child: CircularProgressIndicator()) : const SizedBox(width: 1), ); }, @@ -731,12 +732,13 @@ class EditorWithButtons extends StatelessWidget { }), const SizedBox(width: defaultSpacing), // Run action - ValueListenableBuilder( + ValueListenableBuilder( valueListenable: appModel.compilingBusy, - builder: (_, bool value, __) { + builder: (_, compiling, __) { return PointerInterceptor( child: RunButton( - onPressed: value ? null : onCompileAndRun, + onPressed: + compiling.busy ? null : onCompileAndRun, ), ); }, diff --git a/pkgs/dartpad_ui/lib/model.dart b/pkgs/dartpad_ui/lib/model.dart index 2420bd399..d734b80fd 100644 --- a/pkgs/dartpad_ui/lib/model.dart +++ b/pkgs/dartpad_ui/lib/model.dart @@ -54,7 +54,8 @@ class AppModel { final ValueNotifier consoleOutput = ValueNotifier(''); final ValueNotifier formattingBusy = ValueNotifier(false); - final ValueNotifier compilingBusy = ValueNotifier(false); + final ValueNotifier compilingBusy = + ValueNotifier(CompilingState.none); final ValueNotifier docHelpBusy = ValueNotifier(false); final ValueNotifier hasRun = ValueNotifier(false); @@ -76,23 +77,25 @@ class AppModel { final ValueNotifier vimKeymapsEnabled = ValueNotifier(false); bool _consoleShowingError = false; + final ValueNotifier showReload = ValueNotifier(false); - final ValueNotifier _useNewDDC = ValueNotifier(false); + final ValueNotifier useNewDDC = ValueNotifier(false); final ValueNotifier currentDeltaDill = ValueNotifier(null); AppModel() { consoleOutput.addListener(_recalcLayout); - void updateCanReload() => canReload.value = - hasRun.value && !compilingBusy.value && currentDeltaDill.value != null; + void updateCanReload() => canReload.value = hasRun.value && + !compilingBusy.value.busy && + currentDeltaDill.value != null; hasRun.addListener(updateCanReload); compilingBusy.addListener(updateCanReload); currentDeltaDill.addListener(updateCanReload); void updateShowReload() { - showReload.value = _useNewDDC.value && (_appIsFlutter.value ?? false); + showReload.value = useNewDDC.value && (_appIsFlutter.value ?? false); } - _useNewDDC.addListener(updateShowReload); + useNewDDC.addListener(updateShowReload); _appIsFlutter.addListener(updateShowReload); _splitSubscription = @@ -187,7 +190,7 @@ class AppServices { appModel.analysisIssues.addListener(_updateEditorProblemsStatus); void updateUseNewDDC() { - appModel._useNewDDC.value = + appModel.useNewDDC.value = _hotReloadableChannels.contains(_channel.value); } @@ -344,13 +347,15 @@ class AppServices { } Future _performCompileAndAction({required bool reload}) async { + final willUseReload = reload && appModel.useNewDDC.value; + final source = appModel.sourceCodeController.text; - final progress = - appModel.editorStatus.showMessage(initialText: 'Compiling…'); + final progress = appModel.editorStatus + .showMessage(initialText: willUseReload ? 'Reloading…' : 'Compiling…'); try { CompileDDCResponse response; - if (!appModel._useNewDDC.value) { + if (!appModel.useNewDDC.value) { response = await _compileDDC(CompileRequest(source: source)); } else if (reload) { response = await _compileNewDDCReload(CompileRequest( @@ -366,7 +371,7 @@ class AppServices { modulesBaseUrl: response.modulesBaseUrl, engineVersion: appModel.runtimeVersions.value?.engineVersion, dartSource: source, - isNewDDC: appModel._useNewDDC.value, + isNewDDC: appModel.useNewDDC.value, reload: reload, ); appModel.currentDeltaDill.value = response.deltaDill; @@ -411,38 +416,38 @@ class AppServices { Future compile(CompileRequest request) async { try { - appModel.compilingBusy.value = true; + appModel.compilingBusy.value = CompilingState.compiling; return await services.compile(request); } finally { - appModel.compilingBusy.value = false; + appModel.compilingBusy.value = CompilingState.none; } } Future _compileDDC(CompileRequest request) async { try { - appModel.compilingBusy.value = true; + appModel.compilingBusy.value = CompilingState.compiling; return await services.compileDDC(request); } finally { - appModel.compilingBusy.value = false; + appModel.compilingBusy.value = CompilingState.none; } } Future _compileNewDDC(CompileRequest request) async { try { - appModel.compilingBusy.value = true; + appModel.compilingBusy.value = CompilingState.compiling; return await services.compileNewDDC(request); } finally { - appModel.compilingBusy.value = false; + appModel.compilingBusy.value = CompilingState.none; } } Future _compileNewDDCReload( CompileRequest request) async { try { - appModel.compilingBusy.value = true; + appModel.compilingBusy.value = CompilingState.reloading; return await services.compileNewDDCReload(request); } finally { - appModel.compilingBusy.value = false; + appModel.compilingBusy.value = CompilingState.none; } } @@ -477,12 +482,14 @@ class AppServices { appModel._usesPackageWeb = hasPackageWebImport(dartSource); appModel._recalcLayout(); - _executionService?.execute(javaScript, - modulesBaseUrl: modulesBaseUrl, - engineVersion: engineVersion, - reload: reload, - isNewDDC: isNewDDC, - isFlutter: appIsFlutter); + _executionService?.execute( + javaScript, + modulesBaseUrl: modulesBaseUrl, + engineVersion: engineVersion, + reload: reload, + isNewDDC: isNewDDC, + isFlutter: appIsFlutter, + ); } void dispose() { @@ -579,3 +586,13 @@ class SplitDragStateManager { } enum SplitDragState { inactive, active } + +enum CompilingState { + none(false), + compiling(true), + reloading(true); + + final bool busy; + + const CompilingState(this.busy); +}