mirror of
https://github.com/flarum/core.git
synced 2025-07-20 08:11:27 +02:00
Mithril 2 update (#2255)
* Update frontend to Mithril 2 - Update Mithril version to v2.0.4 - Add Typescript typings for Mithril - Rename "props" to "attrs"; "initProps" to "initAttrs"; "m.prop" to "m.stream"; "m.withAttr" to "utils/withAttr". - Use Mithril 2's new lifecycle hooks - SubtreeRetainer has been rewritten to be more useful for the new system - Utils for forcing page re-initializations have been added (force attr in links, setRouteWithForcedRefresh util) - Other mechanical changes, following the upgrade guide - Remove some of the custom stuff in our Component base class - Introduce "fragments" for non-components that control their own DOM - Remove Mithril patches, introduce a few new ones (route attrs in <a>; - Redesign AlertManagerState `show` with 3 overloads: `show(children)`, `show(attrs, children)`, `show(componentClass, attrs, children)` - The `affixedSidebar` util has been replaced with an `AffixedSidebar` component Challenges: - `children` and `tag` are now reserved, and can not be used as attr names - Behavior of links to current page changed in Mithril. If moving to a page that is handled by the same component, the page component WILL NOT be re-initialized by default. Additional code to keep track of the current url is needed (See IndexPage, DiscussionPage, and UserPage for examples) - Native Promise rejections are shown on console when not handled - Instances of components can no longer be stored. The state pattern should be used instead. Refs #1821. Co-authored-by: Alexander Skvortsov <sasha.skvortsov109@gmail.com> Co-authored-by: Matthew Kilgore <tankerkiller125@gmail.com> Co-authored-by: Franz Liedke <franz@develophp.org>
This commit is contained in:
committed by
GitHub
parent
1321b8cc28
commit
71f3379fcc
@@ -1,27 +1,60 @@
|
||||
import Component from '../Component';
|
||||
import Stream from 'mithril/stream';
|
||||
import extract from './extract';
|
||||
|
||||
export default function patchMithril(global) {
|
||||
const mo = global.m;
|
||||
const defaultMithril = global.m;
|
||||
|
||||
const m = function (comp, ...args) {
|
||||
if (comp.prototype && comp.prototype instanceof Component) {
|
||||
let children = args.slice(1);
|
||||
if (children.length === 1 && Array.isArray(children[0])) {
|
||||
children = children[0];
|
||||
/**
|
||||
* If the href URL of the link is the same as the current page path
|
||||
* we will not add a new entry to the browser history.
|
||||
*
|
||||
* This allows us to still refresh the Page component
|
||||
* without adding endless history entries.
|
||||
*
|
||||
* We also add the `force` attribute that adds a custom state key
|
||||
* for when you want to force a complete refresh of the Page
|
||||
*/
|
||||
const defaultLinkView = defaultMithril.route.Link.view;
|
||||
const modifiedLink = {
|
||||
view: function (vnode) {
|
||||
let { href, options = {} } = vnode.attrs;
|
||||
|
||||
if (href === m.route.get()) {
|
||||
if (!('replace' in options)) options.replace = true;
|
||||
}
|
||||
|
||||
return comp.component(args[0], children);
|
||||
}
|
||||
if (extract(vnode.attrs, 'force')) {
|
||||
if (!('state' in options)) options.state = {};
|
||||
if (!('key' in options.state)) options.state.key = Date.now();
|
||||
}
|
||||
|
||||
const node = mo.apply(this, arguments);
|
||||
vnode.attrs.options = options;
|
||||
|
||||
return defaultLinkView(vnode);
|
||||
},
|
||||
};
|
||||
|
||||
const modifiedMithril = function (comp, ...args) {
|
||||
const node = defaultMithril.apply(this, arguments);
|
||||
|
||||
if (!node.attrs) node.attrs = {};
|
||||
|
||||
// Allows the use of the bidi attr.
|
||||
if (node.attrs.bidi) {
|
||||
m.bidi(node, node.attrs.bidi);
|
||||
modifiedMithril.bidi(node, node.attrs.bidi);
|
||||
}
|
||||
|
||||
// Allows us to use a "route" attr on links, which will automatically convert the link to one which
|
||||
// supports linking to other pages in the SPA without refreshing the document.
|
||||
if (node.attrs.route) {
|
||||
node.attrs.href = node.attrs.route;
|
||||
node.attrs.config = m.route;
|
||||
node.tag = modifiedLink;
|
||||
|
||||
// For some reason, m.route.Link does not like vnode.text, so if present, we
|
||||
// need to convert it to text vnodes and store it in children.
|
||||
if (node.text) {
|
||||
node.children = { tag: '#', children: node.text };
|
||||
}
|
||||
|
||||
delete node.attrs.route;
|
||||
}
|
||||
@@ -29,17 +62,11 @@ export default function patchMithril(global) {
|
||||
return node;
|
||||
};
|
||||
|
||||
Object.keys(mo).forEach((key) => (m[key] = mo[key]));
|
||||
Object.keys(defaultMithril).forEach((key) => (modifiedMithril[key] = defaultMithril[key]));
|
||||
|
||||
/**
|
||||
* Redraw only if not in the middle of a computation (e.g. a route change).
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
m.lazyRedraw = function () {
|
||||
m.startComputation();
|
||||
m.endComputation();
|
||||
};
|
||||
modifiedMithril.stream = Stream;
|
||||
|
||||
global.m = m;
|
||||
modifiedMithril.route.Link = modifiedLink;
|
||||
|
||||
global.m = modifiedMithril;
|
||||
}
|
||||
|
Reference in New Issue
Block a user