Merge remote-tracking branch 'soapbox/develop' into cleanup
This commit is contained in:
commit
690621e0a3
9 changed files with 35 additions and 27 deletions
|
@ -36,8 +36,8 @@ danger:
|
||||||
- export CI_MERGE_REQUEST_IID=${CI_OPEN_MERGE_REQUESTS#*!}
|
- export CI_MERGE_REQUEST_IID=${CI_OPEN_MERGE_REQUESTS#*!}
|
||||||
- npx danger ci
|
- npx danger ci
|
||||||
except:
|
except:
|
||||||
refs:
|
variables:
|
||||||
- $CI_DEFAULT_BRANCH
|
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
|
||||||
lint-js:
|
lint-js:
|
||||||
|
@ -115,8 +115,8 @@ docs-deploy:
|
||||||
script:
|
script:
|
||||||
- curl -X POST -F"token=$CI_JOB_TOKEN" -F'ref=master' https://gitlab.com/api/v4/projects/15685485/trigger/pipeline
|
- curl -X POST -F"token=$CI_JOB_TOKEN" -F'ref=master' https://gitlab.com/api/v4/projects/15685485/trigger/pipeline
|
||||||
only:
|
only:
|
||||||
refs:
|
variables:
|
||||||
- $CI_DEFAULT_BRANCH
|
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
|
||||||
changes:
|
changes:
|
||||||
- "docs/**/*"
|
- "docs/**/*"
|
||||||
|
|
||||||
|
@ -141,8 +141,8 @@ pages:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
only:
|
only:
|
||||||
refs:
|
variables:
|
||||||
- $CI_DEFAULT_BRANCH
|
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
@ -157,8 +157,8 @@ docker:
|
||||||
- docker build -t $CI_REGISTRY_IMAGE .
|
- docker build -t $CI_REGISTRY_IMAGE .
|
||||||
- docker push $CI_REGISTRY_IMAGE
|
- docker push $CI_REGISTRY_IMAGE
|
||||||
only:
|
only:
|
||||||
refs:
|
variables:
|
||||||
- $CI_DEFAULT_BRANCH
|
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
|
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
|
||||||
|
|
|
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Compatibility: rudimentary support for Takahē.
|
- Compatibility: rudimentary support for Takahē.
|
||||||
|
- UI: added backdrop blur behind modals.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Posts: letterbox images to 19:6 again.
|
- Posts: letterbox images to 19:6 again.
|
||||||
|
@ -15,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Fixed
|
### Fixed
|
||||||
- Layout: use accent color for "floating action button" (mobile compose button).
|
- Layout: use accent color for "floating action button" (mobile compose button).
|
||||||
- ServiceWorker: don't serve favicon, robots.txt, and others from ServiceWorker.
|
- ServiceWorker: don't serve favicon, robots.txt, and others from ServiceWorker.
|
||||||
|
- Datepicker: correctly default to the current year.
|
||||||
|
- Scheduled posts: fix page crashing on deleting a scheduled post.
|
||||||
|
|
||||||
## [3.0.0] - 2022-12-25
|
## [3.0.0] - 2022-12-25
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type })
|
||||||
<div
|
<div
|
||||||
role='presentation'
|
role='presentation'
|
||||||
id='modal-overlay'
|
id='modal-overlay'
|
||||||
className='fixed inset-0 bg-gray-500/90 dark:bg-gray-700/90'
|
className='fixed inset-0 bg-gray-500/90 dark:bg-gray-700/90 backdrop-blur'
|
||||||
onClick={handleOnClose}
|
onClick={handleOnClose}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ const Datepicker = ({ onChange }: IDatepicker) => {
|
||||||
|
|
||||||
const [month, setMonth] = useState<number>(new Date().getMonth());
|
const [month, setMonth] = useState<number>(new Date().getMonth());
|
||||||
const [day, setDay] = useState<number>(new Date().getDate());
|
const [day, setDay] = useState<number>(new Date().getDate());
|
||||||
const [year, setYear] = useState<number>(2022);
|
const [year, setYear] = useState<number>(new Date().getFullYear());
|
||||||
|
|
||||||
const numberOfDays = useMemo(() => {
|
const numberOfDays = useMemo(() => {
|
||||||
return getDaysInMonth(month, year);
|
return getDaysInMonth(month, year);
|
||||||
|
|
|
@ -20,7 +20,12 @@ interface IScheduledStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScheduledStatus: React.FC<IScheduledStatus> = ({ statusId, ...other }) => {
|
const ScheduledStatus: React.FC<IScheduledStatus> = ({ statusId, ...other }) => {
|
||||||
const status = useAppSelector((state) => buildStatus(state, state.scheduled_statuses.get(statusId)!)) as StatusEntity;
|
const status = useAppSelector((state) => {
|
||||||
|
const scheduledStatus = state.scheduled_statuses.get(statusId);
|
||||||
|
|
||||||
|
if (!scheduledStatus) return null;
|
||||||
|
return buildStatus(state, scheduledStatus);
|
||||||
|
}) as StatusEntity | null;
|
||||||
|
|
||||||
if (!status) return null;
|
if (!status) return null;
|
||||||
|
|
||||||
|
|
|
@ -455,7 +455,7 @@ export default function compose(state = initialState, action: AnyAction) {
|
||||||
case COMPOSE_POLL_REMOVE:
|
case COMPOSE_POLL_REMOVE:
|
||||||
return updateCompose(state, action.id, compose => compose.set('poll', null));
|
return updateCompose(state, action.id, compose => compose.set('poll', null));
|
||||||
case COMPOSE_SCHEDULE_ADD:
|
case COMPOSE_SCHEDULE_ADD:
|
||||||
return updateCompose(state, action.id, compose => compose.set('schedule', new Date()));
|
return updateCompose(state, action.id, compose => compose.set('schedule', new Date(Date.now() + 10 * 60 * 1000)));
|
||||||
case COMPOSE_SCHEDULE_SET:
|
case COMPOSE_SCHEDULE_SET:
|
||||||
return updateCompose(state, action.id, compose => compose.set('schedule', action.date));
|
return updateCompose(state, action.id, compose => compose.set('schedule', action.date));
|
||||||
case COMPOSE_SCHEDULE_REMOVE:
|
case COMPOSE_SCHEDULE_REMOVE:
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
STATUS_QUOTES_FETCH_REQUEST,
|
STATUS_QUOTES_FETCH_REQUEST,
|
||||||
STATUS_QUOTES_FETCH_SUCCESS,
|
STATUS_QUOTES_FETCH_SUCCESS,
|
||||||
} from 'soapbox/actions/status-quotes';
|
} from 'soapbox/actions/status-quotes';
|
||||||
|
import { STATUS_CREATE_SUCCESS } from 'soapbox/actions/statuses';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BOOKMARKED_STATUSES_FETCH_REQUEST,
|
BOOKMARKED_STATUSES_FETCH_REQUEST,
|
||||||
|
@ -66,7 +67,7 @@ import {
|
||||||
} from '../actions/scheduled-statuses';
|
} from '../actions/scheduled-statuses';
|
||||||
|
|
||||||
import type { AnyAction } from 'redux';
|
import type { AnyAction } from 'redux';
|
||||||
import type { Status as StatusEntity } from 'soapbox/types/entities';
|
import type { APIEntity } from 'soapbox/types/entities';
|
||||||
|
|
||||||
export const StatusListRecord = ImmutableRecord({
|
export const StatusListRecord = ImmutableRecord({
|
||||||
next: null as string | null,
|
next: null as string | null,
|
||||||
|
@ -77,8 +78,6 @@ export const StatusListRecord = ImmutableRecord({
|
||||||
|
|
||||||
type State = ImmutableMap<string, StatusList>;
|
type State = ImmutableMap<string, StatusList>;
|
||||||
type StatusList = ReturnType<typeof StatusListRecord>;
|
type StatusList = ReturnType<typeof StatusListRecord>;
|
||||||
type Status = string | StatusEntity;
|
|
||||||
type Statuses = Array<string | StatusEntity>;
|
|
||||||
|
|
||||||
const initialState: State = ImmutableMap({
|
const initialState: State = ImmutableMap({
|
||||||
favourites: StatusListRecord(),
|
favourites: StatusListRecord(),
|
||||||
|
@ -89,15 +88,15 @@ const initialState: State = ImmutableMap({
|
||||||
joined_events: StatusListRecord(),
|
joined_events: StatusListRecord(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const getStatusId = (status: string | StatusEntity) => typeof status === 'string' ? status : status.id;
|
const getStatusId = (status: string | APIEntity) => typeof status === 'string' ? status : status.id;
|
||||||
|
|
||||||
const getStatusIds = (statuses: Statuses = []) => (
|
const getStatusIds = (statuses: APIEntity[] = []) => (
|
||||||
ImmutableOrderedSet(statuses.map(getStatusId))
|
ImmutableOrderedSet(statuses.map(getStatusId))
|
||||||
);
|
);
|
||||||
|
|
||||||
const setLoading = (state: State, listType: string, loading: boolean) => state.setIn([listType, 'isLoading'], loading);
|
const setLoading = (state: State, listType: string, loading: boolean) => state.setIn([listType, 'isLoading'], loading);
|
||||||
|
|
||||||
const normalizeList = (state: State, listType: string, statuses: Statuses, next: string | null) => {
|
const normalizeList = (state: State, listType: string, statuses: APIEntity[], next: string | null) => {
|
||||||
return state.update(listType, StatusListRecord(), listMap => listMap.withMutations(map => {
|
return state.update(listType, StatusListRecord(), listMap => listMap.withMutations(map => {
|
||||||
map.set('next', next);
|
map.set('next', next);
|
||||||
map.set('loaded', true);
|
map.set('loaded', true);
|
||||||
|
@ -106,7 +105,7 @@ const normalizeList = (state: State, listType: string, statuses: Statuses, next:
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const appendToList = (state: State, listType: string, statuses: Statuses, next: string | null) => {
|
const appendToList = (state: State, listType: string, statuses: APIEntity[], next: string | null) => {
|
||||||
const newIds = getStatusIds(statuses);
|
const newIds = getStatusIds(statuses);
|
||||||
|
|
||||||
return state.update(listType, StatusListRecord(), listMap => listMap.withMutations(map => {
|
return state.update(listType, StatusListRecord(), listMap => listMap.withMutations(map => {
|
||||||
|
@ -116,18 +115,23 @@ const appendToList = (state: State, listType: string, statuses: Statuses, next:
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const prependOneToList = (state: State, listType: string, status: Status) => {
|
const prependOneToList = (state: State, listType: string, status: APIEntity) => {
|
||||||
const statusId = getStatusId(status);
|
const statusId = getStatusId(status);
|
||||||
return state.updateIn([listType, 'items'], ImmutableOrderedSet(), items => {
|
return state.updateIn([listType, 'items'], ImmutableOrderedSet(), items => {
|
||||||
return ImmutableOrderedSet([statusId]).union(items as ImmutableOrderedSet<string>);
|
return ImmutableOrderedSet([statusId]).union(items as ImmutableOrderedSet<string>);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeOneFromList = (state: State, listType: string, status: Status) => {
|
const removeOneFromList = (state: State, listType: string, status: APIEntity) => {
|
||||||
const statusId = getStatusId(status);
|
const statusId = getStatusId(status);
|
||||||
return state.updateIn([listType, 'items'], ImmutableOrderedSet(), items => (items as ImmutableOrderedSet<string>).delete(statusId));
|
return state.updateIn([listType, 'items'], ImmutableOrderedSet(), items => (items as ImmutableOrderedSet<string>).delete(statusId));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const maybeAppendScheduledStatus = (state: State, status: APIEntity) => {
|
||||||
|
if (!status.scheduled_at) return state;
|
||||||
|
return prependOneToList(state, 'scheduled_statuses', getStatusId(status));
|
||||||
|
};
|
||||||
|
|
||||||
export default function statusLists(state = initialState, action: AnyAction) {
|
export default function statusLists(state = initialState, action: AnyAction) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case FAVOURITED_STATUSES_FETCH_REQUEST:
|
case FAVOURITED_STATUSES_FETCH_REQUEST:
|
||||||
|
@ -209,6 +213,8 @@ export default function statusLists(state = initialState, action: AnyAction) {
|
||||||
return setLoading(state, 'joined_events', false);
|
return setLoading(state, 'joined_events', false);
|
||||||
case JOINED_EVENTS_FETCH_SUCCESS:
|
case JOINED_EVENTS_FETCH_SUCCESS:
|
||||||
return normalizeList(state, 'joined_events', action.statuses, action.next);
|
return normalizeList(state, 'joined_events', action.statuses, action.next);
|
||||||
|
case STATUS_CREATE_SUCCESS:
|
||||||
|
return maybeAppendScheduledStatus(state, action.status);
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,6 @@
|
||||||
"dotenv": "^8.0.0",
|
"dotenv": "^8.0.0",
|
||||||
"emoji-datasource": "5.0.1",
|
"emoji-datasource": "5.0.1",
|
||||||
"emoji-mart": "npm:emoji-mart-lazyload",
|
"emoji-mart": "npm:emoji-mart-lazyload",
|
||||||
"entities": "^3.0.1",
|
|
||||||
"es6-symbol": "^3.1.1",
|
"es6-symbol": "^3.1.1",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
"exif-js": "^2.3.0",
|
"exif-js": "^2.3.0",
|
||||||
|
|
|
@ -5184,11 +5184,6 @@ entities@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||||
|
|
||||||
entities@^3.0.1:
|
|
||||||
version "3.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
|
|
||||||
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
|
|
||||||
|
|
||||||
envinfo@^7.7.3:
|
envinfo@^7.7.3:
|
||||||
version "7.8.1"
|
version "7.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
|
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
|
||||||
|
|
Loading…
Reference in a new issue