DEV: Make `capabilities` into a service (#18678)
This commit is contained in:
parent
d563b73202
commit
cbabc01e0e
|
@ -77,6 +77,12 @@ const DEPRECATED_MODULES = new Map(
|
|||
dropFrom: "3.0.0",
|
||||
silent: true,
|
||||
},
|
||||
"capabilities:main": {
|
||||
newName: "service:capabilities",
|
||||
since: "3.1.0.beta4",
|
||||
dropFrom: "3.2.0.beta1",
|
||||
silent: true,
|
||||
},
|
||||
"current-user:main": {
|
||||
newName: "service:current-user",
|
||||
since: "2.9.0.beta7",
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { inject as service } from "@ember/service";
|
||||
import { action } from "@ember/object";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default class SidebarFooter extends Component {
|
||||
@service capabilities;
|
||||
@service site;
|
||||
@service siteSettings;
|
||||
@service currentUser;
|
||||
|
||||
get capabilities() {
|
||||
return getOwner(this).lookup("capabilities:main");
|
||||
}
|
||||
|
||||
@action
|
||||
addSection() {
|
||||
showModal("sidebar-section-form");
|
||||
|
|
|
@ -20,7 +20,7 @@ export function autoLoadModules(container, registry) {
|
|||
let context = {
|
||||
siteSettings: container.lookup("service:site-settings"),
|
||||
keyValueStore: container.lookup("service:key-value-store"),
|
||||
capabilities: container.lookup("capabilities:main"),
|
||||
capabilities: container.lookup("service:capabilities"),
|
||||
currentUser: container.lookup("service:current-user"),
|
||||
site: container.lookup("service:site"),
|
||||
session: container.lookup("service:session"),
|
||||
|
|
|
@ -5,7 +5,8 @@ import deprecated from "discourse-common/lib/deprecated";
|
|||
|
||||
export default {
|
||||
name: "inject-objects",
|
||||
after: "export-application-global",
|
||||
after: "sniff-capabilities",
|
||||
|
||||
initialize(container, app) {
|
||||
// This is required for Ember CLI tests to work
|
||||
setDefaultOwner(app.__container__);
|
||||
|
|
|
@ -6,7 +6,7 @@ export default {
|
|||
|
||||
initialize(container) {
|
||||
const site = container.lookup("service:site");
|
||||
this.capabilities = container.lookup("capabilities:main");
|
||||
this.capabilities = container.lookup("service:capabilities");
|
||||
|
||||
if (!this.capabilities.isIpadOS && !site.mobileView) {
|
||||
return;
|
||||
|
|
|
@ -58,7 +58,7 @@ export default {
|
|||
{ id: "discourse-audio" }
|
||||
);
|
||||
|
||||
const caps = container.lookup("capabilities:main");
|
||||
const caps = container.lookup("service:capabilities");
|
||||
if (caps.isSafari || caps.isIOS) {
|
||||
api.decorateCookedElement(
|
||||
(elem) => {
|
||||
|
|
|
@ -7,7 +7,7 @@ export default {
|
|||
|
||||
initialize(container) {
|
||||
const siteSettings = container.lookup("service:site-settings");
|
||||
const capabilities = container.lookup("capabilities:main");
|
||||
const capabilities = container.lookup("service:capabilities");
|
||||
|
||||
if (siteSettings.composer_media_optimization_image_enabled) {
|
||||
// NOTE: There are various performance issues with the Canvas
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
export default {
|
||||
name: "sniff-capabilities",
|
||||
after: "export-application-global",
|
||||
|
||||
initialize(container) {
|
||||
const caps = container.lookup("service:capabilities");
|
||||
const html = document.documentElement;
|
||||
|
||||
if (caps.touch) {
|
||||
html.classList.add("touch", "discourse-touch");
|
||||
} else {
|
||||
html.classList.add("no-touch", "discourse-no-touch");
|
||||
}
|
||||
},
|
||||
};
|
|
@ -7,7 +7,7 @@ export default {
|
|||
after: "inject-objects",
|
||||
|
||||
initialize(container) {
|
||||
const caps = container.lookup("capabilities:main");
|
||||
const caps = container.lookup("service:capabilities");
|
||||
if (caps.isAppWebview) {
|
||||
window
|
||||
.matchMedia("(prefers-color-scheme: dark)")
|
||||
|
|
|
@ -58,6 +58,9 @@ export default {
|
|||
|
||||
app.register("location:discourse-location", DiscourseLocation);
|
||||
|
||||
app.inject("controller", "capabilities", "service:capabilities");
|
||||
app.inject("component", "capabilities", "service:capabilities");
|
||||
|
||||
ALL_TARGETS.forEach((t) => {
|
||||
app.inject(t, "appEvents", "service:app-events");
|
||||
app.inject(t, "pmTopicTrackingState", "service:pm-topic-tracking-state");
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
// Initializes an object that lets us know about browser's capabilities
|
||||
|
||||
const APPLE_NAVIGATOR_PLATFORMS = /iPhone|iPod|iPad|Macintosh|MacIntel/;
|
||||
|
||||
const APPLE_USERAGENTDATA_PLATFORM = /macOS/;
|
||||
|
||||
export default {
|
||||
name: "sniff-capabilities",
|
||||
|
||||
initialize(_, app) {
|
||||
const html = document.querySelector("html");
|
||||
const touch = navigator.maxTouchPoints > 1 || "ontouchstart" in window;
|
||||
const ua = navigator.userAgent;
|
||||
const caps = { touch };
|
||||
|
||||
if (touch) {
|
||||
html.classList.add("touch", "discourse-touch");
|
||||
} else {
|
||||
html.classList.add("no-touch", "discourse-no-touch");
|
||||
}
|
||||
|
||||
caps.isAndroid = ua.includes("Android");
|
||||
caps.isWinphone = ua.includes("Windows Phone");
|
||||
caps.isOpera = !!window.opera || ua.includes(" OPR/");
|
||||
caps.isFirefox = ua.includes("Firefox");
|
||||
caps.isChrome = !!window.chrome && !caps.isOpera;
|
||||
caps.isSafari =
|
||||
/Constructor/.test(window.HTMLElement) ||
|
||||
window.safari?.pushNotification.toString() ===
|
||||
"[object SafariRemoteNotification]";
|
||||
caps.isIpadOS = ua.includes("Mac OS") && !/iPhone|iPod/.test(ua) && touch;
|
||||
caps.isIOS =
|
||||
(/iPhone|iPod/.test(navigator.userAgent) || caps.isIpadOS) &&
|
||||
!window.MSStream;
|
||||
|
||||
caps.isApple =
|
||||
APPLE_NAVIGATOR_PLATFORMS.test(navigator.platform) ||
|
||||
(navigator.userAgentData &&
|
||||
APPLE_USERAGENTDATA_PLATFORM.test(navigator.userAgentData.platform));
|
||||
|
||||
caps.hasContactPicker =
|
||||
"contacts" in navigator && "ContactsManager" in window;
|
||||
caps.canVibrate = "vibrate" in navigator;
|
||||
caps.isPwa =
|
||||
window.matchMedia("(display-mode: standalone)").matches ||
|
||||
window.navigator.standalone ||
|
||||
document.referrer.includes("android-app://");
|
||||
|
||||
caps.isiOSPWA = caps.isPwa && caps.isIOS;
|
||||
|
||||
caps.wasLaunchedFromDiscourseHub =
|
||||
window.location.search.includes("discourse_app=1");
|
||||
caps.isAppWebview = window.ReactNativeWebView !== undefined;
|
||||
|
||||
// Inject it
|
||||
app.register("capabilities:main", caps, { instantiate: false });
|
||||
app.inject("view", "capabilities", "capabilities:main");
|
||||
app.inject("controller", "capabilities", "capabilities:main");
|
||||
app.inject("component", "capabilities", "capabilities:main");
|
||||
},
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
import Service from "@ember/service";
|
||||
|
||||
const APPLE_NAVIGATOR_PLATFORMS = /iPhone|iPod|iPad|Macintosh|MacIntel/;
|
||||
const APPLE_USER_AGENT_DATA_PLATFORM = /macOS/;
|
||||
|
||||
// Lets us know about browser's capabilities
|
||||
export default class Capabilities extends Service {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
const ua = navigator.userAgent;
|
||||
|
||||
this.touch = navigator.maxTouchPoints > 1 || "ontouchstart" in window;
|
||||
|
||||
this.isAndroid = ua.includes("Android");
|
||||
this.isWinphone = ua.includes("Windows Phone");
|
||||
this.isIpadOS =
|
||||
ua.includes("Mac OS") && !/iPhone|iPod/.test(ua) && this.touch;
|
||||
this.isIOS =
|
||||
(/iPhone|iPod/.test(navigator.userAgent) || this.isIpadOS) &&
|
||||
!window.MSStream;
|
||||
this.isApple =
|
||||
APPLE_NAVIGATOR_PLATFORMS.test(navigator.platform) ||
|
||||
(navigator.userAgentData &&
|
||||
APPLE_USER_AGENT_DATA_PLATFORM.test(navigator.userAgentData.platform));
|
||||
|
||||
this.isOpera = !!window.opera || ua.includes(" OPR/");
|
||||
this.isFirefox = ua.includes("Firefox");
|
||||
this.isChrome = !!window.chrome && !this.isOpera;
|
||||
this.isSafari =
|
||||
/Constructor/.test(window.HTMLElement) ||
|
||||
window.safari?.pushNotification.toString() ===
|
||||
"[object SafariRemoteNotification]";
|
||||
|
||||
this.hasContactPicker =
|
||||
"contacts" in navigator && "ContactsManager" in window;
|
||||
this.canVibrate = "vibrate" in navigator;
|
||||
this.isPwa =
|
||||
window.matchMedia("(display-mode: standalone)").matches ||
|
||||
window.navigator.standalone ||
|
||||
document.referrer.includes("android-app://");
|
||||
this.isiOSPWA = this.isPwa && this.isIOS;
|
||||
this.wasLaunchedFromDiscourseHub =
|
||||
window.location.search.includes("discourse_app=1");
|
||||
this.isAppWebview = window.ReactNativeWebView !== undefined;
|
||||
}
|
||||
}
|
|
@ -147,7 +147,7 @@ export default class Widget {
|
|||
this.site = register.lookup("service:site");
|
||||
this.siteSettings = register.lookup("service:site-settings");
|
||||
this.currentUser = register.lookup("service:current-user");
|
||||
this.capabilities = register.lookup("capabilities:main");
|
||||
this.capabilities = register.lookup("service:capabilities");
|
||||
this.store = register.lookup("service:store");
|
||||
this.appEvents = register.lookup("service:app-events");
|
||||
this.keyValueStore = register.lookup("service:key-value-store");
|
||||
|
|
|
@ -114,7 +114,7 @@ acceptance(
|
|||
});
|
||||
|
||||
test("button to toggle between mobile and desktop view on touch devices ", async function (assert) {
|
||||
const capabilities = this.container.lookup("capabilities:main");
|
||||
const capabilities = this.container.lookup("service:capabilities");
|
||||
capabilities.touch = true;
|
||||
|
||||
await visit("/");
|
||||
|
|
|
@ -18,7 +18,6 @@ import {
|
|||
} from "discourse/lib/user-presence";
|
||||
import isZoomed from "discourse/plugins/chat/discourse/lib/zoom-check";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
|
||||
const PAGE_SIZE = 50;
|
||||
const PAST = "past";
|
||||
|
@ -26,6 +25,7 @@ const FUTURE = "future";
|
|||
const READ_INTERVAL_MS = 1000;
|
||||
|
||||
export default class ChatLivePane extends Component {
|
||||
@service capabilities;
|
||||
@service chat;
|
||||
@service chatChannelsManager;
|
||||
@service router;
|
||||
|
@ -136,10 +136,6 @@ export default class ChatLivePane extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
get capabilities() {
|
||||
return getOwner(this).lookup("capabilities:main");
|
||||
}
|
||||
|
||||
@debounce(100)
|
||||
fetchMessages(options = {}) {
|
||||
if (this._selfDeleted) {
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import discourseLater from "discourse-common/lib/later";
|
||||
import { action } from "@ember/object";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
import { inject as service } from "@ember/service";
|
||||
|
||||
export default class ChatMessageActionsMobile extends Component {
|
||||
@service capabilities;
|
||||
|
||||
@tracked hasExpandedReply = false;
|
||||
@tracked showFadeIn = false;
|
||||
|
||||
messageActions = null;
|
||||
|
||||
get capabilities() {
|
||||
return getOwner(this).lookup("capabilities:main");
|
||||
}
|
||||
|
||||
@action
|
||||
fadeAndVibrate() {
|
||||
discourseLater(this.#addFadeIn.bind(this));
|
||||
|
|
|
@ -16,7 +16,6 @@ import isZoomed from "discourse/plugins/chat/discourse/lib/zoom-check";
|
|||
import showModal from "discourse/lib/show-modal";
|
||||
import ChatMessageFlag from "discourse/plugins/chat/discourse/lib/chat-message-flag";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import ChatMessageReaction from "discourse/plugins/chat/discourse/models/chat-message-reaction";
|
||||
|
||||
let _chatMessageDecorators = [];
|
||||
|
@ -38,6 +37,7 @@ export default class ChatMessage extends Component {
|
|||
@service dialog;
|
||||
@service currentUser;
|
||||
@service appEvents;
|
||||
@service capabilities;
|
||||
@service chat;
|
||||
@service chatEmojiReactionStore;
|
||||
@service chatEmojiPickerManager;
|
||||
|
@ -482,10 +482,6 @@ export default class ChatMessage extends Component {
|
|||
this.react(emoji, REACTIONS.add);
|
||||
}
|
||||
|
||||
get capabilities() {
|
||||
return getOwner(this).lookup("capabilities:main");
|
||||
}
|
||||
|
||||
@action
|
||||
react(emoji, reactAction) {
|
||||
if (!this.args.canInteractWithChat) {
|
||||
|
|
Loading…
Reference in New Issue