If the error isn't a 409, we'll want to re-throw the error so it'll be handled by the default system (showing an alert).
For simplicity, we can also move 409-handling logic out of setTimeout.
Finally, we adjust the timeout to 300 milliseconds to match the modal transition animation length.
* Revert "Fix header contents moving when opening modal (#2131)"
* Fix header contents moving when modal opened/closed.
Conditionally apply the navbar-fixed-top class only when needed, so that we can take advantage of it without always having the navbar in position:fixed, as was done in the previous solution. That resulted in a clash with custom headers.
* Show header on refresh of scrolled page
Due to some magic in Mithril 0.1's context:retain flag, some DOM elements were cached across page reloads. Since that has been eliminated, if we refresh the page and we are scrolled down, the "affix" class which makes the header fixed (and as a result, visible) isn't applied until the first scroll. We fix this by running ScrollListener.update() immediately to set initial navbar state.
When on a discussion page, the URL changing doesn't always mean we've moved to a different page. In our custom rerender logic, we only want to call `this.onNewRoute()` if the page has actually changed.
After we scroll to a post, we redraw to render post content. We then update the scrubber again so its height is accurate. This commit moves that update to AFTER our adjustment of scroll position, so that scrubber height is based on actual post heights. This fixes some subtle scrubber glitches.
Let's stay consistent with previous behavior, and run these on "internal route change" (same component handles different route) as well as on initial render of a page component.
Currently, the controls are on a new line due to the container div. We want to wrap ALL children of the alert, including the controls, in the container div.
We need to split it into a separate class so that we can add modify the alert vnode AFTER the alert component's `view` logic has been applied.
From using PhpStorm to try and see if the autocomplete works properly, it appears as it doesn't. The intention was to not have to import Mithril every time we wanted to type something with Mithril.*, but that doesn't seem to be possible - and it's not a big deal anyway
During the frontend rewrite, we introduced mithril patches for a `route` attr, and for `m.stream`. Later, we decided not to go that route, but not to remove the patches yet to avoid breaking extensions while we were finalizing the replacements. We can now remove these.
Other BC layers are for things from before beta 14, so those remain in place.
- Use Mithril.Attributes as base for ComponentAttrs, remove =any from class signature for Component
- Convert Alert to TypeScript, introduce AlertAttrs interface
- Convert AlertManagerState to TypeScript, add overload signatures for `show`, introduce AlertState interface for stored Alerts.
- Set ComponentAttrs as default T for Component
- Make attrs in AlertAttrs optional
- Add AlertIdentifier interface, simplify show type signature
- Remove mithril patch shim, as all patches onto m are now deprecated
- Use Mithril.Static for shim
- Ensure that the discussion list is cleared before it is updated with fetched results
- Rename `clear` to `deferClear`, improve documentation to make its purpose clearer.
- Call onNewRoute when page changed with same component in DiscussionPage and UserPage
- Make app.previous and app.current changed in onNewRoute, not in oninit. This way, when the route is changed, but still handled by the same component, a new PageState object will still be created.
While more pleasant from an FSM standpoint, comparing the current targetPost to the previous one does not work if goToNumber is called twice in a row for the same post. For instance, if a user clicks the mentions link to a post twice, the post stream breaks.
In some cases, such as if we've stickied a post, an event post
may have been added / removed.This means that `this.visibleEnd`
and`this.count()` will be out of sync by 1 post, but we are still
"viewing the end" of the post stream, so we should still reload
all posts up until the last one.
Because the Slidable class was always added on creation, it was lost every time the class list changed (in this case when the discussion was hidden/unhidden which added/removed DiscussionListItem--hidden class). So by determining the Slidable class's presence in elementAttrs() method, it guarantees it always properly set.
While seemingly correct, an onremove method in Modal that triggers animateHide is problematic, because if one modal is opened from another, the one currently open will be removed from the DOM, triggering animateHide, and closing the new modal.
To compensate, an onupdate method now closes a modal if one is open but shouldn't be; this supports the functionality of the old method when the modal is closed not from the modal instance itself (e.g. app.modal.close())
This is not ideal, but necessary. We should consider eventually expanding the modal system to support showing multiple modals at the same time (stacked over each other). Then, we can move this back to individual modals.
When the page is scrolled, goToIndex is called, or the page is loaded,
various listeners result in the scrubber being updated with a new
position and values. However, if goToNumber is called, the scrubber
will not be updated. Accordingly, we add logic to the scrubber's
onupdate to update itself, but only when needed, as indicated by this
This saves us a LOT of unnecessary calls, and makes scrubber movement smoother.
* 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 is needed to have access to the newly created SuperTextarea
instance (app.composer.editor) directly after calling show().
Discovered when making ext-mentions work with the Composer state
changes. As far as I could reconstruct, a synchronous redraw was also
triggered in this situation before the changes in #2161.
This commit fixes the method `abbreviateNumber` so that it behaves as stated in the JSDoc.
Previously, an input of `1234` would have produced `1K`. With this change, the output will be `1.2K`.
* Fix closing the composer with ESC key
Regression from #2161.
* Remove obsolete method
Regression from #2162.
* Mark method as protected
* Fade in posts in post stream using CSS
This also avoids a double-fade from the JavaScript code, which was
probably introduced in #2160.
* Fix fadeIn for post stream items
Co-authored-by: Alexander Skvortsov <sasha.skvortsov109@gmail.com>
Like previous "state PRs", this moves app-wide logic relating to
our "composer" widget to its own "state" class, which can be
referenced and called from all parts of the app. This lets us
avoid storing component instances, which we cannot do any longer
once we update to Mithril v2.
This was not as trivial as some of the other state changes, as we
tried to separate DOM effects (e.g. animations) from actual state
changes (e.g. minimizing or opening the composer).
New features:
- A new `app.screen()` method returns the current responsive screen
mode. This lets us check what breakpoint we're on in JS land
without hardcoding / duplicating the actual breakpoints from CSS.
- A new `SuperTextarea` util exposes useful methods for directly
interacting with and manipulating the text contents of e.g. our
post editor.
- A new `ConfirmDocumentUnload` wrapper component encapsulates the
logic for asking the user for confirmation when trying to close
the browser window or navigating to another page. This is used in
the composer to prevent accidentally losing unsaved post content.
There is still potential for future cleanups, but we finally want
to unblock the Mithril update, so these will have to wait:
- Composer height change logic is very DOM-based, so should maybe
not sit in the state.
- I would love to experiment with using composition rather than
inheritance for the `ComposerBody` subclasses.
This file isn't used anywhere. We should be calling it at some point. It has existed for 5 years.
Renamed function because it makes more sense for name to match file name (not that it matters when building)
This allows us to get started with converting all Flarum JavaScript code to TypeScript.
In addition, we will have time to experiment to find the best Webpack configuration before integrating into flarum-webpack-config.
See flarum/flarum-webpack-config#3.
- Encapsulate app.current, app.previous in PageState objects
- Reorganize Page classes to use one central base class in common
Co-authored-by: Franz Liedke <franz@develophp.org>
* Don't store checkbox states in NotificaitonGrid, use props for loading in Checkbox and Switch, replace preferenceSaver with internal management of loading state
* Deprecate GetDisplayName event
* Add interface for display name driver
* Add username driver as default
* Add code to register supported drivers / used driver as singletons
* Configured User class to use new driver-based system for display names
* Add extender for adding display name driver
* Add integration test for user display name driver
* Add frontend UI for selecting display name driver
* Don't use body as tooltip container, allow notification area overflow
Badge tooltips are using container: 'body', so they can overflow the
notification area. When the user navigates back while a badge tooltip is
showing, the tooltip remains visible.
This commit removes the body container attribute and instead allows the
notificationDropDown to overflow, so badge tooltips aren't cut off.
Instead, this adds overflow: hidden to NotificationList.
Fixes#2118.
* Remove newline
* Use decodeURI instead of unescape & don't close modals
* Add comment
* Don't use a try/catch, clean up the group log code
* Remove double negative
* Format; fix issues from rebasing
Only users that have the new `viewHiddenGroups` permissions will be able to see these groups.
You might want this when you want to give certain users special permissions, but don't want to make your authorization scheme public to regular users.
Co-authored-by: luceos <daniel+github@klabbers.email>
When users have external avatar urls (for instance: in a SSO environment where the avatar is provided by another domain), color thief fails to get the avatar dominant color because the canvas would be tainted.
Following the instructions here (https://lokeshdhakar.com/projects/color-thief/ on the "Does it work if the image is hosted on another domain?"), adding an `image.crossOrigin = 'Anonymous';` solves the issue.
Tested on my forum which before suffered from a JS error and works fine (without this fix, the canvas remain in the `body` while an script error is thrown by color thief)
Refs #1788
TypeError: t.showDeletionAlert is not a function
at onSuccess(./src/forum/utils/UserControls.js:104:12)
Also, don't override 'this' param with user object for editAction