diff --git a/app/components/course-page/test-results-bar/autofix-section/autofix-result.hbs b/app/components/course-page/test-results-bar/autofix-section/autofix-result.hbs index 40c68f2218..3b73622685 100644 --- a/app/components/course-page/test-results-bar/autofix-section/autofix-result.hbs +++ b/app/components/course-page/test-results-bar/autofix-section/autofix-result.hbs @@ -35,14 +35,9 @@ {{#if (eq @autofixRequest.status "in_progress")}}
-
- {{#if this.logstream}} - +
+ {{#if this.logstreamContent}} + {{/if}}
diff --git a/app/components/course-page/test-results-bar/autofix-section/autofix-result.ts b/app/components/course-page/test-results-bar/autofix-section/autofix-result.ts index 6d661b27de..8062656ca1 100644 --- a/app/components/course-page/test-results-bar/autofix-section/autofix-result.ts +++ b/app/components/course-page/test-results-bar/autofix-section/autofix-result.ts @@ -1,12 +1,10 @@ import AnalyticsEventTrackerService from 'codecrafters-frontend/services/analytics-event-tracker'; -import type Store from '@ember-data/store'; import { action } from '@ember/object'; import { service } from '@ember/service'; import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; -import Logstream from 'codecrafters-frontend/utils/logstream'; import type AutofixRequestModel from 'codecrafters-frontend/models/autofix-request'; -import type ActionCableConsumerService from 'codecrafters-frontend/services/action-cable-consumer'; +import type Logstream from 'codecrafters-frontend/utils/logstream'; interface Signature { Element: HTMLDivElement; @@ -17,40 +15,21 @@ interface Signature { } export default class AutofixResult extends Component { - @service declare store: Store; - @service declare actionCableConsumer: ActionCableConsumerService; @service declare analyticsEventTracker: AnalyticsEventTrackerService; - @tracked logstream: Logstream | null = null; @tracked shouldShowFullLog = false; + @tracked logstreamContent: string | null = null; @tracked diffIsBlurred = true; @action - handleDidUpdateAutofixRequestLogstreamId() { - if (this.logstream && this.args.autofixRequest.logstreamId !== this.logstream.logstreamId) { - this.logstream.unsubscribe(); - this.handleMarkdownStreamElementInserted(); // create a new logstream - } - } + handleLogstreamDidUpdate(logstream: Logstream): void { + this.logstreamContent = logstream.content; - @action - handleLogstreamDidPoll(): void { + // TODO: See if we're doing this too often? + // Ensure we also reload the autofix request to see whether the status has changed this.args.autofixRequest.reload(); } - @action - handleMarkdownStreamElementInserted() { - this.logstream = new Logstream(this.args.autofixRequest.logstreamId, this.actionCableConsumer, this.store, this.handleLogstreamDidPoll); - this.logstream.subscribe(); - } - - @action - handleWillDestroyMarkdownStreamElement() { - if (this.logstream) { - this.logstream.unsubscribe(); - } - } - @action toggleBlur() { if (this.diffIsBlurred) { diff --git a/app/modifiers/logstream-did-update.ts b/app/modifiers/logstream-did-update.ts new file mode 100644 index 0000000000..66cee61f43 --- /dev/null +++ b/app/modifiers/logstream-did-update.ts @@ -0,0 +1,50 @@ +// Invokes a callback when a logstream is updated. +// Usage:
+import type ActionCableConsumerService from 'codecrafters-frontend/services/action-cable-consumer'; +import type Store from '@ember-data/store'; +import Logstream from 'codecrafters-frontend/utils/logstream'; +import Modifier, { type ArgsFor } from 'ember-modifier'; +import { inject as service } from '@ember/service'; +import { registerDestructor } from '@ember/destroyable'; +import type { Owner } from '@ember/test-helpers/build-owner'; + +interface Signature { + Args: { + Positional: [(logstream: Logstream) => void, string]; + }; +} + +function cleanup(instance: LogstreamDidUpdateModifier) { + if (instance.logstream) { + instance.logstream.unsubscribe(); + instance.logstream = undefined; + } +} + +export default class LogstreamDidUpdateModifier extends Modifier { + @service declare actionCableConsumer: ActionCableConsumerService; + @service declare store: Store; + + logstream?: Logstream; + + constructor(owner: unknown, args: ArgsFor) { + super(owner as Owner, args); + registerDestructor(this, cleanup); + } + + modify(_element: HTMLElement, [callback, logstreamId]: Signature['Args']['Positional']) { + cleanup(this); + + this.logstream = new Logstream(logstreamId, this.actionCableConsumer, this.store, () => { + callback(this.logstream!); + }); + + this.logstream.subscribe(); + } +} + +declare module '@glint/environment-ember-loose/registry' { + export default interface Registry { + 'logstream-did-update': typeof LogstreamDidUpdateModifier; + } +} diff --git a/app/utils/logstream.ts b/app/utils/logstream.ts index 5da6785e7e..28585163b4 100644 --- a/app/utils/logstream.ts +++ b/app/utils/logstream.ts @@ -35,10 +35,6 @@ export default class Logstream { } subscribeTask = task({ drop: true }, async (): Promise => { - if (this.isSubscribed) { - return; - } - this.isTerminated = false; this.isSubscribed = false;