DEV: Convert software-update-prompt to glimmer/gjs/dbutton (#28341)

This commit is contained in:
Jarek Radosz 2024-08-13 15:47:14 +02:00 committed by GitHub
parent eccfc946f1
commit 8a09fd370a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 122 additions and 128 deletions

View File

@ -0,0 +1,117 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { cancel } from "@ember/runloop";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import concatClass from "discourse/helpers/concat-class";
import { isTesting } from "discourse-common/config/environment";
import i18n from "discourse-common/helpers/i18n";
import discourseLater from "discourse-common/lib/later";
import { bind } from "discourse-common/utils/decorators";
export default class SoftwareUpdatePrompt extends Component {
@service messageBus;
@service session;
@tracked showPrompt = false;
@tracked animatePrompt = false;
timeoutHandler;
constructor() {
super(...arguments);
this.messageBus.subscribe("/refresh_client", this.onRefresh);
this.messageBus.subscribe("/global/asset-version", this.onAsset);
}
willDestroy() {
super.willDestroy(...arguments);
this.messageBus.unsubscribe("/refresh_client", this.onRefresh);
this.messageBus.unsubscribe("/global/asset-version", this.onAsset);
cancel(this.timeoutHandler);
}
@bind
onRefresh() {
this.session.requiresRefresh = true;
}
@bind
onAsset(version) {
if (this.session.assetVersion !== version) {
this.session.requiresRefresh = true;
}
if (!this.timeoutHandler && this.session.requiresRefresh) {
if (isTesting()) {
this.updatePromptState(true);
} else {
// Since we can do this transparently for people browsing the forum
// hold back the message 24 hours.
this.timeoutHandler = discourseLater(
() => this.updatePromptState(true),
1000 * 60 * 24 * 60
);
}
}
}
updatePromptState(value) {
// when adding the message, we inject the HTML then add the animation
// when dismissing, things need to happen in the opposite order
const firstProp = value ? "showPrompt" : "animatePrompt";
const secondProp = value ? "animatePrompt" : "showPrompt";
this[firstProp] = value;
if (isTesting()) {
this[secondProp] = value;
} else {
discourseLater(() => (this[secondProp] = value), 500);
}
}
@action
refreshPage() {
document.location.reload();
}
@action
dismiss() {
this.updatePromptState(false);
}
<template>
{{#if this.showPrompt}}
<div
class={{concatClass
"software-update-prompt"
(if this.animatePrompt "require-software-refresh")
}}
>
<div class="wrap">
<div aria-live="polite" class="update-prompt-main-content">
<DButton
@action={{this.refreshPage}}
@icon="redo"
@label="software_update_prompt.message"
class="btn-transparent update-prompt-message"
/>
<span class="update-prompt-dismiss">
<DButton
@action={{this.dismiss}}
@icon="times"
aria-label={{i18n "software_update_prompt.dismiss"}}
class="btn-transparent"
/>
</span>
</div>
</div>
</div>
{{/if}}
</template>
}

View File

@ -1,24 +0,0 @@
{{#if this.showPrompt}}
<div
class="software-update-prompt{{if
this.animatePrompt
' require-software-refresh'
}}"
>
<div class="wrap">
<div class="update-prompt-main-content" aria-live="polite">
<span
role="button"
onclick={{action "refreshPage"}}
class="update-prompt-message"
>{{d-icon "redo"}}
{{html-safe (i18n "software_update_prompt.message")}}</span>
<span class="update-prompt-dismiss"><span
aria-label={{i18n "software_update_prompt.dismiss"}}
role="button"
onclick={{action "dismiss"}}
>{{d-icon "times"}}</span></span>
</div>
</div>
</div>
{{/if}}

View File

@ -1,90 +0,0 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { cancel } from "@ember/runloop";
import { isTesting } from "discourse-common/config/environment";
import getURL from "discourse-common/lib/get-url";
import discourseLater from "discourse-common/lib/later";
import discourseComputed, { bind, on } from "discourse-common/utils/decorators";
export default Component.extend({
tagName: "",
showPrompt: false,
animatePrompt: false,
_timeoutHandler: null,
init() {
this._super(...arguments);
this.messageBus.subscribe("/refresh_client", this.onRefresh);
this.messageBus.subscribe("/global/asset-version", this.onAsset);
},
willDestroy() {
this._super(...arguments);
this.messageBus.unsubscribe("/refresh_client", this.onRefresh);
this.messageBus.unsubscribe("/global/asset-version", this.onAsset);
},
@bind
onRefresh() {
this.session.requiresRefresh = true;
},
@bind
onAsset(version) {
if (this.session.assetVersion !== version) {
this.session.requiresRefresh = true;
}
if (!this._timeoutHandler && this.session.requiresRefresh) {
if (isTesting()) {
this.updatePromptState(true);
} else {
// Since we can do this transparently for people browsing the forum
// hold back the message 24 hours.
this._timeoutHandler = discourseLater(() => {
this.updatePromptState(true);
}, 1000 * 60 * 24 * 60);
}
}
},
@discourseComputed
rootUrl() {
return getURL("/");
},
updatePromptState(value) {
// when adding the message, we inject the HTML then add the animation
// when dismissing, things need to happen in the opposite order
const firstProp = value ? "showPrompt" : "animatePrompt",
secondProp = value ? "animatePrompt" : "showPrompt";
this.set(firstProp, value);
if (isTesting()) {
this.set(secondProp, value);
} else {
discourseLater(() => {
this.set(secondProp, value);
}, 500);
}
},
@action
refreshPage() {
document.location.reload();
},
@action
dismiss() {
this.updatePromptState(false);
},
@on("willDestroyElement")
_resetTimeoutHandler() {
this._timeoutHandler && cancel(this._timeoutHandler);
this._timeoutHandler = null;
},
});

View File

@ -5,7 +5,6 @@
left: 0;
top: var(--header-offset, 60px);
background-color: var(--tertiary-low);
color: var(--tertiary);
max-height: 0;
overflow: hidden;
transition: max-height 0.3s;
@ -20,15 +19,15 @@
}
.update-prompt-message {
cursor: pointer;
color: var(--tertiary);
padding: 0.75em 0;
.d-icon {
margin-right: 0.33em;
color: var(--tertiary);
font-size: 0.9em;
}
span {
.d-button-label > span {
text-decoration: underline;
}
}
@ -39,16 +38,8 @@
height: 44px;
flex: 1;
span {
cursor: pointer;
height: 100%;
display: flex;
align-items: center;
padding-left: 20px;
&:hover {
color: var(--tertiary-hover);
}
.d-icon {
color: var(--tertiary);
}
}