1
0
mirror of https://github.com/flarum/core.git synced 2025-08-01 22:20:21 +02:00

Merge pull request #3228 from flarum/as/v1.2_frontend_fixes

Some v1.2 frontend fixes
This commit is contained in:
Alexander Skvortsov
2021-12-27 20:24:53 -05:00
committed by GitHub
7 changed files with 52 additions and 22 deletions

View File

@@ -9,6 +9,7 @@ import Translator from './Translator';
import Store, { ApiPayload, ApiResponse, ApiResponsePlural, ApiResponseSingle, payloadIsPlural } from './Store'; import Store, { ApiPayload, ApiResponse, ApiResponsePlural, ApiResponseSingle, payloadIsPlural } from './Store';
import Session from './Session'; import Session from './Session';
import extract from './utils/extract'; import extract from './utils/extract';
import extractText from './utils/extractText';
import Drawer from './utils/Drawer'; import Drawer from './utils/Drawer';
import mapRoutes from './utils/mapRoutes'; import mapRoutes from './utils/mapRoutes';
import RequestError, { InternalFlarumRequestOptions } from './utils/RequestError'; import RequestError, { InternalFlarumRequestOptions } from './utils/RequestError';
@@ -365,9 +366,21 @@ export default class Application {
updateTitle(): void { updateTitle(): void {
const count = this.titleCount ? `(${this.titleCount}) ` : ''; const count = this.titleCount ? `(${this.titleCount}) ` : '';
const pageTitleWithSeparator = this.title && m.route.get() !== this.forum.attribute('basePath') + '/' ? this.title + ' - ' : ''; const onHomepage = m.route.get() === this.forum.attribute('basePath') + '/';
const title = this.forum.attribute('title');
document.title = count + pageTitleWithSeparator + title; const params = {
pageTitle: this.title,
forumName: this.forum.attribute('title'),
// Until we add page numbers to the frontend, this is constant at 1
// so that the page number portion doesn't show up in the URL.
pageNumber: 1,
};
const title =
onHomepage || !this.title
? extractText(app.translator.trans('core.lib.meta_titles.without_page_title', params))
: extractText(app.translator.trans('core.lib.meta_titles.with_page_title', params));
document.title = count + title;
} }
protected transformRequestOptions<ResponseType>(flarumOptions: FlarumRequestOptions<ResponseType>): InternalFlarumRequestOptions<ResponseType> { protected transformRequestOptions<ResponseType>(flarumOptions: FlarumRequestOptions<ResponseType>): InternalFlarumRequestOptions<ResponseType> {

View File

@@ -24,16 +24,19 @@ export default class ModalManager extends Component<IModalManagerAttrs> {
view(vnode: Mithril.VnodeDOM<IModalManagerAttrs, this>): Mithril.Children { view(vnode: Mithril.VnodeDOM<IModalManagerAttrs, this>): Mithril.Children {
const modal = this.attrs.state.modal; const modal = this.attrs.state.modal;
const Tag = modal?.componentClass;
return ( return (
<div className="ModalManager modal fade"> <div className="ModalManager modal fade">
{!!modal && {!!Tag && (
modal.componentClass.component({ <Tag
...modal.attrs, key={modal?.key}
animateShow: this.animateShow.bind(this), {...modal.attrs}
animateHide: this.animateHide.bind(this), animateShow={this.animateShow.bind(this)}
state: this.attrs.state, animateHide={this.animateHide.bind(this)}
})} state={this.attrs.state}
/>
)}
</div> </div>
); );
} }

View File

@@ -22,8 +22,15 @@ export default class ModalManagerState {
modal: null | { modal: null | {
componentClass: UnsafeModalClass; componentClass: UnsafeModalClass;
attrs?: Record<string, unknown>; attrs?: Record<string, unknown>;
key: number;
} = null; } = null;
/**
* Used to force re-initialization of modals if a modal
* is replaced by another of the same type.
*/
private key = 0;
private closeTimeout?: NodeJS.Timeout; private closeTimeout?: NodeJS.Timeout;
/** /**
@@ -48,7 +55,7 @@ export default class ModalManagerState {
if (this.closeTimeout) clearTimeout(this.closeTimeout); if (this.closeTimeout) clearTimeout(this.closeTimeout);
this.modal = { componentClass, attrs }; this.modal = { componentClass, attrs, key: this.key++ };
m.redraw.sync(); m.redraw.sync();
} }

View File

@@ -27,7 +27,10 @@ export default class Drawer {
}); });
this.appElement = document.getElementById('app'); this.appElement = document.getElementById('app');
this.focusTrap = createFocusTrap('#drawer', { allowOutsideClick: true }); // Despite the `focus-trap` documentation, both `clickOutsideDeactivates`
// and `allowOutsideClick` are necessary so that inputs in modals triggered
// from the drawer's nav components can be interacted with.
this.focusTrap = createFocusTrap('#drawer', { allowOutsideClick: true, clickOutsideDeactivates: true });
this.drawerAvailableMediaQuery = window.matchMedia( this.drawerAvailableMediaQuery = window.matchMedia(
`(max-width: ${getComputedStyle(document.documentElement).getPropertyValue('--screen-phone-max')})` `(max-width: ${getComputedStyle(document.documentElement).getPropertyValue('--screen-phone-max')})`
); );

View File

@@ -88,7 +88,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
/** /**
* An array of SearchSources. * An array of SearchSources.
*/ */
protected sources!: SearchSource[]; protected sources?: SearchSource[];
/** /**
* The number of sources that are still loading results. * The number of sources that are still loading results.
@@ -192,7 +192,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
this.setIndex(this.getCurrentNumericIndex()); this.setIndex(this.getCurrentNumericIndex());
// If there are no sources, the search view is not shown. // If there are no sources, the search view is not shown.
if (!this.sources.length) return; if (!this.sources?.length) return;
this.updateMaxHeight(); this.updateMaxHeight();
} }
@@ -200,6 +200,10 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
oncreate(vnode: Mithril.VnodeDOM<T, this>) { oncreate(vnode: Mithril.VnodeDOM<T, this>) {
super.oncreate(vnode); super.oncreate(vnode);
// If there are no sources, we shouldn't initialize logic for
// search elements, as they will not be shown.
if (!this.sources?.length) return;
const search = this; const search = this;
const state = this.searchState; const state = this.searchState;
@@ -237,7 +241,7 @@ export default class Search<T extends SearchAttrs = SearchAttrs> extends Compone
if (state.isCached(query)) return; if (state.isCached(query)) return;
if (query.length >= (search.constructor as typeof Search).MIN_SEARCH_LEN) { if (query.length >= (search.constructor as typeof Search).MIN_SEARCH_LEN) {
search.sources.map((source) => { search.sources?.map((source) => {
if (!source.search) return; if (!source.search) return;
search.loadingSources++; search.loadingSources++;

View File

@@ -542,6 +542,11 @@ core:
loading_indicator: loading_indicator:
accessible_label: => core.ref.loading accessible_label: => core.ref.loading
# Translations in this namespace are used to format page meta titles.
meta_titles:
with_page_title: "{pageNumber, plural, =1 {{pageTitle} - {forumName}} other {{pageTitle}: Page # - {forumName}}}"
without_page_title: "{pageNumber, plural, =1 {{forumName}} other {Page # - {forumName}}}"
# These translations are used in modals. # These translations are used in modals.
modal: modal:
close: Close close: Close
@@ -628,11 +633,6 @@ core:
submit_button: => core.ref.save_changes submit_button: => core.ref.save_changes
title: => core.ref.reset_your_password title: => core.ref.reset_your_password
# Translations in this namespace are used to format page meta titles.
meta_titles:
with_page_title: "{pageNumber, plural, =1 {{pageTitle} - {forumName}} other {{pageTitle}: Page # - {forumName}}}"
without_page_title: "{pageNumber, plural, =1 {{forumName}} other {Page # - {forumName}}}"
# Translations in this namespace are used in messages output by the API. # Translations in this namespace are used in messages output by the API.
api: api:
invalid_username_message: "The username may only contain letters, numbers, and dashes." invalid_username_message: "The username may only contain letters, numbers, and dashes."

View File

@@ -37,7 +37,7 @@ class BasicTitleDriver implements TitleDriverInterface
]; ];
return $onHomePage || ! $document->title return $onHomePage || ! $document->title
? $this->translator->trans('core.views.meta_titles.without_page_title', $params) ? $this->translator->trans('core.lib.meta_titles.without_page_title', $params)
: $this->translator->trans('core.views.meta_titles.with_page_title', $params); : $this->translator->trans('core.lib.meta_titles.with_page_title', $params);
} }
} }