mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-03-21 13:19:22 +01:00
Experiment: allow minimize composer
This commit is contained in:
parent
8aab997900
commit
cd17ca0b42
13 changed files with 216 additions and 30 deletions
41
src/app.css
41
src/app.css
|
@ -1609,6 +1609,47 @@ body:has(.media-modal-container + .status-deck) .media-post-link {
|
||||||
bottom: calc(16px + env(safe-area-inset-bottom) + 52px);
|
bottom: calc(16px + env(safe-area-inset-bottom) + 52px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#compose-button {
|
||||||
|
&.min {
|
||||||
|
outline: 2px solid var(--button-text-color);
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--button-bg-color);
|
||||||
|
border: 2px solid var(--button-text-color);
|
||||||
|
box-shadow: 0 2px 8px var(--drop-shadow-color);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease-out 0.5s;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.loading {
|
||||||
|
outline-color: var(--button-bg-blur-color);
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
content: '';
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 5s linear infinite;
|
||||||
|
border: 2px dashed var(--button-text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
&:after {
|
||||||
|
background-color: var(--red-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* SHEET */
|
/* SHEET */
|
||||||
|
|
||||||
|
|
|
@ -108,4 +108,5 @@ export const ICONS = {
|
||||||
settings: () => import('@iconify-icons/mingcute/settings-6-line'),
|
settings: () => import('@iconify-icons/mingcute/settings-6-line'),
|
||||||
'heart-break': () => import('@iconify-icons/mingcute/heart-crack-line'),
|
'heart-break': () => import('@iconify-icons/mingcute/heart-crack-line'),
|
||||||
'user-x': () => import('@iconify-icons/mingcute/user-x-line'),
|
'user-x': () => import('@iconify-icons/mingcute/user-x-line'),
|
||||||
|
minimize: () => import('@iconify-icons/mingcute/arrows-down-line'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { getLists } from '../utils/lists';
|
||||||
import niceDateTime from '../utils/nice-date-time';
|
import niceDateTime from '../utils/nice-date-time';
|
||||||
import pmem from '../utils/pmem';
|
import pmem from '../utils/pmem';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
|
import showCompose from '../utils/show-compose';
|
||||||
import showToast from '../utils/show-toast';
|
import showToast from '../utils/show-toast';
|
||||||
import states, { hideAllModals } from '../utils/states';
|
import states, { hideAllModals } from '../utils/states';
|
||||||
import store from '../utils/store';
|
import store from '../utils/store';
|
||||||
|
@ -1081,11 +1082,11 @@ function RelatedActions({
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
states.showCompose = {
|
showCompose({
|
||||||
draftStatus: {
|
draftStatus: {
|
||||||
status: `@${currentInfo?.acct || acct} `,
|
status: `@${currentInfo?.acct || acct} `,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="at" />
|
<Icon icon="at" />
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
import { useSnapshot } from 'valtio';
|
||||||
|
|
||||||
import openCompose from '../utils/open-compose';
|
import openCompose from '../utils/open-compose';
|
||||||
import openOSK from '../utils/open-osk';
|
import openOSK from '../utils/open-osk';
|
||||||
|
@ -7,7 +8,15 @@ import states from '../utils/states';
|
||||||
import Icon from './icon';
|
import Icon from './icon';
|
||||||
|
|
||||||
export default function ComposeButton() {
|
export default function ComposeButton() {
|
||||||
|
const snapStates = useSnapshot(states);
|
||||||
|
|
||||||
function handleButton(e) {
|
function handleButton(e) {
|
||||||
|
if (snapStates.composerState.minimized) {
|
||||||
|
states.composerState.minimized = false;
|
||||||
|
openOSK();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
const newWin = openCompose();
|
const newWin = openCompose();
|
||||||
|
|
||||||
|
@ -28,7 +37,14 @@ export default function ComposeButton() {
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button type="button" id="compose-button" onClick={handleButton}>
|
<button
|
||||||
|
type="button"
|
||||||
|
id="compose-button"
|
||||||
|
onClick={handleButton}
|
||||||
|
class={`${snapStates.composerState.minimized ? 'min' : ''} ${
|
||||||
|
snapStates.composerState.publishing ? 'loading' : ''
|
||||||
|
} ${snapStates.composerState.publishingError ? 'error' : ''}`}
|
||||||
|
>
|
||||||
<Icon icon="quill" size="xl" alt="Compose" />
|
<Icon icon="quill" size="xl" alt="Compose" />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -514,6 +514,7 @@ function Compose({
|
||||||
// I don't think this warrant a draft mode for a status that's already posted
|
// I don't think this warrant a draft mode for a status that's already posted
|
||||||
// Maybe it could be a big edit change but it should be rare
|
// Maybe it could be a big edit change but it should be rare
|
||||||
if (editStatus) return;
|
if (editStatus) return;
|
||||||
|
if (states.composerState.minimized) return;
|
||||||
const key = draftKey();
|
const key = draftKey();
|
||||||
const backgroundDraft = {
|
const backgroundDraft = {
|
||||||
key,
|
key,
|
||||||
|
@ -670,6 +671,11 @@ function Compose({
|
||||||
[replyToStatus],
|
[replyToStatus],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onMinimize = () => {
|
||||||
|
saveUnsavedDraft();
|
||||||
|
states.composerState.minimized = true;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="compose-container-outer">
|
<div id="compose-container-outer">
|
||||||
<div id="compose-container" class={standalone ? 'standalone' : ''}>
|
<div id="compose-container" class={standalone ? 'standalone' : ''}>
|
||||||
|
@ -689,7 +695,7 @@ function Compose({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!standalone ? (
|
{!standalone ? (
|
||||||
<span>
|
<span class="button-group">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="light pop-button"
|
class="light pop-button"
|
||||||
|
@ -736,6 +742,13 @@ function Compose({
|
||||||
>
|
>
|
||||||
<Icon icon="popout" alt="Pop out" />
|
<Icon icon="popout" alt="Pop out" />
|
||||||
</button>{' '}
|
</button>{' '}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="light min-button"
|
||||||
|
onClick={onMinimize}
|
||||||
|
>
|
||||||
|
<Icon icon="minimize" alt="Minimize" />
|
||||||
|
</button>{' '}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="light close-button"
|
class="light close-button"
|
||||||
|
@ -810,6 +823,10 @@ function Compose({
|
||||||
} else {
|
} else {
|
||||||
window.opener.__STATES__.showCompose = true;
|
window.opener.__STATES__.showCompose = true;
|
||||||
}
|
}
|
||||||
|
if (window.opener.__STATES__.composerState.minimized) {
|
||||||
|
// Maximize it
|
||||||
|
window.opener.__STATES__.composerState.minimized = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
@ -915,6 +932,8 @@ function Compose({
|
||||||
spoilerText = (sensitive && spoilerText) || undefined;
|
spoilerText = (sensitive && spoilerText) || undefined;
|
||||||
status = status === '' ? undefined : status;
|
status = status === '' ? undefined : status;
|
||||||
|
|
||||||
|
// states.composerState.minimized = true;
|
||||||
|
states.composerState.publishing = true;
|
||||||
setUIState('loading');
|
setUIState('loading');
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -948,6 +967,8 @@ function Compose({
|
||||||
return result.status === 'rejected' || !result.value?.id;
|
return result.status === 'rejected' || !result.value?.id;
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
states.composerState.publishing = false;
|
||||||
|
states.composerState.publishingError = true;
|
||||||
setUIState('error');
|
setUIState('error');
|
||||||
// Alert all the reasons
|
// Alert all the reasons
|
||||||
results.forEach((result) => {
|
results.forEach((result) => {
|
||||||
|
@ -1021,6 +1042,8 @@ function Compose({
|
||||||
newStatus = await masto.v1.statuses.create(params);
|
newStatus = await masto.v1.statuses.create(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
states.composerState.minimized = false;
|
||||||
|
states.composerState.publishing = false;
|
||||||
setUIState('default');
|
setUIState('default');
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
|
@ -1031,6 +1054,8 @@ function Compose({
|
||||||
instance,
|
instance,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
states.composerState.publishing = false;
|
||||||
|
states.composerState.publishingError = true;
|
||||||
console.error(e);
|
console.error(e);
|
||||||
alert(e?.reason || e);
|
alert(e?.reason || e);
|
||||||
setUIState('error');
|
setUIState('error');
|
||||||
|
|
|
@ -10,17 +10,56 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: var(--backdrop-color);
|
background-color: var(--backdrop-color);
|
||||||
animation: appear 0.5s var(--timing-function) both;
|
animation: appear 0.5s var(--timing-function) both;
|
||||||
|
transition: all 0.5s var(--timing-function);
|
||||||
|
|
||||||
&.solid {
|
&.solid {
|
||||||
background-color: var(--backdrop-solid-color);
|
background-color: var(--backdrop-solid-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--compose-button-dimension: 56px;
|
||||||
|
--compose-button-dimension-half: calc(var(--compose-button-dimension) / 2);
|
||||||
|
--compose-button-dimension-margin: 16px;
|
||||||
|
|
||||||
|
&.min {
|
||||||
|
/* Minimized */
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
transform: scale(0);
|
||||||
|
--right: max(
|
||||||
|
var(--compose-button-dimension-margin),
|
||||||
|
env(safe-area-inset-right)
|
||||||
|
);
|
||||||
|
--bottom: max(
|
||||||
|
var(--compose-button-dimension-margin),
|
||||||
|
env(safe-area-inset-bottom)
|
||||||
|
);
|
||||||
|
--origin-right: calc(
|
||||||
|
100% - var(--compose-button-dimension-half) - var(--right)
|
||||||
|
);
|
||||||
|
--origin-bottom: calc(
|
||||||
|
100% - var(--compose-button-dimension-half) - var(--bottom)
|
||||||
|
);
|
||||||
|
transform-origin: var(--origin-right) var(--origin-bottom);
|
||||||
|
}
|
||||||
|
|
||||||
.sheet {
|
.sheet {
|
||||||
transition: transform 0.3s var(--timing-function);
|
transition: transform 0.3s var(--timing-function);
|
||||||
transform-origin: center bottom;
|
transform-origin: 80% 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:has(~ div) .sheet {
|
&:has(~ div) .sheet {
|
||||||
transform: scale(0.975);
|
transform: scale(0.975);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: calc(40em - 1px)) {
|
||||||
|
#app[data-shortcuts-view-mode='tab-menu-bar'] ~ #modal-container > div.min {
|
||||||
|
border: 2px solid red;
|
||||||
|
|
||||||
|
--bottom: calc(
|
||||||
|
var(--compose-button-dimension-margin) + env(safe-area-inset-bottom) +
|
||||||
|
52px
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import useCloseWatcher from '../utils/useCloseWatcher';
|
||||||
|
|
||||||
const $modalContainer = document.getElementById('modal-container');
|
const $modalContainer = document.getElementById('modal-container');
|
||||||
|
|
||||||
function Modal({ children, onClose, onClick, class: className }) {
|
function Modal({ children, onClose, onClick, class: className, minimized }) {
|
||||||
if (!children) return null;
|
if (!children) return null;
|
||||||
|
|
||||||
const modalRef = useRef();
|
const modalRef = useRef();
|
||||||
|
@ -43,21 +43,30 @@ function Modal({ children, onClose, onClick, class: className }) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const $deckContainers = document.querySelectorAll('.deck-container');
|
const $deckContainers = document.querySelectorAll('.deck-container');
|
||||||
if (children) {
|
if (minimized) {
|
||||||
$deckContainers.forEach(($deckContainer) => {
|
// Similar to focusDeck in focus-deck.jsx
|
||||||
$deckContainer.setAttribute('inert', '');
|
// Focus last deck
|
||||||
});
|
const page = $deckContainers[$deckContainers.length - 1]; // last one
|
||||||
|
if (page && page.tabIndex === -1) {
|
||||||
|
page.focus();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$deckContainers.forEach(($deckContainer) => {
|
if (children) {
|
||||||
$deckContainer.removeAttribute('inert');
|
$deckContainers.forEach(($deckContainer) => {
|
||||||
});
|
$deckContainer.setAttribute('inert', '');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$deckContainers.forEach(($deckContainer) => {
|
||||||
|
$deckContainer.removeAttribute('inert');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
$deckContainers.forEach(($deckContainer) => {
|
$deckContainers.forEach(($deckContainer) => {
|
||||||
$deckContainer.removeAttribute('inert');
|
$deckContainer.removeAttribute('inert');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}, [children]);
|
}, [children, minimized]);
|
||||||
|
|
||||||
const Modal = (
|
const Modal = (
|
||||||
<div
|
<div
|
||||||
|
@ -72,7 +81,8 @@ function Modal({ children, onClose, onClick, class: className }) {
|
||||||
onClose?.(e);
|
onClose?.(e);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
tabIndex="-1"
|
tabIndex={minimized ? 0 : '-1'}
|
||||||
|
inert={minimized}
|
||||||
onFocus={(e) => {
|
onFocus={(e) => {
|
||||||
try {
|
try {
|
||||||
if (e.target === e.currentTarget) {
|
if (e.target === e.currentTarget) {
|
||||||
|
|
|
@ -39,7 +39,10 @@ export default function Modals() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!!snapStates.showCompose && (
|
{!!snapStates.showCompose && (
|
||||||
<Modal class="solid">
|
<Modal
|
||||||
|
class={`solid ${snapStates.composerState.minimized ? 'min' : ''}`}
|
||||||
|
minimized={!!snapStates.composerState.minimized}
|
||||||
|
>
|
||||||
<IntlSegmenterSuspense>
|
<IntlSegmenterSuspense>
|
||||||
<Compose
|
<Compose
|
||||||
replyToStatus={
|
replyToStatus={
|
||||||
|
|
|
@ -51,6 +51,7 @@ import openCompose from '../utils/open-compose';
|
||||||
import pmem from '../utils/pmem';
|
import pmem from '../utils/pmem';
|
||||||
import safeBoundingBoxPadding from '../utils/safe-bounding-box-padding';
|
import safeBoundingBoxPadding from '../utils/safe-bounding-box-padding';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
|
import showCompose from '../utils/show-compose';
|
||||||
import showToast from '../utils/show-toast';
|
import showToast from '../utils/show-toast';
|
||||||
import { speak, supportsTTS } from '../utils/speech';
|
import { speak, supportsTTS } from '../utils/speech';
|
||||||
import states, { getStatus, saveStatus, statusKey } from '../utils/states';
|
import states, { getStatus, saveStatus, statusKey } from '../utils/states';
|
||||||
|
@ -524,9 +525,9 @@ function Status({
|
||||||
});
|
});
|
||||||
if (newWin) return;
|
if (newWin) return;
|
||||||
}
|
}
|
||||||
states.showCompose = {
|
showCompose({
|
||||||
replyToStatus: status,
|
replyToStatus: status,
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if media has no descriptions
|
// Check if media has no descriptions
|
||||||
|
@ -771,11 +772,11 @@ function Status({
|
||||||
menuExtras={
|
menuExtras={
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
states.showCompose = {
|
showCompose({
|
||||||
draftStatus: {
|
draftStatus: {
|
||||||
status: `\n${url}`,
|
status: `\n${url}`,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="quote" />
|
<Icon icon="quote" />
|
||||||
|
@ -1092,9 +1093,9 @@ function Status({
|
||||||
{supports('@mastodon/post-edit') && (
|
{supports('@mastodon/post-edit') && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
states.showCompose = {
|
showCompose({
|
||||||
editStatus: status,
|
editStatus: status,
|
||||||
};
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="pencil" />
|
<Icon icon="pencil" />
|
||||||
|
@ -2125,11 +2126,11 @@ function Status({
|
||||||
menuExtras={
|
menuExtras={
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
states.showCompose = {
|
showCompose({
|
||||||
draftStatus: {
|
draftStatus: {
|
||||||
status: `\n${url}`,
|
status: `\n${url}`,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon="quote" />
|
<Icon icon="quote" />
|
||||||
|
|
|
@ -388,6 +388,27 @@ select.plain {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
button,
|
||||||
|
.button {
|
||||||
|
margin-inline: calc(-1 * var(--hairline-width));
|
||||||
|
|
||||||
|
&:first-child:not(:only-child) {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
&:not(:first-child, :last-child, :only-child) {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
&:last-child:not(:only-child) {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
tab-size: 2;
|
tab-size: 2;
|
||||||
}
|
}
|
||||||
|
@ -547,3 +568,9 @@ kbd {
|
||||||
.shazam-container-horizontal[hidden] {
|
.shazam-container-horizontal[hidden] {
|
||||||
grid-template-columns: 0fr;
|
grid-template-columns: 0fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,12 +23,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-heading {
|
.hero-heading {
|
||||||
font-size: var(--text-size);
|
font-size: var(--text-size);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
27
src/utils/show-compose.js
Normal file
27
src/utils/show-compose.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import openOSK from './open-osk';
|
||||||
|
import showToast from './show-toast';
|
||||||
|
import states from './states';
|
||||||
|
|
||||||
|
const TOAST_DURATION = 5_000; // 5 seconds
|
||||||
|
|
||||||
|
export default function showCompose(opts) {
|
||||||
|
if (!opts) opts = true;
|
||||||
|
|
||||||
|
if (states.showCompose) {
|
||||||
|
if (states.composerState.minimized) {
|
||||||
|
showToast({
|
||||||
|
duration: TOAST_DURATION,
|
||||||
|
text: `A draft post is currently minimized. Post or discard it before creating a new one.`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showToast({
|
||||||
|
duration: TOAST_DURATION,
|
||||||
|
text: `A post is currently open. Post or discard it before creating a new one.`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openOSK();
|
||||||
|
states.showCompose = opts;
|
||||||
|
}
|
|
@ -40,6 +40,7 @@ const states = proxy({
|
||||||
statusReply: {},
|
statusReply: {},
|
||||||
accounts: {},
|
accounts: {},
|
||||||
routeNotification: null,
|
routeNotification: null,
|
||||||
|
composerState: {},
|
||||||
// Modals
|
// Modals
|
||||||
showCompose: false,
|
showCompose: false,
|
||||||
showSettings: false,
|
showSettings: false,
|
||||||
|
|
Loading…
Reference in a new issue