mirror of
https://github.com/discourse/discourse.git
synced 2025-01-19 03:22:46 +08:00
DEV: Refactor user-tip to avoid unneeded wrapper element (#29365)
We were using a modifier purely for its lifecycle hooks - not to modify an element. This commit switches to using a helper, which provides a similar lifecycle, but without needing to be attached to an element.
This commit is contained in:
parent
adef7081a2
commit
c6c09db5b0
|
@ -4,6 +4,7 @@ import { schedule } from "@ember/runloop";
|
|||
import { service } from "@ember/service";
|
||||
import { modifier } from "ember-modifier";
|
||||
import UserTipContainer from "discourse/components/user-tip-container";
|
||||
import helperFn from "discourse/helpers/helper-fn";
|
||||
import escape from "discourse-common/lib/escape";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import I18n from "discourse-i18n";
|
||||
|
@ -14,7 +15,7 @@ export default class UserTip extends Component {
|
|||
@service userTips;
|
||||
@service tooltip;
|
||||
|
||||
registerTip = modifier(() => {
|
||||
registerTip = helperFn((_, on) => {
|
||||
const tip = {
|
||||
id: this.args.id,
|
||||
priority: this.args.priority ?? 0,
|
||||
|
@ -22,9 +23,9 @@ export default class UserTip extends Component {
|
|||
|
||||
this.userTips.addAvailableTip(tip);
|
||||
|
||||
return () => {
|
||||
on.cleanup(() => {
|
||||
this.userTips.removeAvailableTip(tip);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
tip = modifier((element) => {
|
||||
|
@ -82,10 +83,9 @@ export default class UserTip extends Component {
|
|||
}
|
||||
|
||||
<template>
|
||||
<div {{this.registerTip}}>
|
||||
{{#if this.shouldRenderTip}}
|
||||
<span {{this.tip}}></span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{this.registerTip}}
|
||||
{{#if this.shouldRenderTip}}
|
||||
<span {{this.tip}}></span>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
||||
|
|
50
app/assets/javascripts/discourse/app/helpers/helper-fn.js
Normal file
50
app/assets/javascripts/discourse/app/helpers/helper-fn.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
import Helper from "@ember/component/helper";
|
||||
import { registerDestructor } from "@ember/destroyable";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
|
||||
/**
|
||||
* Build an Ember helper with cleanup logic. The passed function will be called with the named argument,
|
||||
* and an 'on' utility object which allows you to register a cleanup function via `on.cleanup(...)`.
|
||||
*
|
||||
* Whenever any autotracked state is changed, the cleanup function will be run, and your function
|
||||
* will be re-evaluated.
|
||||
*
|
||||
* @param {(args: object, on: { cleanup: () => void } ) => any} fn - The helper function.
|
||||
*/
|
||||
export default function helperFn(callback) {
|
||||
return class extends Helper {
|
||||
cleanupFn = null;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
registerDestructor(this, this.cleanup);
|
||||
}
|
||||
|
||||
compute(positional, named) {
|
||||
if (positional.length) {
|
||||
throw new Error(
|
||||
"Positional arguments are not permitted for helperFn-defined helpers. Use named arguments instead."
|
||||
);
|
||||
}
|
||||
|
||||
this.cleanup();
|
||||
|
||||
const on = {
|
||||
cleanup: (fn) => {
|
||||
if (this.cleanupFn) {
|
||||
throw new Error("on.cleanup can only be called once");
|
||||
}
|
||||
this.cleanupFn = fn;
|
||||
},
|
||||
};
|
||||
|
||||
return callback(named, on);
|
||||
}
|
||||
|
||||
@bind
|
||||
cleanup() {
|
||||
this.cleanupFn?.();
|
||||
this.cleanupFn = null;
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user