diff --git a/app/assets/javascripts/discourse/app/initializers/colocated-template-overrides.js b/app/assets/javascripts/discourse/app/initializers/colocated-template-overrides.js index 0aed290e53..ce2df37071 100644 --- a/app/assets/javascripts/discourse/app/initializers/colocated-template-overrides.js +++ b/app/assets/javascripts/discourse/app/initializers/colocated-template-overrides.js @@ -15,20 +15,23 @@ GlimmerManager.getComponentTemplate = (component) => { export default { name: "colocated-template-overrides", - after: "populate-template-map", + after: ["populate-template-map", "mobile"], initialize(container) { - this.eachThemePluginTemplate((templateKey, moduleNames) => { - if (!templateKey.startsWith("components/")) { - return; - } + this.site = container.lookup("service:site"); - if (DiscourseTemplateMap.coreTemplates.has(templateKey)) { + this.eachThemePluginTemplate((templateKey, moduleNames, mobile) => { + if (!mobile && DiscourseTemplateMap.coreTemplates.has(templateKey)) { // It's a non-colocated core component. Template will be overridden at runtime. return; } - const componentName = templateKey.slice("components/".length); + let componentName = templateKey; + if (mobile) { + componentName = componentName.slice("mobile/".length); + } + componentName = componentName.slice("components/".length); + const component = container.owner.resolveRegistration( `component:${componentName}` ); @@ -43,12 +46,28 @@ export default { }, eachThemePluginTemplate(cb) { - for (const [key, value] of DiscourseTemplateMap.pluginTemplates) { - cb(key, value); + const { coreTemplates, pluginTemplates, themeTemplates } = + DiscourseTemplateMap; + + const orderedOverrides = [ + [pluginTemplates, "components/", false], + [themeTemplates, "components/", false], + ]; + + if (this.site.mobileView) { + orderedOverrides.push( + [coreTemplates, "mobile/components/", true], + [pluginTemplates, "mobile/components/", true], + [themeTemplates, "mobile/components/", true] + ); } - for (const [key, value] of DiscourseTemplateMap.themeTemplates) { - cb(key, value); + for (const [map, prefix, mobile] of orderedOverrides) { + for (const [key, value] of map) { + if (key.startsWith(prefix)) { + cb(key, value, mobile); + } + } } }, diff --git a/app/assets/javascripts/discourse/tests/integration/template-override-test.js b/app/assets/javascripts/discourse/tests/integration/template-override-test.js index b98d37b3b7..639be71d13 100644 --- a/app/assets/javascripts/discourse/tests/integration/template-override-test.js +++ b/app/assets/javascripts/discourse/tests/integration/template-override-test.js @@ -5,6 +5,7 @@ import { hbs } from "ember-cli-htmlbars"; import { registerTemporaryModule } from "../helpers/temporary-module-helper"; import { setComponentTemplate } from "@glimmer/manager"; import Component from "@glimmer/component"; +import { forceMobile, resetMobile } from "discourse/lib/mobile"; class MockColocatedComponent extends Component {} setComponentTemplate(hbs`Colocated Original`, MockColocatedComponent); @@ -22,6 +23,10 @@ function registerBaseComponents(namespace = "discourse") { `${namespace}/components/mock-colocated`, MockColocatedComponent ); + registerTemporaryModule( + `${namespace}/templates/mobile/components/mock-colocated`, + hbs`Core mobile template` + ); registerTemporaryModule( `${namespace}/components/mock-resolved`, MockResolvedComponent @@ -30,6 +35,10 @@ function registerBaseComponents(namespace = "discourse") { `${namespace}/templates/components/mock-resolved`, MockResolvedComponentTemplate ); + registerTemporaryModule( + `${namespace}/templates/mobile/components/mock-resolved`, + hbs`Core resolved mobile` + ); } function registerThemeOverrides() { @@ -37,10 +46,18 @@ function registerThemeOverrides() { "discourse/theme-12/discourse/templates/components/mock-colocated", hbs`Colocated Theme Override` ); + registerTemporaryModule( + `discourse/theme-12/discourse/templates/mobile/components/mock-colocated`, + hbs`Colocated Mobile Theme Override` + ); registerTemporaryModule( "discourse/theme-12/discourse/templates/components/mock-resolved", hbs`Resolved Theme Override` ); + registerTemporaryModule( + "discourse/theme-12/discourse/templates/mobile/components/mock-resolved", + hbs`Resolved Mobile Theme Override` + ); } function registerPluginOverrides() { @@ -81,6 +98,26 @@ module("Integration | Initializers | template-overrides", function () { }); }); + module("with core mobile overrides", function (hooks) { + hooks.beforeEach(() => { + registerBaseComponents(); + forceMobile(); + }); + hooks.afterEach(resetMobile); + + setupRenderingTest(hooks); + + test("core mobile overrides are used", async function () { + await render(TestTemplate); + assert + .dom("#mock-colocated") + .hasText("Core mobile template", "colocated component correct"); + assert + .dom("#mock-resolved") + .hasText("Core resolved mobile", "resolved component correct"); + }); + }); + module("with theme overrides", function (hooks) { hooks.beforeEach(() => registerBaseComponents()); hooks.beforeEach(registerThemeOverrides); @@ -97,6 +134,33 @@ module("Integration | Initializers | template-overrides", function () { }); }); + module("with mobile theme overrides", function (hooks) { + hooks.beforeEach(() => { + registerThemeOverrides(); + forceMobile(); + registerBaseComponents(); + }); + hooks.afterEach(resetMobile); + + setupRenderingTest(hooks); + + test("mobile theme overrides are used", async function () { + await render(TestTemplate); + assert + .dom("#mock-colocated") + .hasText( + "Colocated Mobile Theme Override", + "colocated component correct" + ); + assert + .dom("#mock-resolved") + .hasText( + "Resolved Mobile Theme Override", + "resolved component correct" + ); + }); + }); + module("with plugin overrides", function (hooks) { hooks.beforeEach(() => registerBaseComponents()); hooks.beforeEach(registerPluginOverrides);