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

Set browser tab title based on stack item #1803

Merged
9 changes: 9 additions & 0 deletions packages/host/app/lib/stack-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ export class StackItem {
throw new Error(`This StackItem has no card set`);
}

get title() {
if (this.newCard) {
return this.newCard.title;
} else if (this.cardResource?.card) {
return this.cardResource.card.title;
}
return undefined;
}

get cardError() {
return this.cardResource?.cardError?.error;
}
Expand Down
18 changes: 17 additions & 1 deletion packages/host/app/services/operator-mode-state-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type RouterService from '@ember/routing/router-service';
import { scheduleOnce } from '@ember/runloop';
import Service, { service } from '@ember/service';

import { tracked } from '@glimmer/tracking';
import { tracked, cached } from '@glimmer/tracking';

import { restartableTask, task } from 'ember-concurrency';
import { mergeWith } from 'lodash';
Expand Down Expand Up @@ -344,6 +344,18 @@ export default class OperatorModeStateService extends Service {
});
}

@cached
get title() {
if (this.state.submode === Submodes.Code) {
return `${this.codePathRelativeToRealm} in ${
this.realm.info(this.realmURL.href).name
}`;
} else {
let itemForTitle = this.topMostStackItems().pop(); // top-most card of right stack
return itemForTitle?.title ?? 'Boxel';
}
}

private updateOpenDirsForNestedPath() {
let localPath = this.codePathRelativeToRealm;

Expand Down Expand Up @@ -392,6 +404,10 @@ export default class OperatorModeStateService extends Service {

private persist() {
this.operatorModeController.operatorModeState = this.serialize();
// This sets the title of the document for it's appearance in the browser
// history (which needs to happen after the history pushState)--the
// afterRender is the perfect place for this
document.title = this.title;
}

// Serialized POJO version of state, with only cards that have been saved.
Expand Down
7 changes: 7 additions & 0 deletions packages/host/app/templates/index.gts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import Component from '@glimmer/component';

import { pageTitle } from 'ember-page-title';

import RouteTemplate from 'ember-route-template';

import OperatorModeContainer from '../components/operator-mode/container';

import type OperatorModeStateService from '../services/operator-mode-state-service';

class IndexComponent extends Component<void> {
@service private declare operatorModeStateService: OperatorModeStateService;
// Remove this and onClose argument in OperatorModeContainer once we remove host mode and the card route, where closing operator mode will not be a thing anymore
@action closeOperatorMode() {
// noop
}

<template>
{{pageTitle this.operatorModeStateService.title}}
<div>
<OperatorModeContainer @onClose={{this.closeOperatorMode}} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
waitUntil,
} from '@ember/test-helpers';

import { getPageTitle } from 'ember-page-title/test-support';
import window from 'ember-window-mock';
import { module, test } from 'qunit';

Expand Down Expand Up @@ -407,6 +408,7 @@ module('Acceptance | operator mode tests', function (hooks) {

assert.dom('[data-test-operator-mode-stack]').exists();
assert.dom('[data-test-stack-card-index="0"]').exists(); // Index card opens in the stack
assert.strictEqual(getPageTitle(), 'Test Workspace B');
await click('[data-test-boxel-filter-list-button="All Cards"]');

await waitFor(`[data-test-cards-grid-item="${testRealmURL}Pet/mango"]`);
Expand Down Expand Up @@ -460,6 +462,7 @@ module('Acceptance | operator mode tests', function (hooks) {
],
submode: Submodes.Interact,
});
assert.strictEqual(getPageTitle(), 'Mango');
});

test('can open code submode when card or field has no embedded template', async function (assert) {
Expand Down Expand Up @@ -500,6 +503,10 @@ module('Acceptance | operator mode tests', function (hooks) {
assert.operatorModeParametersMatch(currentURL(), {
codePath: `${testRealmURL}address-with-no-embedded-template.gts`,
});
assert.strictEqual(
getPageTitle(),
`address-with-no-embedded-template.gts in Test Workspace B`,
);
});

test('open workspace chooser when boxel icon is clicked', async function (assert) {
Expand Down