mirror of
https://github.com/flarum/core.git
synced 2025-08-18 14:22:02 +02:00
Compare commits
9 Commits
dw/fix-pos
...
dw/remove-
Author | SHA1 | Date | |
---|---|---|---|
|
7de9afdcb9 | ||
|
140a6e4477 | ||
|
ec0c233d15 | ||
|
dc661bf144 | ||
|
7a27f494c6 | ||
|
edde6be301 | ||
|
96fdaac3ef | ||
|
e57655553f | ||
|
a1cc456f3a |
@@ -9,7 +9,6 @@
|
|||||||
<a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a>
|
<a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
## About Flarum
|
## About Flarum
|
||||||
|
|
||||||
**[Flarum](https://flarum.org/) is a delightfully simple discussion platform for your website.** It's fast and easy to use, with all the features you need to run a successful community. It is designed to be:
|
**[Flarum](https://flarum.org/) is a delightfully simple discussion platform for your website.** It's fast and easy to use, with all the features you need to run a successful community. It is designed to be:
|
||||||
@@ -20,13 +19,15 @@
|
|||||||
|
|
||||||
* **Powerful and extensible.** Customize, extend, and integrate Flarum to suit your community. Flarum’s architecture is amazingly flexible, with a powerful Extension API.
|
* **Powerful and extensible.** Customize, extend, and integrate Flarum to suit your community. Flarum’s architecture is amazingly flexible, with a powerful Extension API.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
This repository contains Flarum's core code. If you want to set up a forum, visit the [Flarum skeleton repository](https://github.com/flarum/flarum).
|
This repository contains Flarum's core code. If you want to set up a forum, visit the [Flarum skeleton repository](https://github.com/flarum/flarum). For support, refer to the [documentation](https://docs.flarum.org/), and ask questions on [Flarum Discuss](https://discuss.flarum.org/) (our community forum) or [Discord server](https://flarum.org/discord/).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Thank you for considering contributing to Flarum! Please read the **[Contributing guide](https://flarum.org/docs/contributing.html)** to learn how you can help.
|
Thank you for considering contributing to Flarum! Please read the **[Contributing guide](https://docs.flarum.org/contributing)** to learn how you can help.
|
||||||
|
|
||||||
## Security Vulnerabilities
|
## Security Vulnerabilities
|
||||||
|
|
||||||
|
@@ -10,3 +10,17 @@
|
|||||||
* can fix.
|
* can fix.
|
||||||
*/
|
*/
|
||||||
export default function fireDebugWarning(...args: Parameters<typeof console.warn>): void;
|
export default function fireDebugWarning(...args: Parameters<typeof console.warn>): void;
|
||||||
|
/**
|
||||||
|
* Fire a Flarum deprecation warning which is shown in the JS console.
|
||||||
|
*
|
||||||
|
* These warnings are only shown when the forum is in debug mode, and the function exists to
|
||||||
|
* reduce bundle size caused by multiple warnings across our JavaScript.
|
||||||
|
*
|
||||||
|
* @param message The message to display. (Short, but sweet, please!)
|
||||||
|
* @param githubId The PR or Issue ID with more info in relation to this change.
|
||||||
|
* @param [removedFrom] The version in which this feature will be completely removed. (default: 2.0)
|
||||||
|
* @param [repo] The repo which the issue or PR is located in. (default: flarum/core)
|
||||||
|
*
|
||||||
|
* @see {@link fireDebugWarning}
|
||||||
|
*/
|
||||||
|
export declare function fireDeprecationWarning(message: string, githubId: string, removedFrom?: string, repo?: string): void;
|
||||||
|
12
js/dist-typings/forum/components/Search.d.ts
vendored
12
js/dist-typings/forum/components/Search.d.ts
vendored
@@ -42,12 +42,22 @@ export interface SearchAttrs extends ComponentAttrs {
|
|||||||
*
|
*
|
||||||
* - state: SearchState instance.
|
* - state: SearchState instance.
|
||||||
*/
|
*/
|
||||||
export default class Search<T extends SearchAttrs = SearchAttrs> extends Component<T> {
|
export default class Search<T extends SearchAttrs = SearchAttrs> extends Component<T, SearchState> {
|
||||||
/**
|
/**
|
||||||
* The minimum query length before sources are searched.
|
* The minimum query length before sources are searched.
|
||||||
*/
|
*/
|
||||||
protected static MIN_SEARCH_LEN: number;
|
protected static MIN_SEARCH_LEN: number;
|
||||||
|
/**
|
||||||
|
* The instance of `SearchState` for this component.
|
||||||
|
*/
|
||||||
protected searchState: SearchState;
|
protected searchState: SearchState;
|
||||||
|
/**
|
||||||
|
* The instance of `SearchState` for this component.
|
||||||
|
*
|
||||||
|
* @deprecated Replace with`this.searchState` instead.
|
||||||
|
*/
|
||||||
|
protected get state(): SearchState;
|
||||||
|
protected set state(state: SearchState);
|
||||||
/**
|
/**
|
||||||
* Whether or not the search input has focus.
|
* Whether or not the search input has focus.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,13 +1,26 @@
|
|||||||
|
import Component from '../../common/Component';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
export interface IWelcomeHeroAttrs {
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* The `WelcomeHero` component displays a hero that welcomes the user to the
|
* The `WelcomeHero` component displays a hero that welcomes the user to the
|
||||||
* forum.
|
* forum.
|
||||||
*/
|
*/
|
||||||
export default class WelcomeHero extends Component<import("../../common/Component").ComponentAttrs, undefined> {
|
export default class WelcomeHero extends Component<IWelcomeHeroAttrs> {
|
||||||
constructor();
|
/**
|
||||||
hidden: string | boolean | null | undefined;
|
* @deprecated Extend the `isHidden` method instead.
|
||||||
|
*/
|
||||||
|
hidden: boolean;
|
||||||
|
oninit(vnode: Mithril.Vnode<IWelcomeHeroAttrs, this>): void;
|
||||||
|
view(vnode: Mithril.Vnode<IWelcomeHeroAttrs, this>): JSX.Element | null;
|
||||||
/**
|
/**
|
||||||
* Hide the welcome hero.
|
* Hide the welcome hero.
|
||||||
*/
|
*/
|
||||||
hide(): void;
|
hide(): void;
|
||||||
|
/**
|
||||||
|
* Determines whether the welcome hero should be hidden.
|
||||||
|
*
|
||||||
|
* @returns if the welcome hero is hidden.
|
||||||
|
*/
|
||||||
|
isHidden(): boolean;
|
||||||
}
|
}
|
||||||
import Component from "../../common/Component";
|
|
||||||
|
2
js/dist/admin.js
generated
vendored
2
js/dist/admin.js
generated
vendored
File diff suppressed because one or more lines are too long
2
js/dist/admin.js.map
generated
vendored
2
js/dist/admin.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2
js/dist/forum.js
generated
vendored
2
js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
js/dist/forum.js.map
generated
vendored
2
js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
import app from '../common/app';
|
import app from '../common/app';
|
||||||
import { FlarumRequestOptions } from './Application';
|
import { FlarumRequestOptions } from './Application';
|
||||||
import fireDebugWarning from './helpers/fireDebugWarning';
|
import { fireDeprecationWarning } from './helpers/fireDebugWarning';
|
||||||
import Model, { ModelData, SavedModelData } from './Model';
|
import Model, { ModelData, SavedModelData } from './Model';
|
||||||
|
|
||||||
export interface MetaInformation {
|
export interface MetaInformation {
|
||||||
@@ -123,11 +123,7 @@ export default class Store {
|
|||||||
if (!this.models[data.type]) {
|
if (!this.models[data.type]) {
|
||||||
if (!allowUnregistered) {
|
if (!allowUnregistered) {
|
||||||
setTimeout(() =>
|
setTimeout(() =>
|
||||||
fireDebugWarning(
|
fireDeprecationWarning(`Pushing object of type \`${data.type}\` not allowed, as type not yet registered in the store.`, '3206')
|
||||||
`[Flarum 2.0 Deprecation] Cannot push object of type \`${data.type}\`, as that type has not yet been registered in the store. This will throw an error in Flarum 2.0 and later.
|
|
||||||
|
|
||||||
For more information, see https://github.com/flarum/core/pull/3206.`
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,3 +16,21 @@ export default function fireDebugWarning(...args: Parameters<typeof console.warn
|
|||||||
|
|
||||||
console.warn(...args);
|
console.warn(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire a Flarum deprecation warning which is shown in the JS console.
|
||||||
|
*
|
||||||
|
* These warnings are only shown when the forum is in debug mode, and the function exists to
|
||||||
|
* reduce bundle size caused by multiple warnings across our JavaScript.
|
||||||
|
*
|
||||||
|
* @param message The message to display. (Short, but sweet, please!)
|
||||||
|
* @param githubId The PR or Issue ID with more info in relation to this change.
|
||||||
|
* @param [removedFrom] The version in which this feature will be completely removed. (default: 2.0)
|
||||||
|
* @param [repo] The repo which the issue or PR is located in. (default: flarum/core)
|
||||||
|
*
|
||||||
|
* @see {@link fireDebugWarning}
|
||||||
|
*/
|
||||||
|
export function fireDeprecationWarning(message: string, githubId: string, removedFrom: string = '2.0', repo: string = 'flarum/core'): void {
|
||||||
|
// GitHub auto-redirects between `/pull` and `/issues` for us, so using `/pull` saves 2 bytes!
|
||||||
|
fireDebugWarning(`[Flarum ${removedFrom} Deprecation] ${message}\n\nSee: https://github.com/${repo}/pull/${githubId}`);
|
||||||
|
}
|
||||||
|
@@ -1,15 +1,14 @@
|
|||||||
|
import { fireDeprecationWarning } from '../helpers/fireDebugWarning';
|
||||||
|
|
||||||
|
const deprecatedNotice = 'The `evented` util is deprecated and no longer supported.';
|
||||||
|
const deprecationIssueId = '2547';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `evented` mixin provides methods allowing an object to trigger events,
|
* The `evented` mixin provides methods allowing an object to trigger events,
|
||||||
* running externally registered event handlers.
|
* running externally registered event handlers.
|
||||||
*
|
*
|
||||||
* @deprecated v1.2, to be removed in v2.0
|
* @deprecated v1.2, to be removed in v2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fireDebugWarning from '../helpers/fireDebugWarning';
|
|
||||||
|
|
||||||
const deprecatedNotice =
|
|
||||||
'The `evented` util is deprecated and will be removed in Flarum 2.0. For more info, please see https://github.com/flarum/core/issues/2547';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Arrays of registered event handlers, grouped by the event name.
|
* Arrays of registered event handlers, grouped by the event name.
|
||||||
@@ -27,7 +26,7 @@ export default {
|
|||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
getHandlers(event) {
|
getHandlers(event) {
|
||||||
fireDebugWarning(deprecatedNotice);
|
fireDeprecationWarning(deprecatedNotice, deprecationIssueId);
|
||||||
|
|
||||||
this.handlers = this.handlers || {};
|
this.handlers = this.handlers || {};
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@ export default {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
trigger(event, ...args) {
|
trigger(event, ...args) {
|
||||||
fireDebugWarning(deprecatedNotice);
|
fireDeprecationWarning(deprecatedNotice, deprecationIssueId);
|
||||||
|
|
||||||
this.getHandlers(event).forEach((handler) => handler.apply(this, args));
|
this.getHandlers(event).forEach((handler) => handler.apply(this, args));
|
||||||
},
|
},
|
||||||
@@ -56,7 +55,7 @@ export default {
|
|||||||
* @param {function} handler The function to handle the event.
|
* @param {function} handler The function to handle the event.
|
||||||
*/
|
*/
|
||||||
on(event, handler) {
|
on(event, handler) {
|
||||||
fireDebugWarning(deprecatedNotice);
|
fireDeprecationWarning(deprecatedNotice, deprecationIssueId);
|
||||||
|
|
||||||
this.getHandlers(event).push(handler);
|
this.getHandlers(event).push(handler);
|
||||||
},
|
},
|
||||||
@@ -69,7 +68,7 @@ export default {
|
|||||||
* @param {function} handler The function to handle the event.
|
* @param {function} handler The function to handle the event.
|
||||||
*/
|
*/
|
||||||
one(event, handler) {
|
one(event, handler) {
|
||||||
fireDebugWarning(deprecatedNotice);
|
fireDeprecationWarning(deprecatedNotice, deprecationIssueId);
|
||||||
|
|
||||||
const wrapper = function () {
|
const wrapper = function () {
|
||||||
handler.apply(this, arguments);
|
handler.apply(this, arguments);
|
||||||
@@ -87,7 +86,7 @@ export default {
|
|||||||
* @param {function} handler The function that handles the event.
|
* @param {function} handler The function that handles the event.
|
||||||
*/
|
*/
|
||||||
off(event, handler) {
|
off(event, handler) {
|
||||||
fireDebugWarning(deprecatedNotice);
|
fireDeprecationWarning(deprecatedNotice, deprecationIssueId);
|
||||||
|
|
||||||
const handlers = this.getHandlers(event);
|
const handlers = this.getHandlers(event);
|
||||||
const index = handlers.indexOf(handler);
|
const index = handlers.indexOf(handler);
|
||||||
|
@@ -6,7 +6,6 @@ import PostControls from '../utils/PostControls';
|
|||||||
import listItems from '../../common/helpers/listItems';
|
import listItems from '../../common/helpers/listItems';
|
||||||
import ItemList from '../../common/utils/ItemList';
|
import ItemList from '../../common/utils/ItemList';
|
||||||
import LoadingIndicator from '../../common/components/LoadingIndicator';
|
import LoadingIndicator from '../../common/components/LoadingIndicator';
|
||||||
import classList from '../../common/utils/classList';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `Post` component displays a single post. The basic post template just
|
* The `Post` component displays a single post. The basic post template just
|
||||||
@@ -125,16 +124,24 @@ export default class Post extends Component {
|
|||||||
* @returns {string[]}
|
* @returns {string[]}
|
||||||
*/
|
*/
|
||||||
classes(existing) {
|
classes(existing) {
|
||||||
|
let classes = (existing || '').split(' ').concat(['Post']);
|
||||||
|
|
||||||
const user = this.attrs.post.user();
|
const user = this.attrs.post.user();
|
||||||
const discussion = this.attrs.post.discussion();
|
const discussion = this.attrs.post.discussion();
|
||||||
|
|
||||||
return classList(existing, 'Post', {
|
if (this.loading) {
|
||||||
'Post--loading': this.loading,
|
classes.push('Post--loading');
|
||||||
'Post--by-actor': user === app.session.user,
|
}
|
||||||
'Post--by-start-user': user?.id() === discussion.attribute('startUserId'),
|
|
||||||
})
|
if (user && user === app.session.user) {
|
||||||
.split(' ')
|
classes.push('Post--by-actor');
|
||||||
.filter((x) => !!x);
|
}
|
||||||
|
|
||||||
|
if (user && user.id() === discussion.attribute('startUserId')) {
|
||||||
|
classes.push('Post--by-start-user');
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -55,6 +55,6 @@ export default class PostMeta extends Component {
|
|||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
getPermalink(post) {
|
getPermalink(post) {
|
||||||
return window.location.origin + app.route.post(post);
|
return app.forum.attribute('baseUrl') + app.route.post(post);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,8 +9,8 @@ import icon from '../../common/helpers/icon';
|
|||||||
import SearchState from '../states/SearchState';
|
import SearchState from '../states/SearchState';
|
||||||
import DiscussionsSearchSource from './DiscussionsSearchSource';
|
import DiscussionsSearchSource from './DiscussionsSearchSource';
|
||||||
import UsersSearchSource from './UsersSearchSource';
|
import UsersSearchSource from './UsersSearchSource';
|
||||||
|
import { fireDeprecationWarning } from '../../common/helpers/fireDebugWarning';
|
||||||
import type Mithril from 'mithril';
|
import type Mithril from 'mithril';
|
||||||
import Model from '../../common/Model';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `SearchSource` interface defines a section of search results in the
|
* The `SearchSource` interface defines a section of search results in the
|
||||||
@@ -53,14 +53,33 @@ export interface SearchAttrs extends ComponentAttrs {
|
|||||||
*
|
*
|
||||||
* - state: SearchState instance.
|
* - state: SearchState instance.
|
||||||
*/
|
*/
|
||||||
export default class Search<T extends SearchAttrs = SearchAttrs> extends Component<T> {
|
export default class Search<T extends SearchAttrs = SearchAttrs> extends Component<T, SearchState> {
|
||||||
/**
|
/**
|
||||||
* The minimum query length before sources are searched.
|
* The minimum query length before sources are searched.
|
||||||
*/
|
*/
|
||||||
protected static MIN_SEARCH_LEN = 3;
|
protected static MIN_SEARCH_LEN = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance of `SearchState` for this component.
|
||||||
|
*/
|
||||||
protected searchState!: SearchState;
|
protected searchState!: SearchState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance of `SearchState` for this component.
|
||||||
|
*
|
||||||
|
* @deprecated Replace with`this.searchState` instead.
|
||||||
|
*/
|
||||||
|
// TODO: [Flarum 2.0] Remove this.
|
||||||
|
// @ts-expect-error This is a get accessor, while superclass defines this as a property. This is needed to prevent breaking changes, however.
|
||||||
|
protected get state() {
|
||||||
|
fireDeprecationWarning('`state` property of the Search component is deprecated', '3212');
|
||||||
|
return this.searchState;
|
||||||
|
}
|
||||||
|
protected set state(state: SearchState) {
|
||||||
|
fireDeprecationWarning('`state` property of the Search component is deprecated', '3212');
|
||||||
|
this.searchState = state;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the search input has focus.
|
* Whether or not the search input has focus.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,50 +0,0 @@
|
|||||||
import app from '../../forum/app';
|
|
||||||
import Component from '../../common/Component';
|
|
||||||
import Button from '../../common/components/Button';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `WelcomeHero` component displays a hero that welcomes the user to the
|
|
||||||
* forum.
|
|
||||||
*/
|
|
||||||
export default class WelcomeHero extends Component {
|
|
||||||
oninit(vnode) {
|
|
||||||
super.oninit(vnode);
|
|
||||||
|
|
||||||
this.hidden = localStorage.getItem('welcomeHidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
view() {
|
|
||||||
if (this.hidden) return <div />;
|
|
||||||
|
|
||||||
const slideUp = () => {
|
|
||||||
this.$().slideUp(this.hide.bind(this));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<header className="Hero WelcomeHero">
|
|
||||||
<div class="container">
|
|
||||||
{Button.component({
|
|
||||||
icon: 'fas fa-times',
|
|
||||||
onclick: slideUp,
|
|
||||||
className: 'Hero-close Button Button--icon Button--link',
|
|
||||||
'aria-label': app.translator.trans('core.forum.welcome_hero.hide'),
|
|
||||||
})}
|
|
||||||
|
|
||||||
<div className="containerNarrow">
|
|
||||||
<h2 className="Hero-title">{app.forum.attribute('welcomeTitle')}</h2>
|
|
||||||
<div className="Hero-subtitle">{m.trust(app.forum.attribute('welcomeMessage'))}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the welcome hero.
|
|
||||||
*/
|
|
||||||
hide() {
|
|
||||||
localStorage.setItem('welcomeHidden', 'true');
|
|
||||||
|
|
||||||
this.hidden = true;
|
|
||||||
}
|
|
||||||
}
|
|
69
js/src/forum/components/WelcomeHero.tsx
Normal file
69
js/src/forum/components/WelcomeHero.tsx
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import app from '../app';
|
||||||
|
import Component from '../../common/Component';
|
||||||
|
import Button from '../../common/components/Button';
|
||||||
|
import type Mithril from 'mithril';
|
||||||
|
|
||||||
|
export interface IWelcomeHeroAttrs {}
|
||||||
|
|
||||||
|
const LOCAL_STORAGE_KEY = 'welcomeHidden';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `WelcomeHero` component displays a hero that welcomes the user to the
|
||||||
|
* forum.
|
||||||
|
*/
|
||||||
|
export default class WelcomeHero extends Component<IWelcomeHeroAttrs> {
|
||||||
|
/**
|
||||||
|
* @deprecated Extend the `isHidden` method instead.
|
||||||
|
*/
|
||||||
|
hidden: boolean = false;
|
||||||
|
|
||||||
|
oninit(vnode: Mithril.Vnode<IWelcomeHeroAttrs, this>) {
|
||||||
|
super.oninit(vnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
view(vnode: Mithril.Vnode<IWelcomeHeroAttrs, this>) {
|
||||||
|
if (this.isHidden()) return null;
|
||||||
|
|
||||||
|
const slideUp = () => {
|
||||||
|
this.$().slideUp(this.hide.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header class="Hero WelcomeHero">
|
||||||
|
<div class="container">
|
||||||
|
<Button
|
||||||
|
icon="fas fa-times"
|
||||||
|
onclick={slideUp}
|
||||||
|
className="Hero-close Button Button--icon Button--link"
|
||||||
|
aria-label={app.translator.trans('core.forum.welcome_hero.hide')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="containerNarrow">
|
||||||
|
<h2 class="Hero-title">{app.forum.attribute('welcomeTitle')}</h2>
|
||||||
|
<div class="Hero-subtitle">{m.trust(app.forum.attribute('welcomeMessage'))}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the welcome hero.
|
||||||
|
*/
|
||||||
|
hide() {
|
||||||
|
localStorage.setItem(LOCAL_STORAGE_KEY, 'true');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the welcome hero should be hidden.
|
||||||
|
*
|
||||||
|
* @returns if the welcome hero is hidden.
|
||||||
|
*/
|
||||||
|
isHidden(): boolean {
|
||||||
|
if (!app.forum.attribute<string>('welcomeTitle')?.trim()) return true;
|
||||||
|
if (localStorage.getItem(LOCAL_STORAGE_KEY)) return true;
|
||||||
|
if (this.hidden) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -50,7 +50,6 @@
|
|||||||
color: var(--muted-color);
|
color: var(--muted-color);
|
||||||
}
|
}
|
||||||
thead th {
|
thead th {
|
||||||
position: -webkit-sticky;
|
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
@@ -74,7 +73,6 @@
|
|||||||
}
|
}
|
||||||
tbody {
|
tbody {
|
||||||
th {
|
th {
|
||||||
position: -webkit-sticky;
|
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
padding-right: 50px;
|
padding-right: 50px;
|
||||||
|
@@ -142,8 +142,7 @@
|
|||||||
z-index: var(--zindex-modal);
|
z-index: var(--zindex-modal);
|
||||||
|
|
||||||
.drawerOpen & {
|
.drawerOpen & {
|
||||||
-webkit-transform: none !important;
|
transform: none !important;
|
||||||
transform: none !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.drawer-backdrop {
|
.drawer-backdrop {
|
||||||
|
@@ -177,7 +177,6 @@
|
|||||||
box-shadow: 0 2px 6px var(--shadow-color);
|
box-shadow: 0 2px 6px var(--shadow-color);
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
transform: translate(0, 70vh);
|
transform: translate(0, 70vh);
|
||||||
transition: transform 0.3s, visibility 0s 0.3s;
|
transition: transform 0.3s, visibility 0s 0.3s;
|
||||||
|
|
||||||
@@ -208,8 +207,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.open& {
|
.open& {
|
||||||
-webkit-transform: none;
|
transform: none;
|
||||||
transform: none;
|
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: var(--zindex-modal);
|
z-index: var(--zindex-modal);
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
|
|
||||||
// When fading in the modal, animate it to slide down
|
// When fading in the modal, animate it to slide down
|
||||||
.Modal {
|
.Modal {
|
||||||
@@ -143,8 +142,7 @@
|
|||||||
transform: translate(0, 100vh);
|
transform: translate(0, 100vh);
|
||||||
|
|
||||||
&.in {
|
&.in {
|
||||||
-webkit-transform: none !important;
|
transform: none !important;
|
||||||
transform: none !important;
|
|
||||||
}
|
}
|
||||||
&:before {
|
&:before {
|
||||||
content: " ";
|
content: " ";
|
||||||
@@ -155,8 +153,7 @@
|
|||||||
.Modal {
|
.Modal {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
-webkit-transform: none !important;
|
transform: none !important;
|
||||||
transform: none !important;
|
|
||||||
}
|
}
|
||||||
.Modal-content {
|
.Modal-content {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@@ -183,7 +180,6 @@
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.Modal-content {
|
.Modal-content {
|
||||||
|
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
box-shadow: 0 7px 15px var(--shadow-color);
|
box-shadow: 0 7px 15px var(--shadow-color);
|
||||||
|
@@ -6,7 +6,6 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: auto;
|
width: auto;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
@@ -65,11 +65,7 @@
|
|||||||
// CSS3 Content Columns
|
// CSS3 Content Columns
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
.content-columns(@column-count; @column-gap: @grid-gutter-width) {
|
.content-columns(@column-count; @column-gap: @grid-gutter-width) {
|
||||||
// Safari
|
|
||||||
-webkit-column-count: @column-count;
|
|
||||||
column-count: @column-count;
|
column-count: @column-count;
|
||||||
// Safari
|
|
||||||
-webkit-column-gap: @column-gap;
|
|
||||||
column-gap: @column-gap;
|
column-gap: @column-gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +81,6 @@
|
|||||||
// Placeholder text
|
// Placeholder text
|
||||||
.placeholder(@color) {
|
.placeholder(@color) {
|
||||||
// Safari
|
// Safari
|
||||||
&::-webkit-input-placeholder,
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: @color;
|
color: @color;
|
||||||
}
|
}
|
||||||
@@ -176,7 +171,7 @@
|
|||||||
// User select
|
// User select
|
||||||
// For selecting text on the page
|
// For selecting text on the page
|
||||||
.user-select(@select) {
|
.user-select(@select) {
|
||||||
// Safari + MS Edge
|
// Safari
|
||||||
-webkit-user-select: @select;
|
-webkit-user-select: @select;
|
||||||
user-select: @select;
|
user-select: @select;
|
||||||
}
|
}
|
||||||
|
@@ -80,7 +80,6 @@
|
|||||||
padding: 15px 0;
|
padding: 15px 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: " ";
|
content: " ";
|
||||||
|
@@ -107,25 +107,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.animated {
|
.animated {
|
||||||
-webkit-animation-fill-mode: both;
|
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
|
|
||||||
-webkit-animation-duration: 0.5s;
|
|
||||||
animation-duration: 0.5s;
|
animation-duration: 0.5s;
|
||||||
|
|
||||||
animation-delay: 1.7s;
|
animation-delay: 1.7s;
|
||||||
-webkit-animation-delay: 1.7s;
|
|
||||||
}
|
|
||||||
@-webkit-keyframes fadeIn {
|
|
||||||
0% {opacity: 0}
|
|
||||||
100% {opacity: 1}
|
|
||||||
}
|
}
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
0% {opacity: 0}
|
0% {opacity: 0}
|
||||||
100% {opacity: 1}
|
100% {opacity: 1}
|
||||||
}
|
}
|
||||||
.fadeIn {
|
.fadeIn {
|
||||||
-webkit-animation-name: fadeIn;
|
|
||||||
animation-name: fadeIn;
|
animation-name: fadeIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user