mirror of
https://github.com/discourse/discourse.git
synced 2026-08-07 03:35:32 -05:00
DEV: Introduce reactive JS API for viewport size (#32060)
Usage: ```js @service capabilities; ... this.capabilities.viewport.sm; // True when viewport is sm or larger this.capabilities.viewport.md; // True when viewport is md or larger // etc. ``` These booleans will update live when the browser is resized. Therefore, they should only be used in an autotracking context, so that Ember will re-render things appropriately when they change.
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
|
||||
export default class TrackedMediaQuery {
|
||||
@tracked matches;
|
||||
#matcher;
|
||||
|
||||
#handleChange = () => {
|
||||
this.matches = this.#matcher.matches;
|
||||
};
|
||||
|
||||
constructor(query) {
|
||||
this.#matcher = window.matchMedia(query);
|
||||
this.#matcher.addEventListener("change", this.#handleChange);
|
||||
this.matches = this.#matcher.matches;
|
||||
}
|
||||
|
||||
teardown() {
|
||||
this.#matcher.removeEventListener("change", this.#handleChange);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,19 @@
|
||||
import TrackedMediaQuery from "discourse/lib/tracked-media-query";
|
||||
|
||||
const APPLE_NAVIGATOR_PLATFORMS = /iPhone|iPod|iPad|Macintosh|MacIntel/;
|
||||
const APPLE_USER_AGENT_DATA_PLATFORM = /macOS/;
|
||||
|
||||
const ua = navigator.userAgent;
|
||||
|
||||
// Values match those in viewport.scss
|
||||
const breakpointQueries = {
|
||||
sm: new TrackedMediaQuery("(min-width: 40rem)"),
|
||||
md: new TrackedMediaQuery("(min-width: 48rem)"),
|
||||
lg: new TrackedMediaQuery("(min-width: 64rem)"),
|
||||
xl: new TrackedMediaQuery("(min-width: 80rem)"),
|
||||
"2xl": new TrackedMediaQuery("(min-width: 96rem)"),
|
||||
};
|
||||
|
||||
class Capabilities {
|
||||
touch = navigator.maxTouchPoints > 1 || "ontouchstart" in window;
|
||||
|
||||
@@ -37,6 +48,24 @@ class Capabilities {
|
||||
window.location.search.includes("discourse_app=1");
|
||||
isAppWebview = window.ReactNativeWebView !== undefined;
|
||||
|
||||
viewport = {
|
||||
get sm() {
|
||||
return breakpointQueries.sm.matches;
|
||||
},
|
||||
get md() {
|
||||
return breakpointQueries.md.matches;
|
||||
},
|
||||
get lg() {
|
||||
return breakpointQueries.lg.matches;
|
||||
},
|
||||
get xl() {
|
||||
return breakpointQueries.xl.matches;
|
||||
},
|
||||
get "2xl"() {
|
||||
return breakpointQueries["2xl"].matches;
|
||||
},
|
||||
};
|
||||
|
||||
get userHasBeenActive() {
|
||||
return (
|
||||
!("userActivation" in navigator) || navigator.userActivation.hasBeenActive
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable simple-import-sort/imports */
|
||||
import Application from "../app";
|
||||
import "./loader-shims";
|
||||
import "discourse/static/markdown-it";
|
||||
/* eslint-enable simple-import-sort/imports */
|
||||
|
||||
import { getOwner } from "@ember/owner";
|
||||
|
||||
@@ -1 +1 @@
|
||||
import "discourse/static/markdown-it";
|
||||
// We don't currently use this file, but it is require'd by ember-cli's test bundle
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe "capabilities service", type: :system do
|
||||
describe "viewport helpers" do
|
||||
it "works" do
|
||||
def matches(name)
|
||||
page.evaluate_script("Discourse.lookup('service:capabilities').viewport[#{name.to_json}]")
|
||||
end
|
||||
|
||||
visit "/"
|
||||
expect(page).to have_css("#site-logo")
|
||||
|
||||
expect(matches("sm")).to eq(true)
|
||||
expect(matches("lg")).to eq(true)
|
||||
|
||||
resize_window(width: 700) do
|
||||
try_until_success do
|
||||
expect(matches("sm")).to eq(true)
|
||||
expect(matches("lg")).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user