blob: 111db54056eaebfd6ff845fcec8e33c6db5f4a09 [file]
import 'dart:async';
import 'package:jaspr/dom.dart';
import 'package:jaspr/jaspr.dart';
import '../../../utils/provider.dart';
import '../../../utils/styles.dart';
import '../../workspace/data/workspace_repository.dart';
class AnalysisStatus extends StatefulComponent {
const AnalysisStatus({super.key});
@override
State<AnalysisStatus> createState() => _AnalysisStatusState();
@css
static List<StyleRule> get styles => _AnalysisStatusState.styles;
}
class _AnalysisStatusState extends State<AnalysisStatus> {
StreamSubscription<bool>? _subscription;
Timer? _debounceTimer;
bool _showAnalyzing = false;
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_subscription == null) {
final WorkspaceRepository repo = context.get<WorkspaceRepository>();
_subscription = repo.languageServerClient.codeMirrorLspClient.analysisStatus.listen(_handleStatusChange);
}
}
void _handleStatusChange(bool isAnalyzing) {
_debounceTimer?.cancel();
if (isAnalyzing) {
_debounceTimer = Timer(const Duration(milliseconds: 100), () {
setState(() {
_showAnalyzing = true;
});
});
} else {
setState(() {
_showAnalyzing = false;
});
}
}
@override
void dispose() {
_subscription?.cancel();
_debounceTimer?.cancel();
super.dispose();
}
@override
Component build(BuildContext context) {
return div(
classes: 'analysis-status',
styles: Styles(
display: _showAnalyzing ? Display.flex : Display.none,
),
[
const div(classes: 'analysis-status-spinner', []),
const span(classes: 'analysis-status-text', [.text('Analyzing...')]),
],
);
}
static List<StyleRule> get styles => [
css.keyframes('spin', {
'0%': const Styles(raw: {'transform': 'rotate(0deg)'}),
'100%': const Styles(raw: {'transform': 'rotate(360deg)'}),
}),
css('.analysis-status').styles(
display: Display.flex,
padding: Padding.symmetric(horizontal: 12.px, vertical: 8.px),
border: Border.only(
top: BorderSide.solid(
color: colorBorder,
width: 1.px,
),
),
userSelect: UserSelect.none,
alignItems: AlignItems.center,
gap: Gap.all(8.px),
color: colorOnSurfaceVariant,
fontSize: 11.px,
fontWeight: FontWeight.w500,
raw: {'flex-shrink': '0'},
),
css('.analysis-status-spinner').styles(
width: 12.px,
height: 12.px,
border: Border.all(color: colorPrimary.withOpacity(0.3), width: 2.px),
raw: {
'border-top-color': 'var(--color-primary)',
'border-radius': '50%',
'animation': 'spin 1s linear infinite',
},
),
];
}