Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ae713c083 | |||
| 4b4a9f981f | |||
| 3faabb8280 | |||
| 5f9a92953f | |||
| 81445f0afd | |||
| adf075d19f | |||
| 8a26776492 | |||
| a011c5addf | |||
| d7d013609c | |||
| e36d764aaa | |||
| c6eb0b1927 | |||
| 4edb2f2b2c | |||
| 110c8fb8cc | |||
| 6d0b964e2b | |||
| 60792ec753 | |||
| e5869dc945 | |||
| f61625f4bd | |||
| 02106153ec | |||
| 8eba3f59f8 |
@@ -0,0 +1,7 @@
|
||||
root = true
|
||||
|
||||
[*.scss]
|
||||
indent_size = 2
|
||||
|
||||
[login.scss]
|
||||
indent_size = 4
|
||||
@@ -55,6 +55,9 @@ npm-debug.log
|
||||
yarn-error.log
|
||||
yarn-debug.log
|
||||
|
||||
# Ignore yarn state file
|
||||
.yarn/install-state.gz
|
||||
|
||||
# Ignore vagrant log files
|
||||
*-cloudimg-console.log
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
steps:
|
||||
lint:
|
||||
image: node:22-alpine
|
||||
image: docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0
|
||||
pull: true
|
||||
|
||||
|
||||
# https://woodpecker-ci.org/docs/usage/volumes
|
||||
volumes:
|
||||
- /woodpecker/masto-fe-standalone/node_modules:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/node_modules
|
||||
- /woodpecker/masto-fe-standalone/.eslintcache:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/.eslintcache
|
||||
|
||||
|
||||
# https://woodpecker-ci.org/docs/administration/configuration/backends/docker#run-user
|
||||
backend_options:
|
||||
docker:
|
||||
user: 1000:1000
|
||||
|
||||
|
||||
# https://woodpecker-ci.org/docs/usage/workflow-syntax#commands
|
||||
commands:
|
||||
- yarn
|
||||
- yarn lint:js
|
||||
|
||||
|
||||
# https://woodpecker-ci.org/docs/usage/workflow-syntax#when---conditional-execution
|
||||
when:
|
||||
- event: pull_request
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
nodeLinker: node-modules
|
||||
+15
-1884
File diff suppressed because it is too large
Load Diff
+69
-3198
File diff suppressed because it is too large
Load Diff
+14
-3
@@ -4,11 +4,22 @@
|
||||
|
||||
## Dependencies
|
||||
|
||||
To work on the code decently, you should have Node and Yarn installed. To avoid fuckery, Node Version Manager is **highly recommended**: https://github.com/nvm-sh/nvm.
|
||||
To work on the code, you must have Node installed.
|
||||
|
||||
To avoid fuckery, Node Version Manager is **highly recommended**: https://github.com/nvm-sh/nvm. You can then install the latest `lts` version of node with `nvm install --lts && nvm use --lts`.
|
||||
|
||||
You should install yarn as described [here](https://yarnpkg.com/getting-started/install) and/or [here](https://yarnpkg.com/migration/guide).
|
||||
|
||||
## Testing Locally
|
||||
|
||||
You can fairly easily test builds of Masto-FE locally by using Docker and the GoToSocial testrig.
|
||||
If you want to run Masto-FE in dev mode:
|
||||
|
||||
- install the project: `yarn install`
|
||||
- start the dev server: `yarn dev`
|
||||
|
||||
You should now be able to connect on http://localhost:3035. Changes will automatically compile.
|
||||
|
||||
You can also fairly easily test builds of Masto-FE locally by using Docker and the GoToSocial testrig.
|
||||
|
||||
### Build GoToSocial + launch the GtS testrig
|
||||
|
||||
@@ -37,7 +48,7 @@ Leave the testrig running.
|
||||
|
||||
### Build Masto-FE + run it locally
|
||||
|
||||
Now in a *separate* terminal window, get back to the Masto-FE directory, and do a Docker build (this might take a bit of time):
|
||||
Now in a _separate_ terminal window, get back to the Masto-FE directory, and do a Docker build (this might take a bit of time):
|
||||
|
||||
```bash
|
||||
docker build -t superseriousbusiness/masto-fe-standalone:latest .
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
### BUILDER IMAGE ###
|
||||
FROM node:lts-alpine AS builder
|
||||
FROM docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0 AS builder
|
||||
|
||||
# Prepare the build directory, copy
|
||||
# relevant source + config files over.
|
||||
|
||||
@@ -40,7 +40,7 @@ Serve all the stuff in `public` behind an nginx or whatever you want! See the in
|
||||
|
||||
### Docker (definitely the easiest way)
|
||||
|
||||
The Docker container is based on Nginx, and serves over port 3000. Just deploy it and listen on that port, preferably with a reverse proxy at some point (Traefik? Caddy? Another Nginx perhaps?) handling https.
|
||||
The Docker container is based on Nginx, and serves over port 80. Just deploy it and listen on that port, preferably with a reverse proxy at some point (Traefik? Caddy? Another Nginx perhaps?) handling https.
|
||||
|
||||
## Testing locally, linting, etc
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { expandSpoilers, disableSwiping } from 'flavours/glitch/initial_state';
|
||||
import { disableSwiping } from 'flavours/glitch/initial_state';
|
||||
|
||||
import { openModal } from './modal';
|
||||
|
||||
@@ -7,18 +7,9 @@ export const LOCAL_SETTING_DELETE = 'LOCAL_SETTING_DELETE';
|
||||
|
||||
export function checkDeprecatedLocalSettings() {
|
||||
return (dispatch, getState) => {
|
||||
const local_auto_unfold = getState().getIn(['local_settings', 'content_warnings', 'auto_unfold']);
|
||||
const local_swipe_to_change_columns = getState().getIn(['local_settings', 'swipe_to_change_columns']);
|
||||
let changed_settings = [];
|
||||
|
||||
if (local_auto_unfold !== null && local_auto_unfold !== undefined) {
|
||||
if (local_auto_unfold === expandSpoilers) {
|
||||
dispatch(deleteLocalSetting(['content_warnings', 'auto_unfold']));
|
||||
} else {
|
||||
changed_settings.push('user_setting_expand_spoilers');
|
||||
}
|
||||
}
|
||||
|
||||
if (local_swipe_to_change_columns !== null && local_swipe_to_change_columns !== undefined) {
|
||||
if (local_swipe_to_change_columns === !disableSwiping) {
|
||||
dispatch(deleteLocalSetting(['swipe_to_change_columns']));
|
||||
|
||||
@@ -21,11 +21,21 @@ export const fetchServer = () => (dispatch, getState) => {
|
||||
|
||||
dispatch(fetchServerRequest());
|
||||
|
||||
api(getState)
|
||||
.get('/api/v2/instance').then(({ data }) => {
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
}).catch(err => dispatch(fetchServerFail(err)));
|
||||
/* global data */
|
||||
try {
|
||||
api(getState)
|
||||
.get('/api/v2/instance').then({ data }).catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
} catch (e) {
|
||||
api(getState)
|
||||
.get('/api/v1/instance').then(({ data }) => {
|
||||
if (data.contact_account) dispatch(importFetchedAccount(data.contact_account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
}).catch(err => dispatch(fetchServerFail(err)));
|
||||
}
|
||||
};
|
||||
|
||||
const fetchServerRequest = () => ({
|
||||
|
||||
@@ -8,9 +8,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
|
||||
|
||||
// Our imports
|
||||
import { expandSpoilers } from 'flavours/glitch/initial_state';
|
||||
|
||||
import DeprecatedLocalSettingsPageItem from './deprecated_item';
|
||||
import LocalSettingsPageItem from './item';
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
@@ -308,35 +305,21 @@ class LocalSettingsPage extends PureComponent {
|
||||
</LocalSettingsPageItem>
|
||||
<section>
|
||||
<h2><FormattedMessage id='settings.content_warnings_unfold_opts' defaultMessage='Auto-unfolding options' /></h2>
|
||||
<DeprecatedLocalSettingsPageItem
|
||||
<LocalSettingsPageItem
|
||||
settings={settings}
|
||||
item={['content_warnings', 'auto_unfold']}
|
||||
onChange={onChange}
|
||||
id='mastodon-settings--content_warnings-auto_unfold'
|
||||
value={expandSpoilers}
|
||||
>
|
||||
<FormattedMessage id='settings.enable_content_warnings_auto_unfold' defaultMessage='Automatically unfold content-warnings' />
|
||||
<span className='hint'>
|
||||
<FormattedMessage
|
||||
id='settings.deprecated_setting'
|
||||
defaultMessage="This setting is now controlled from Mastodon's {settings_page_link}"
|
||||
values={{
|
||||
settings_page_link: (
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id='settings.shared_settings_link'
|
||||
defaultMessage='user preferences'
|
||||
/>
|
||||
</span>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</DeprecatedLocalSettingsPageItem>
|
||||
</LocalSettingsPageItem>
|
||||
<LocalSettingsPageItem
|
||||
settings={settings}
|
||||
item={['content_warnings', 'filter']}
|
||||
id='mastodon-settings--content_warnings-auto_unfold'
|
||||
onChange={onChange}
|
||||
dependsOn={[['content_warnings', 'auto_unfold']]}
|
||||
placeholder={intl.formatMessage(messages.regexp)}
|
||||
disabled={!expandSpoilers}
|
||||
>
|
||||
<FormattedMessage id='settings.content_warnings_filter' defaultMessage='Content warnings to not automatically unfold:' />
|
||||
</LocalSettingsPageItem>
|
||||
|
||||
@@ -55,6 +55,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||
singleColumn: PropTypes.bool,
|
||||
children: PropTypes.node,
|
||||
openSettings: PropTypes.func,
|
||||
onLogout: PropTypes.func,
|
||||
};
|
||||
|
||||
// Corresponds to (max-width: $no-gap-breakpoint + 285px - 1px) in SCSS
|
||||
@@ -139,7 +140,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||
};
|
||||
|
||||
render () {
|
||||
const { columns, children, singleColumn, openSettings } = this.props;
|
||||
const { columns, children, singleColumn, openSettings, onLogout } = this.props;
|
||||
const { renderComposePanel } = this.state;
|
||||
|
||||
if (singleColumn) {
|
||||
@@ -158,7 +159,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||
|
||||
<div className='columns-area__panels__pane columns-area__panels__pane--start columns-area__panels__pane--navigational'>
|
||||
<div className='columns-area__panels__pane__inner'>
|
||||
<NavigationPanel onOpenSettings={openSettings} />
|
||||
<NavigationPanel onOpenSettings={openSettings} onLogout={onLogout} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,6 @@ import illustration from 'flavours/glitch/images/logo_warn_glitch.svg';
|
||||
|
||||
const messages = defineMessages({
|
||||
discardChanges: { id: 'confirmations.deprecated_settings.confirm', defaultMessage: 'Use Mastodon preferences' },
|
||||
user_setting_expand_spoilers: { id: 'settings.enable_content_warnings_auto_unfold', defaultMessage: 'Automatically unfold content-warnings' },
|
||||
user_setting_disable_swiping: { id: 'settings.swipe_to_change_columns', defaultMessage: 'Allow swiping to change columns (Mobile only)' },
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import CharacterCounter from 'flavours/glitch/features/compose/components/charac
|
||||
import UploadProgress from 'flavours/glitch/features/compose/components/upload_progress';
|
||||
import { Tesseract as fetchTesseract } from 'flavours/glitch/features/ui/util/async-components';
|
||||
import Video, { getPointerPosition } from 'flavours/glitch/features/video';
|
||||
import { me } from 'flavours/glitch/initial_state';
|
||||
import { me , maxMediaDescChars } from 'flavours/glitch/initial_state';
|
||||
import { assetHost } from 'flavours/glitch/utils/config';
|
||||
|
||||
import { changeUploadCompose, uploadThumbnail, onChangeMediaDescription, onChangeMediaFocus } from '../../../actions/compose';
|
||||
@@ -367,10 +367,10 @@ class FocalPointModal extends ImmutablePureComponent {
|
||||
|
||||
<div className='setting-text__toolbar'>
|
||||
<button disabled={detecting || media.get('type') !== 'image' || is_changing_upload} className='link-button' onClick={this.handleTextDetection}><FormattedMessage id='upload_modal.detect_text' defaultMessage='Detect text from picture' /></button>
|
||||
<CharacterCounter max={1500} text={detecting ? '' : description} />
|
||||
<CharacterCounter max={maxMediaDescChars} text={detecting ? '' : description} />
|
||||
</div>
|
||||
|
||||
<Button disabled={!dirty || detecting || isUploadingThumbnail || length(description) > 1500 || is_changing_upload} text={intl.formatMessage(is_changing_upload ? messages.applying : messages.apply)} onClick={this.handleSubmit} />
|
||||
<Button disabled={!dirty || detecting || isUploadingThumbnail || length(description) > maxMediaDescChars || is_changing_upload} text={intl.formatMessage(is_changing_upload ? messages.applying : messages.apply)} onClick={this.handleSubmit} />
|
||||
</div>
|
||||
|
||||
<div className='focal-point-modal__content'>
|
||||
|
||||
@@ -30,6 +30,7 @@ const messages = defineMessages({
|
||||
advancedInterface: { id: 'navigation_bar.advanced_interface', defaultMessage: 'Open in advanced web interface' },
|
||||
openedInClassicInterface: { id: 'navigation_bar.opened_in_classic_interface', defaultMessage: 'Posts, accounts, and other specific pages are opened by default in the classic web interface.' },
|
||||
app_settings: { id: 'navigation_bar.app_settings', defaultMessage: 'App settings' },
|
||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Log out' },
|
||||
});
|
||||
|
||||
class NavigationPanel extends Component {
|
||||
@@ -42,6 +43,7 @@ class NavigationPanel extends Component {
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onOpenSettings: PropTypes.func,
|
||||
onLogout: PropTypes.func,
|
||||
};
|
||||
|
||||
isFirehoseActive = (match, location) => {
|
||||
@@ -49,7 +51,7 @@ class NavigationPanel extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { intl, onOpenSettings } = this.props;
|
||||
const { intl, onOpenSettings, onLogout } = this.props;
|
||||
const { signedIn, disabledAccountId } = this.context.identity;
|
||||
|
||||
return (
|
||||
@@ -104,6 +106,7 @@ class NavigationPanel extends Component {
|
||||
<hr />
|
||||
|
||||
<ColumnLink transparent onClick={onOpenSettings} icon='cogs' text={intl.formatMessage(messages.app_settings)} />
|
||||
<ColumnLink transparent onClick={onLogout} icon='sign-out' text={intl.formatMessage(messages.logout)} />
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -112,6 +115,7 @@ class NavigationPanel extends Component {
|
||||
<ColumnLink transparent to='/about' icon='ellipsis-h' text={intl.formatMessage(messages.about)} />
|
||||
</div>
|
||||
|
||||
|
||||
<NavigationPortal />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { openModal } from 'flavours/glitch/actions/modal';
|
||||
import { logOut } from 'flavours/glitch/utils/log_out';
|
||||
|
||||
import ColumnsArea from '../components/columns_area';
|
||||
|
||||
const messages = defineMessages({
|
||||
logoutMessage: { id: 'confirmations.logout.message', defaultMessage: 'Are you sure you want to log out?' },
|
||||
logoutConfirm: { id: 'confirmations.logout.confirm', defaultMessage: 'Log out' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
columns: state.getIn(['settings', 'columns']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||
openSettings (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -17,6 +25,17 @@ const mapDispatchToProps = dispatch => ({
|
||||
modalProps: {},
|
||||
}));
|
||||
},
|
||||
onLogout () {
|
||||
dispatch(openModal({
|
||||
modalType: 'CONFIRM',
|
||||
modalProps: {
|
||||
message: intl.formatMessage(messages.logoutMessage),
|
||||
confirm: intl.formatMessage(messages.logoutConfirm),
|
||||
closeWhenConfirm: false,
|
||||
onConfirm: () => logOut(),
|
||||
},
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(ColumnsArea);
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })(ColumnsArea));
|
||||
|
||||
@@ -149,7 +149,9 @@ class SwitchingColumnsArea extends PureComponent {
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
if (![this.props.location.pathname, '/'].includes(prevProps.location.pathname)) {
|
||||
this.node.handleChildrenContentChange();
|
||||
if (this.node && this.node.handleChildrenContentChange === 'function') {
|
||||
this.node.handleChildrenContentChange();
|
||||
}
|
||||
}
|
||||
|
||||
if (prevProps.singleColumn !== this.props.singleColumn) {
|
||||
|
||||
@@ -104,6 +104,7 @@ export const hasMultiColumnPath = initialPath === '/'
|
||||
* @property {object} local_settings
|
||||
* @property {number} max_toot_chars
|
||||
* @property {number} max_media_attachments
|
||||
* @property {number} max_media_desc_chars
|
||||
* @property {number} poll_limits
|
||||
*/
|
||||
|
||||
@@ -167,6 +168,7 @@ export const sso_redirect = getMeta('sso_redirect');
|
||||
// Glitch-soc-specific settings
|
||||
export const maxChars = (initialState && initialState.max_toot_chars) || 500;
|
||||
export const maxMediaAttachments = (initialState && initialState.max_media_attachments) || 4;
|
||||
export const maxMediaDescChars = (initialState && initialState.max_media_desc_chars) || 1500;
|
||||
export const favouriteModal = getMeta('favourite_modal');
|
||||
export const pollLimits = (initialState && initialState.poll_limits);
|
||||
export const defaultContentType = getMeta('default_content_type');
|
||||
|
||||
@@ -23,6 +23,7 @@ const initialState = ImmutableMap({
|
||||
tag_misleading_links: true,
|
||||
rewrite_mentions: 'no',
|
||||
content_warnings : ImmutableMap({
|
||||
auto_unfold : false,
|
||||
filter : null,
|
||||
media_outside: true,
|
||||
shared_state : true,
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
}
|
||||
|
||||
@mixin search-input() {
|
||||
outline: 0;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
|
||||
@@ -164,10 +164,6 @@ body {
|
||||
button {
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.app-holder {
|
||||
@@ -178,7 +174,6 @@ button {
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
& > noscript {
|
||||
@@ -250,7 +245,6 @@ button {
|
||||
margin: 0;
|
||||
line-height: inherit;
|
||||
cursor: pointer;
|
||||
outline: 0;
|
||||
transition: color 300ms linear;
|
||||
text-decoration: underline;
|
||||
|
||||
|
||||
@@ -753,7 +753,6 @@
|
||||
font-size: 14px;
|
||||
resize: none;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
border-radius: 4px;
|
||||
|
||||
&::placeholder {
|
||||
|
||||
@@ -260,10 +260,6 @@ $ui-header-height: 55px;
|
||||
background: lighten($ui-base-color, 11%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&--transparent {
|
||||
background: transparent;
|
||||
color: $ui-secondary-color;
|
||||
@@ -350,7 +346,6 @@ $ui-header-height: 55px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
outline: 0;
|
||||
overflow: hidden;
|
||||
|
||||
& > button {
|
||||
@@ -377,11 +372,6 @@ $ui-header-height: 55px;
|
||||
text-shadow: 0 0 10px rgba($ui-highlight-color, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.column {
|
||||
@@ -743,10 +733,6 @@ $ui-header-height: 55px;
|
||||
input {
|
||||
width: 100%;
|
||||
margin-bottom: 6px;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -786,16 +772,6 @@ $ui-header-height: 55px;
|
||||
color: lighten($darker-text-color, 4%);
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: lighten($ui-base-color, 4%);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
outline: 0;
|
||||
color: $inverted-text-color;
|
||||
background: $simple-background-color;
|
||||
font-size: 14px;
|
||||
@@ -61,9 +60,6 @@
|
||||
color: $dark-text-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
@include single-column('screen and (max-width: 630px)') {
|
||||
font-size: 16px;
|
||||
}
|
||||
@@ -220,7 +216,6 @@
|
||||
padding: 10px 32px 0 10px;
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
outline: 0;
|
||||
color: $inverted-text-color;
|
||||
background: $simple-background-color;
|
||||
font-size: 14px;
|
||||
@@ -236,10 +231,6 @@
|
||||
all: unset;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@include single-column('screen and (max-width: 630px)') {
|
||||
font-size: 16px;
|
||||
}
|
||||
@@ -670,7 +661,6 @@
|
||||
&.active {
|
||||
background: $ui-highlight-color;
|
||||
color: $primary-text-color;
|
||||
outline: 0;
|
||||
|
||||
.language-dropdown__dropdown__results__item__common-name {
|
||||
color: $secondary-text-color;
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
outline: none;
|
||||
background: lighten($ui-base-color, 3%);
|
||||
transition: background 200ms ease-out;
|
||||
}
|
||||
|
||||
@@ -76,14 +76,8 @@
|
||||
padding-bottom: 2px;
|
||||
padding-inline-start: 2px;
|
||||
padding-inline-end: 5px;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
img {
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.8;
|
||||
|
||||
@@ -123,16 +123,6 @@
|
||||
border: 1px solid $ui-secondary-color;
|
||||
border-radius: 4px;
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
border-bottom: 1px $ui-secondary-color solid;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
transition: background 0.3s;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
|
||||
@@ -454,10 +454,6 @@
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.detailed-status & {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -483,7 +479,6 @@
|
||||
max-height: 100% !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,7 +585,6 @@
|
||||
|
||||
.player-button {
|
||||
display: inline-block;
|
||||
outline: 0;
|
||||
flex: 0 0 auto;
|
||||
background: transparent;
|
||||
padding: 5px;
|
||||
|
||||
@@ -198,16 +198,6 @@
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&.inverted {
|
||||
color: $lighter-text-color;
|
||||
|
||||
@@ -282,7 +272,6 @@
|
||||
cursor: pointer;
|
||||
padding: 0 3px;
|
||||
white-space: nowrap;
|
||||
outline: 0;
|
||||
transition: all 100ms ease-in;
|
||||
transition-property: background-color, color;
|
||||
|
||||
@@ -308,16 +297,6 @@
|
||||
&.active {
|
||||
color: $highlight-text-color;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
body > [data-popper-placement] {
|
||||
@@ -623,7 +602,6 @@ body > [data-popper-placement] {
|
||||
&:hover,
|
||||
&:active {
|
||||
background: var(--dropdown-border-color);
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1038,7 +1016,6 @@ body > [data-popper-placement] {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-bottom: 2px solid $ui-primary-color;
|
||||
outline: 0;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
font-family: inherit;
|
||||
@@ -1195,12 +1172,8 @@ button.icon-button.active i.fa-retweet {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0 !important;
|
||||
|
||||
.ckbox {
|
||||
box-shadow: 0 0 1px 1px $ui-highlight-color;
|
||||
}
|
||||
&:focus.ckbox {
|
||||
box-shadow: 0 0 1px 1px $ui-highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1523,7 +1496,6 @@ button.icon-button.active i.fa-retweet {
|
||||
|
||||
&:focus {
|
||||
background: lighten($ui-base-color, 2%);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
|
||||
@@ -693,17 +693,12 @@
|
||||
line-height: 22px;
|
||||
resize: vertical;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
border-radius: 4px;
|
||||
margin: 20px 0;
|
||||
|
||||
&::placeholder {
|
||||
color: $dark-text-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
@@ -821,7 +816,6 @@
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
resize: none;
|
||||
outline: 0;
|
||||
border-radius: 4px;
|
||||
border: 1px solid $ui-secondary-color;
|
||||
min-height: 100px;
|
||||
@@ -1019,7 +1013,6 @@
|
||||
color: $inverted-text-color;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
outline: 0;
|
||||
font-family: inherit;
|
||||
background: $simple-background-color
|
||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(darken($simple-background-color, 14%))}'/></svg>")
|
||||
@@ -1128,7 +1121,6 @@
|
||||
}
|
||||
|
||||
.embed-modal__html {
|
||||
outline: 0;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
@@ -1142,16 +1134,6 @@
|
||||
margin-bottom: 15px;
|
||||
border-radius: 4px;
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: lighten($ui-base-color, 4%);
|
||||
}
|
||||
@@ -1377,10 +1359,6 @@ img.modal-warning {
|
||||
&::placeholder {
|
||||
color: lighten($darker-text-color, 4%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
@@ -1477,7 +1455,6 @@ img.modal-warning {
|
||||
overflow: hidden;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
background: darken($ui-base-color, 4%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,37 +107,17 @@
|
||||
color: lighten($darker-text-color, 4%);
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: lighten($ui-base-color, 4%);
|
||||
}
|
||||
}
|
||||
|
||||
.search__icon {
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
.fa {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
inset-inline-end: 10px;
|
||||
display: inline-block;
|
||||
opacity: 0;
|
||||
transition: all 100ms linear;
|
||||
transition-property: color, transform, opacity;
|
||||
font-size: 18px;
|
||||
|
||||
@@ -57,10 +57,6 @@
|
||||
padding-top: 5px;
|
||||
clear: both;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.emojione {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -213,7 +209,6 @@
|
||||
|
||||
.focusable {
|
||||
&:focus {
|
||||
outline: 0;
|
||||
background: lighten($ui-base-color, 4%);
|
||||
|
||||
&.status.status-direct {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
align-items: center;
|
||||
color: $primary-text-color;
|
||||
text-decoration: none;
|
||||
outline: 0;
|
||||
padding: 12px 16px;
|
||||
line-height: 32px;
|
||||
font-weight: 500;
|
||||
|
||||
@@ -432,7 +432,6 @@ code {
|
||||
color: $primary-text-color;
|
||||
display: block;
|
||||
width: 100%;
|
||||
outline: 0;
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
background: darken($ui-base-color, 10%);
|
||||
@@ -535,7 +534,6 @@ code {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
outline: 0;
|
||||
margin-bottom: 10px;
|
||||
margin-inline-end: 10px;
|
||||
|
||||
@@ -581,7 +579,6 @@ code {
|
||||
color: $primary-text-color;
|
||||
display: block;
|
||||
width: 100%;
|
||||
outline: 0;
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
background: darken($ui-base-color, 10%)
|
||||
@@ -702,7 +699,6 @@ code {
|
||||
}
|
||||
|
||||
.oauth-code {
|
||||
outline: 0;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
@@ -714,16 +710,6 @@ code {
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: lighten($ui-base-color, 4%);
|
||||
}
|
||||
|
||||
@@ -5,88 +5,76 @@
|
||||
@import 'basics';
|
||||
|
||||
body {
|
||||
height: 100vh;
|
||||
|
||||
a {
|
||||
color: #89caff;
|
||||
}
|
||||
font-family: ui-rounded, mastodon-font-sans-serif, sans-serif;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
max-width: 30rem;
|
||||
--login-row-gap: 10px;
|
||||
|
||||
display: grid;
|
||||
row-gap: var(--login-row-gap);
|
||||
margin: 50px auto;
|
||||
padding: 1rem;
|
||||
margin: auto;
|
||||
max-width: 30rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mascot {
|
||||
height: 10rem;
|
||||
img {
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
row-gap: var(--login-row-gap);
|
||||
}
|
||||
|
||||
.login {
|
||||
display: flex;
|
||||
position: relative;
|
||||
column-gap: 10px;
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
line-height: 33px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.instance {
|
||||
background: #282c37;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
color: #9baec8;
|
||||
display: block;
|
||||
label {
|
||||
font-family: inherit;
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
padding: 15px;
|
||||
padding-inline-end: 30px;
|
||||
width: 100%;
|
||||
color: $primary-text-color;
|
||||
display: block;
|
||||
word-wrap: break-word;
|
||||
font-weight: 500;
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
column-gap: .5rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #66befe;
|
||||
border: 0 none;
|
||||
form {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
grid-template-columns: 1fr min-content;
|
||||
}
|
||||
|
||||
:focus-visible,
|
||||
button:focus-visible {
|
||||
outline: 2px solid #66befe;
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 7px 10px;
|
||||
border: 1px solid lighten(#66befe, 7%);
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
color: #2a2b2f;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
letter-spacing: 0;
|
||||
line-height: 22px;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: 500;
|
||||
padding: 7px 10px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
flex-basis: auto;
|
||||
background-color: #66befe;
|
||||
|
||||
&:hover {
|
||||
background-color: #89caff;
|
||||
@@ -98,21 +86,35 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #444b5d;
|
||||
input[type='text'] {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
border: 1px solid lighten(#282c37, 7%);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: .75rem;
|
||||
box-sizing: border-box;
|
||||
box-shadow: none;
|
||||
color: #9baec8;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: 18px;
|
||||
background: #282c37;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20px 15px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid lighten(#39404f, 7%);
|
||||
color: #fff;
|
||||
background-color: #39404f;
|
||||
}
|
||||
|
||||
.link-footer {
|
||||
padding: 10px;
|
||||
padding-inline: 10px;
|
||||
color: #97a8b4;
|
||||
font-size: 0.875rem;
|
||||
|
||||
p, a {
|
||||
color: #97A8B4;
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: $inverted-text-color;
|
||||
outline: 0;
|
||||
font-family: inherit;
|
||||
background: $simple-background-color;
|
||||
border: 1px solid darken($simple-background-color, 14%);
|
||||
@@ -139,16 +138,6 @@
|
||||
border-color: $valid-value-color;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
outline: 0 !important;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
border-color: $dark-text-color;
|
||||
|
||||
@@ -285,7 +274,6 @@
|
||||
color: $inverted-text-color;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
outline: 0;
|
||||
font-family: inherit;
|
||||
background: $simple-background-color
|
||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(darken($simple-background-color, 14%))}'/></svg>")
|
||||
|
||||
@@ -96,7 +96,8 @@ $dismiss-overlay-width: 4rem;
|
||||
:root {
|
||||
--dropdown-border-color: #{lighten($ui-base-color, 12%)};
|
||||
--dropdown-background-color: #{lighten($ui-base-color, 4%)};
|
||||
--dropdown-shadow: 0 20px 25px -5px #{rgba($base-shadow-color, 0.25)},
|
||||
--dropdown-shadow:
|
||||
0 20px 25px -5px #{rgba($base-shadow-color, 0.25)},
|
||||
0 8px 10px -6px #{rgba($base-shadow-color, 0.25)};
|
||||
--modal-background-color: #{darken($ui-base-color, 4%)};
|
||||
--modal-border-color: #{lighten($ui-base-color, 4%)};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { expandSpoilers } from 'flavours/glitch/initial_state';
|
||||
|
||||
function _autoUnfoldCW(spoiler_text, skip_unfold_regex) {
|
||||
if (!expandSpoilers)
|
||||
function _autoUnfoldCW(spoiler_text, settings) {
|
||||
if (!settings.getIn(['content_warnings', 'auto_unfold']))
|
||||
return false;
|
||||
|
||||
const skip_unfold_regex = settings.getIn(['content_warnings', 'filter']);
|
||||
|
||||
if (!skip_unfold_regex)
|
||||
return true;
|
||||
|
||||
@@ -20,12 +20,12 @@ function _autoUnfoldCW(spoiler_text, skip_unfold_regex) {
|
||||
}
|
||||
|
||||
export function autoHideCW(settings, spoiler_text) {
|
||||
return !_autoUnfoldCW(spoiler_text, settings.getIn(['content_warnings', 'filter']));
|
||||
return !_autoUnfoldCW(spoiler_text, settings);
|
||||
}
|
||||
|
||||
export function autoUnfoldCW(settings, status) {
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
return _autoUnfoldCW(status.get('spoiler_text'), settings.getIn(['content_warnings', 'filter']));
|
||||
return _autoUnfoldCW(status.get('spoiler_text'), settings);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,21 @@ export const fetchServer = () => (dispatch, getState) => {
|
||||
|
||||
dispatch(fetchServerRequest());
|
||||
|
||||
api(getState)
|
||||
.get('/api/v2/instance').then(({ data }) => {
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
}).catch(err => dispatch(fetchServerFail(err)));
|
||||
/* global data */
|
||||
try {
|
||||
api(getState)
|
||||
.get('/api/v2/instance').then({ data }).catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
} catch (e) {
|
||||
api(getState)
|
||||
.get('/api/v1/instance').then(({ data }) => {
|
||||
if (data.contact_account) dispatch(importFetchedAccount(data.contact_account));
|
||||
dispatch(fetchServerSuccess(data));
|
||||
}).catch(err => dispatch(fetchServerFail(err)));
|
||||
}
|
||||
};
|
||||
|
||||
const fetchServerRequest = () => ({
|
||||
|
||||
@@ -23,7 +23,7 @@ import Audio from 'mastodon/features/audio';
|
||||
import CharacterCounter from 'mastodon/features/compose/components/character_counter';
|
||||
import UploadProgress from 'mastodon/features/compose/components/upload_progress';
|
||||
import { Tesseract as fetchTesseract } from 'mastodon/features/ui/util/async-components';
|
||||
import { me } from 'mastodon/initial_state';
|
||||
import { me , maxMediaDescChars } from 'mastodon/initial_state';
|
||||
import { assetHost } from 'mastodon/utils/config';
|
||||
|
||||
import { changeUploadCompose, uploadThumbnail, onChangeMediaDescription, onChangeMediaFocus } from '../../../actions/compose';
|
||||
@@ -374,12 +374,12 @@ class FocalPointModal extends ImmutablePureComponent {
|
||||
>
|
||||
<FormattedMessage id='upload_modal.detect_text' defaultMessage='Detect text from picture' />
|
||||
</button>
|
||||
<CharacterCounter max={1500} text={detecting ? '' : description} />
|
||||
<CharacterCounter max={maxMediaDescChars} text={detecting ? '' : description} />
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type='submit'
|
||||
disabled={!dirty || detecting || isUploadingThumbnail || length(description) > 1500 || is_changing_upload}
|
||||
disabled={!dirty || detecting || isUploadingThumbnail || length(description) > maxMediaDescChars || is_changing_upload}
|
||||
text={intl.formatMessage(is_changing_upload ? messages.applying : messages.apply)}
|
||||
/>
|
||||
</form>
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
* @property {boolean=} critical_updates_pending
|
||||
* @property {InitialStateMeta} meta
|
||||
* @property {number} max_toot_chars
|
||||
* @property {number} max_media_desc_chars
|
||||
*/
|
||||
|
||||
const element = document.getElementById('initial-state');
|
||||
@@ -149,5 +150,6 @@ export const sso_redirect = getMeta('sso_redirect');
|
||||
|
||||
// Glitch-soc-specific settings
|
||||
export const maxChars = (initialState && initialState.max_toot_chars) || 500;
|
||||
export const maxMediaDescChars = (initialState && initialState.max_media_desc_chars) || 1500;
|
||||
|
||||
export default initialState;
|
||||
|
||||
@@ -96,7 +96,8 @@ $font-monospace: 'mastodon-font-monospace' !default;
|
||||
:root {
|
||||
--dropdown-border-color: #{lighten($ui-base-color, 12%)};
|
||||
--dropdown-background-color: #{lighten($ui-base-color, 4%)};
|
||||
--dropdown-shadow: 0 20px 25px -5px #{rgba($base-shadow-color, 0.25)},
|
||||
--dropdown-shadow:
|
||||
0 20px 25px -5px #{rgba($base-shadow-color, 0.25)},
|
||||
0 8px 10px -6px #{rgba($base-shadow-color, 0.25)};
|
||||
--modal-background-color: #{darken($ui-base-color, 4%)};
|
||||
--modal-border-color: #{lighten($ui-base-color, 4%)};
|
||||
|
||||
+3
-2
@@ -208,7 +208,7 @@
|
||||
"jest": "^29.5.0",
|
||||
"jest-environment-jsdom": "^29.5.0",
|
||||
"lint-staged": "^13.2.2",
|
||||
"prettier": "^3.0.0",
|
||||
"prettier": "3.6.2",
|
||||
"react-test-renderer": "^18.2.0",
|
||||
"stylelint": "^15.10.1",
|
||||
"stylelint-config-standard-scss": "^11.0.0",
|
||||
@@ -230,5 +230,6 @@
|
||||
"Capfile|Gemfile|*.{rb,ruby,ru,rake}": "bundle exec rubocop --force-exclusion -a",
|
||||
"*.{js,jsx,ts,tsx}": "eslint --fix",
|
||||
"*.{css,scss}": "stylelint --fix"
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@4.10.3"
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,5 +1,11 @@
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
await ready();
|
||||
|
||||
const form = document.querySelector('#login')
|
||||
form?.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
auth();
|
||||
});
|
||||
});
|
||||
|
||||
async function ready() {
|
||||
@@ -20,7 +26,7 @@ async function ready() {
|
||||
async function auth() {
|
||||
setMessage('Please wait');
|
||||
|
||||
const instance = document.getElementById('instance').value;
|
||||
const instance = document.getElementById('instance').value.trim();
|
||||
const matches = instance.match(/((?:http|https):\/\/)?(.*)/);
|
||||
|
||||
const protocol = matches[1];
|
||||
|
||||
+13
-17
@@ -5,35 +5,31 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Login | Masto-FE (🦥 flavour)</title>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<link rel="stylesheet" media="all" href="/packs/css/core/common.css" />
|
||||
<link rel="stylesheet" media="all" href="/packs/css/flavours/glitch/login.css" />
|
||||
<script src="/auth.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body class="app-body">
|
||||
<div class="login-container">
|
||||
<header>
|
||||
<img class="mascot" alt src="images/mascot.svg" />
|
||||
<img alt="a friendly smiling sloth" src="images/mascot.svg" />
|
||||
</header>
|
||||
<main>
|
||||
<div class="login">
|
||||
<input class="instance" id="instance" placeholder="Instance URL" aria-label="Instance URL" value="" onkeypress="if (event.keyCode == 13) auth()">
|
||||
<button type="submit" class="button" id="btn" onclick="auth()">
|
||||
<h1>Log into your instance</h1>
|
||||
<form method="post" id="login">
|
||||
<label for="instance">Instance URL</label>
|
||||
<input type="text" id="instance" value="" class="input instance">
|
||||
<button type="submit" class="button" id="btn">
|
||||
<span id="message">Authorize</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="content">
|
||||
</form>
|
||||
<aside class="content">
|
||||
<p>
|
||||
This is a standalone version of the Mastodon front-end that offers compatibility with GoToSocial instances. It is based
|
||||
on <a href="https://iceshrimp.dev/iceshrimp/masto-fe-standalone" rel="nofollow">Iceshrimp's Masto-FE Standalone</a>,
|
||||
which is itself a fork of <a href="https://github.com/glitch-soc/mastodon" rel="nofollow">Mastodon Glitch Edition</a>,
|
||||
which in turn forks <a href="https://github.com/mastodon/mastodon/" rel="nofollow">Mastodon</a>. Phew!
|
||||
<strong>Note:</strong>
|
||||
this application is completely client-side, meaning everything happens in the browser on your machine.
|
||||
It does not store information anywhere else than your browser's local storage.
|
||||
</p>
|
||||
<p>
|
||||
The application is completely client-side, meaning everything happens in the browser on your machine. It does not store
|
||||
information anywhere else than your browser's local storage.
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
</main>
|
||||
<footer class="link-footer">
|
||||
<p>
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Logout | Masto-FE (🦥 flavour)</title>
|
||||
<script>
|
||||
const preserveSettings = localStorage.getItem("mastodon-settings");
|
||||
localStorage.clear();
|
||||
if (preserveSettings !== null) {
|
||||
localStorage.setItem("mastodon-settings", preserveSettings);
|
||||
}
|
||||
window.location.href = "/login.html";
|
||||
</script>
|
||||
</head>
|
||||
|
||||
+10
-1
@@ -23,7 +23,15 @@ async function loadState() {
|
||||
}
|
||||
|
||||
const apiUrl = `${protocol}${domain}/api`;
|
||||
const instance = await fetch(`${apiUrl}/v1/instance`).then(async p => await p.json());
|
||||
let instance
|
||||
try {
|
||||
instance = await fetch(`${apiUrl}/v2/instance`).then(async p => await p.json());
|
||||
if (!instance.configuration) {
|
||||
throw new Error('Instance API v2 unavaialble');
|
||||
}
|
||||
} catch (e) {
|
||||
instance = await fetch(`${apiUrl}/v1/instance`).then(async p => await p.json());
|
||||
}
|
||||
const options = {headers: {Authorization: `Bearer ${access_token}`}};
|
||||
const credentials = await fetch(`${apiUrl}/v1/accounts/verify_credentials`, options).then(async p => await p.json());
|
||||
const state = {
|
||||
@@ -93,6 +101,7 @@ async function loadState() {
|
||||
},
|
||||
"max_toot_chars": instance.configuration.statuses.max_characters,
|
||||
"max_media_attachments": instance.configuration.statuses.max_media_attachments,
|
||||
"max_media_desc_chars": instance.configuration.media_attachments.description_limit,
|
||||
"poll_limits": {
|
||||
"max_expiration": instance.configuration.polls.max_expiration,
|
||||
"max_option_chars": instance.configuration.polls.max_characters_per_option,
|
||||
|
||||
Reference in New Issue
Block a user