chore: merge develop
This commit is contained in:
@@ -2,21 +2,22 @@ RAILS_ENV=development
|
||||
PORT=3001
|
||||
WEB_CONCURRENCY=0
|
||||
RAILS_LOG_TO_STDOUT=true
|
||||
|
||||
# Log Level options: "INFO" | "DEBUG" | "INFO" | "WARN" | "ERROR" | "FATAL"
|
||||
RAILS_LOG_LEVEL=INFO
|
||||
|
||||
RAILS_SERVE_STATIC_FILES=true
|
||||
SECRET_KEY_BASE=test
|
||||
BUGSNAG_API_KEY=
|
||||
|
||||
APP_HOST=http://localhost:3001
|
||||
PURCHASE_URL=https://standardnotes.com/purchase
|
||||
PLANS_URL=https://standardnotes.com/plans
|
||||
DASHBOARD_URL=http://standardnotes.com/dashboard
|
||||
|
||||
DEFAULT_SYNC_SERVER=http://localhost:3000
|
||||
WEBSOCKET_URL=wss://sockets-dev.standardnotes.com
|
||||
|
||||
# Development options
|
||||
DEV_DEFAULT_SYNC_SERVER=https://api.standardnotes.com
|
||||
ENABLE_UNFINISHED_FEATURES=false
|
||||
DEV_WEBSOCKET_URL=wss://sockets-dev.standardnotes.com
|
||||
|
||||
# NewRelic (Optional)
|
||||
NEW_RELIC_ENABLED=false
|
||||
|
||||
@@ -2,25 +2,18 @@
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
// eslint-disable-next-line camelcase
|
||||
_bugsnag_api_key?: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
_purchase_url?: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
_plans_url?: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
_dashboard_url?: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
_default_sync_server: string;
|
||||
// eslint-disable-next-line camelcase
|
||||
_enable_unfinished_features: boolean;
|
||||
// eslint-disable-next-line camelcase
|
||||
_websocket_url: string;
|
||||
bugsnagApiKey?: string;
|
||||
dashboardUrl?: string;
|
||||
defaultFilesHost: string;
|
||||
defaultSyncServer: string;
|
||||
devAccountEmail?: string;
|
||||
devAccountPassword?: string;
|
||||
devAccountServer?: string;
|
||||
enabledUnfinishedFeatures: boolean;
|
||||
plansUrl?: string;
|
||||
purchaseUrl?: string;
|
||||
startApplication?: StartApplication;
|
||||
|
||||
_devAccountEmail?: string;
|
||||
_devAccountPassword?: string;
|
||||
_devAccountServer?: string;
|
||||
websocketUrl: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +30,7 @@ import { isDev } from './utils';
|
||||
|
||||
const startApplication: StartApplication = async function startApplication(
|
||||
defaultSyncServerHost: string,
|
||||
defaultFilesHostHost: string,
|
||||
bridge: Bridge,
|
||||
enableUnfinishedFeatures: boolean,
|
||||
webSocketUrl: string
|
||||
@@ -46,6 +40,7 @@ const startApplication: StartApplication = async function startApplication(
|
||||
|
||||
const mainApplicationGroup = new ApplicationGroup(
|
||||
defaultSyncServerHost,
|
||||
defaultFilesHostHost,
|
||||
bridge,
|
||||
enableUnfinishedFeatures ? Runtime.Dev : Runtime.Prod,
|
||||
webSocketUrl
|
||||
@@ -79,10 +74,11 @@ const startApplication: StartApplication = async function startApplication(
|
||||
|
||||
if (IsWebPlatform) {
|
||||
startApplication(
|
||||
window._default_sync_server,
|
||||
window.defaultSyncServer,
|
||||
window.defaultFilesHost,
|
||||
new BrowserBridge(WebAppVersion),
|
||||
window._enable_unfinished_features,
|
||||
window._websocket_url
|
||||
window.enabledUnfinishedFeatures,
|
||||
window.websocketUrl
|
||||
);
|
||||
} else {
|
||||
window.startApplication = startApplication;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { WebApplication } from '@/ui_models/application';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { StateUpdater, useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { AccountMenuPane } from '.';
|
||||
import { Button } from '../Button';
|
||||
import { Checkbox } from '../Checkbox';
|
||||
@@ -17,22 +17,22 @@ type Props = {
|
||||
setMenuPane: (pane: AccountMenuPane) => void;
|
||||
email: string;
|
||||
password: string;
|
||||
setPassword: StateUpdater<string>;
|
||||
};
|
||||
|
||||
export const ConfirmPassword: FunctionComponent<Props> = observer(
|
||||
({ application, appState, setMenuPane, email, password, setPassword }) => {
|
||||
({ application, appState, setMenuPane, email, password }) => {
|
||||
const { notesAndTagsCount } = appState.accountMenu;
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [isRegistering, setIsRegistering] = useState(false);
|
||||
const [isEphemeral, setIsEphemeral] = useState(false);
|
||||
const [shouldMergeLocal, setShouldMergeLocal] = useState(true);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const passwordInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
passwordInputRef?.current?.focus();
|
||||
passwordInputRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
const handlePasswordChange = (e: Event) => {
|
||||
@@ -50,6 +50,9 @@ export const ConfirmPassword: FunctionComponent<Props> = observer(
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (error.length) {
|
||||
setError('');
|
||||
}
|
||||
if (e.key === 'Enter') {
|
||||
handleConfirmFormSubmit(e);
|
||||
}
|
||||
@@ -59,7 +62,7 @@ export const ConfirmPassword: FunctionComponent<Props> = observer(
|
||||
e.preventDefault();
|
||||
|
||||
if (!password) {
|
||||
passwordInputRef?.current!.focus();
|
||||
passwordInputRef.current?.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -76,21 +79,15 @@ export const ConfirmPassword: FunctionComponent<Props> = observer(
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
application.alertService.alert(err).finally(() => {
|
||||
setPassword('');
|
||||
handleGoBack();
|
||||
});
|
||||
setError(err.message);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsRegistering(false);
|
||||
});
|
||||
} else {
|
||||
application.alertService
|
||||
.alert(STRING_NON_MATCHING_PASSWORDS)
|
||||
.finally(() => {
|
||||
setConfirmPassword('');
|
||||
passwordInputRef?.current!.focus();
|
||||
});
|
||||
setError(STRING_NON_MATCHING_PASSWORDS);
|
||||
setConfirmPassword('');
|
||||
passwordInputRef.current?.focus();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,6 +135,7 @@ export const ConfirmPassword: FunctionComponent<Props> = observer(
|
||||
ref={passwordInputRef}
|
||||
disabled={isRegistering}
|
||||
/>
|
||||
{error ? <div className="color-dark-red my-2">{error}</div> : null}
|
||||
<Button
|
||||
className="btn-w-full mt-1 mb-3"
|
||||
label={
|
||||
|
||||
@@ -36,7 +36,7 @@ export const CreateAccount: FunctionComponent<Props> = observer(
|
||||
|
||||
useEffect(() => {
|
||||
if (emailInputRef.current) {
|
||||
emailInputRef.current!.focus();
|
||||
emailInputRef.current?.focus();
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -62,12 +62,12 @@ export const CreateAccount: FunctionComponent<Props> = observer(
|
||||
e.preventDefault();
|
||||
|
||||
if (!email || email.length === 0) {
|
||||
emailInputRef?.current!.focus();
|
||||
emailInputRef.current?.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password || password.length === 0) {
|
||||
passwordInputRef?.current!.focus();
|
||||
passwordInputRef.current?.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
const { notesAndTagsCount } = appState.accountMenu;
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [isInvalid, setIsInvalid] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [isEphemeral, setIsEphemeral] = useState(false);
|
||||
const [isStrictSignin, setIsStrictSignin] = useState(false);
|
||||
const [isSigningIn, setIsSigningIn] = useState(false);
|
||||
@@ -37,15 +37,15 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
if (emailInputRef?.current) {
|
||||
emailInputRef.current?.focus();
|
||||
}
|
||||
if (isDev && window._devAccountEmail) {
|
||||
setEmail(window._devAccountEmail);
|
||||
setPassword(window._devAccountPassword as string);
|
||||
if (isDev && window.devAccountEmail) {
|
||||
setEmail(window.devAccountEmail);
|
||||
setPassword(window.devAccountPassword as string);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const resetInvalid = () => {
|
||||
if (isInvalid) {
|
||||
setIsInvalid(false);
|
||||
if (error.length) {
|
||||
setError('');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -56,8 +56,8 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
};
|
||||
|
||||
const handlePasswordChange = (e: Event) => {
|
||||
if (isInvalid) {
|
||||
setIsInvalid(false);
|
||||
if (error.length) {
|
||||
setError('');
|
||||
}
|
||||
if (e.target instanceof HTMLInputElement) {
|
||||
setPassword(e.target.value);
|
||||
@@ -91,11 +91,7 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
if (err.toString().includes('Invalid email or password')) {
|
||||
setIsInvalid(true);
|
||||
} else {
|
||||
application.alertService.alert(err);
|
||||
}
|
||||
setError(err.message ?? err.toString());
|
||||
setPassword('');
|
||||
passwordInputRef?.current?.blur();
|
||||
})
|
||||
@@ -141,7 +137,7 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
</div>
|
||||
<div className="px-3 mb-1">
|
||||
<InputWithIcon
|
||||
className={`mb-2 ${isInvalid ? 'border-dark-red' : null}`}
|
||||
className={`mb-2 ${error ? 'border-dark-red' : null}`}
|
||||
icon="email"
|
||||
inputType="email"
|
||||
placeholder="Email"
|
||||
@@ -153,7 +149,7 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
ref={emailInputRef}
|
||||
/>
|
||||
<InputWithIcon
|
||||
className={`mb-2 ${isInvalid ? 'border-dark-red' : null}`}
|
||||
className={`mb-2 ${error ? 'border-dark-red' : null}`}
|
||||
icon="password"
|
||||
inputType={showPassword ? 'text' : 'password'}
|
||||
placeholder="Password"
|
||||
@@ -171,11 +167,7 @@ export const SignInPane: FunctionComponent<Props> = observer(
|
||||
}}
|
||||
ref={passwordInputRef}
|
||||
/>
|
||||
{isInvalid ? (
|
||||
<div className="color-dark-red my-2">
|
||||
Invalid email or password.
|
||||
</div>
|
||||
) : null}
|
||||
{error ? <div className="color-dark-red my-2">{error}</div> : null}
|
||||
<Button
|
||||
className="btn-w-full mt-1 mb-3"
|
||||
label={isSigningIn ? 'Signing in...' : 'Sign in'}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { User } from '@standardnotes/snjs/dist/@types/services/api/responses';
|
||||
import { User as UserType } from '@standardnotes/responses';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
application: WebApplication;
|
||||
}
|
||||
};
|
||||
|
||||
const User = observer(({
|
||||
appState,
|
||||
application,
|
||||
}: Props) => {
|
||||
const User = observer(({ appState, application }: Props) => {
|
||||
const { server } = appState.accountMenu;
|
||||
const user = application.getUser();
|
||||
const user = application.getUser() as UserType;
|
||||
|
||||
return (
|
||||
<div className="sk-panel-section">
|
||||
@@ -21,8 +18,8 @@ const User = observer(({
|
||||
<div className="sk-notification danger">
|
||||
<div className="sk-notification-title">Sync Unreachable</div>
|
||||
<div className="sk-notification-text">
|
||||
Hmm...we can't seem to sync your account.
|
||||
The reason: {appState.sync.errorMessage}
|
||||
Hmm...we can't seem to sync your account. The reason:{' '}
|
||||
{appState.sync.errorMessage}
|
||||
</div>
|
||||
<a
|
||||
className="sk-a info-contrast sk-bold sk-panel-row"
|
||||
@@ -36,12 +33,8 @@ const User = observer(({
|
||||
)}
|
||||
<div className="sk-panel-row">
|
||||
<div className="sk-panel-column">
|
||||
<div className="sk-h1 sk-bold wrap">
|
||||
{(user as User).email}
|
||||
</div>
|
||||
<div className="sk-subtitle neutral">
|
||||
{server}
|
||||
</div>
|
||||
<div className="sk-h1 sk-bold wrap">{user.email}</div>
|
||||
<div className="sk-subtitle neutral">{server}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sk-panel-row" />
|
||||
|
||||
@@ -74,7 +74,6 @@ const MenuPaneSelector: FunctionComponent<PaneSelectorProps> = observer(
|
||||
setMenuPane={setMenuPane}
|
||||
email={email}
|
||||
password={password}
|
||||
setPassword={setPassword}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import {
|
||||
Action,
|
||||
SNActionsExtension,
|
||||
UuidString,
|
||||
SNNote,
|
||||
ListedAccount,
|
||||
} from '@standardnotes/snjs';
|
||||
import { ActionResponse } from '@standardnotes/snjs';
|
||||
import { render } from 'preact';
|
||||
import { PureComponent } from './Abstract/PureComponent';
|
||||
import { MenuRow } from './MenuRow';
|
||||
import { RevisionPreviewModal } from './RevisionPreviewModal';
|
||||
|
||||
type ActionRow = Action & {
|
||||
running?: boolean;
|
||||
spinnerClass?: string;
|
||||
subtitle?: string;
|
||||
};
|
||||
|
||||
type MenuSection = {
|
||||
uuid: UuidString;
|
||||
name: string;
|
||||
loading?: boolean;
|
||||
error?: boolean;
|
||||
hidden?: boolean;
|
||||
deprecation?: string;
|
||||
extension?: SNActionsExtension;
|
||||
rows?: ActionRow[];
|
||||
listedAccount?: ListedAccount;
|
||||
};
|
||||
|
||||
type State = {
|
||||
menuSections: MenuSection[];
|
||||
selectedActionIdentifier?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
application: WebApplication;
|
||||
note: SNNote;
|
||||
};
|
||||
|
||||
export class ActionsMenu extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props, props.application);
|
||||
|
||||
this.state = {
|
||||
menuSections: [],
|
||||
};
|
||||
|
||||
this.loadExtensions();
|
||||
}
|
||||
|
||||
private async loadExtensions(): Promise<void> {
|
||||
const unresolvedListedSections =
|
||||
await this.getNonresolvedListedMenuSections();
|
||||
const unresolvedGenericSections =
|
||||
await this.getNonresolvedGenericMenuSections();
|
||||
this.setState(
|
||||
{
|
||||
menuSections: unresolvedListedSections.concat(
|
||||
unresolvedGenericSections
|
||||
),
|
||||
},
|
||||
() => {
|
||||
this.state.menuSections.forEach((menuSection) => {
|
||||
this.resolveMenuSection(menuSection);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private async getNonresolvedGenericMenuSections(): Promise<MenuSection[]> {
|
||||
const genericExtensions = this.props.application.actionsManager
|
||||
.getExtensions()
|
||||
.sort((a, b) => {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
|
||||
return genericExtensions.map((extension) => {
|
||||
const menuSection: MenuSection = {
|
||||
uuid: extension.uuid,
|
||||
name: extension.name,
|
||||
extension: extension,
|
||||
loading: true,
|
||||
hidden: this.appState.actionsMenu.hiddenSections[extension.uuid],
|
||||
};
|
||||
return menuSection;
|
||||
});
|
||||
}
|
||||
|
||||
private async getNonresolvedListedMenuSections(): Promise<MenuSection[]> {
|
||||
const listedAccountEntries =
|
||||
await this.props.application.getListedAccounts();
|
||||
return listedAccountEntries.map((entry) => {
|
||||
const menuSection: MenuSection = {
|
||||
uuid: entry.authorId,
|
||||
name: `Listed ${entry.authorId}`,
|
||||
loading: true,
|
||||
listedAccount: entry,
|
||||
hidden: this.appState.actionsMenu.hiddenSections[entry.authorId],
|
||||
};
|
||||
return menuSection;
|
||||
});
|
||||
}
|
||||
|
||||
private resolveMenuSection(menuSection: MenuSection): void {
|
||||
if (menuSection.listedAccount) {
|
||||
this.props.application
|
||||
.getListedAccountInfo(menuSection.listedAccount, this.props.note.uuid)
|
||||
.then((accountInfo) => {
|
||||
if (!accountInfo) {
|
||||
this.promoteMenuSection({
|
||||
...menuSection,
|
||||
loading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const existingMenuSection = this.state.menuSections.find(
|
||||
(item) => item.uuid === menuSection.listedAccount?.authorId
|
||||
) as MenuSection;
|
||||
const resolvedMenuSection: MenuSection = {
|
||||
...existingMenuSection,
|
||||
loading: false,
|
||||
error: false,
|
||||
name: accountInfo.display_name,
|
||||
rows: accountInfo?.actions,
|
||||
};
|
||||
this.promoteMenuSection(resolvedMenuSection);
|
||||
});
|
||||
} else if (menuSection.extension) {
|
||||
this.props.application.actionsManager
|
||||
.loadExtensionInContextOfItem(menuSection.extension, this.props.note)
|
||||
.then((resolvedExtension) => {
|
||||
if (!resolvedExtension) {
|
||||
this.promoteMenuSection({
|
||||
...menuSection,
|
||||
loading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const actions = resolvedExtension.actionsWithContextForItem(
|
||||
this.props.note
|
||||
);
|
||||
|
||||
const resolvedMenuSection: MenuSection = {
|
||||
...menuSection,
|
||||
rows: actions,
|
||||
deprecation: resolvedExtension.deprecation,
|
||||
loading: false,
|
||||
error: false,
|
||||
};
|
||||
this.promoteMenuSection(resolvedMenuSection);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private promoteMenuSection(newItem: MenuSection): void {
|
||||
const menuSections = this.state.menuSections.map((menuSection) => {
|
||||
if (menuSection.uuid === newItem.uuid) {
|
||||
return newItem;
|
||||
} else {
|
||||
return menuSection;
|
||||
}
|
||||
});
|
||||
this.setState({ menuSections });
|
||||
}
|
||||
|
||||
private promoteAction(newAction: Action, section: MenuSection): void {
|
||||
const newSection: MenuSection = {
|
||||
...section,
|
||||
rows: section.rows?.map((action) => {
|
||||
if (action.url === newAction.url) {
|
||||
return newAction;
|
||||
} else {
|
||||
return action;
|
||||
}
|
||||
}),
|
||||
};
|
||||
this.promoteMenuSection(newSection);
|
||||
}
|
||||
|
||||
private idForAction(action: Action) {
|
||||
return `${action.label}:${action.verb}:${action.desc}`;
|
||||
}
|
||||
|
||||
executeAction = async (action: Action, section: MenuSection) => {
|
||||
const isLegacyNoteHistoryExt = action.verb === 'nested';
|
||||
if (isLegacyNoteHistoryExt) {
|
||||
const showRevisionAction = action.subactions![0];
|
||||
action = showRevisionAction;
|
||||
}
|
||||
|
||||
this.promoteAction(
|
||||
{
|
||||
...action,
|
||||
running: true,
|
||||
},
|
||||
section
|
||||
);
|
||||
|
||||
const response = await this.props.application.actionsManager.runAction(
|
||||
action,
|
||||
this.props.note
|
||||
);
|
||||
|
||||
this.promoteAction(
|
||||
{
|
||||
...action,
|
||||
running: false,
|
||||
},
|
||||
section
|
||||
);
|
||||
|
||||
if (!response || response.error) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleActionResponse(action, response);
|
||||
this.resolveMenuSection(section);
|
||||
};
|
||||
|
||||
handleActionResponse(action: Action, result: ActionResponse) {
|
||||
switch (action.verb) {
|
||||
case 'render': {
|
||||
const item = result.item;
|
||||
render(
|
||||
<RevisionPreviewModal
|
||||
application={this.application}
|
||||
uuid={item.uuid}
|
||||
content={item.content}
|
||||
/>,
|
||||
document.body.appendChild(document.createElement('div'))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public toggleSectionVisibility(menuSection: MenuSection) {
|
||||
this.appState.actionsMenu.toggleSectionVisibility(menuSection.uuid);
|
||||
this.promoteMenuSection({
|
||||
...menuSection,
|
||||
hidden: !menuSection.hidden,
|
||||
});
|
||||
}
|
||||
|
||||
renderMenuSection(section: MenuSection) {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
key={section.uuid}
|
||||
className="sk-menu-panel-header"
|
||||
onClick={($event) => {
|
||||
this.toggleSectionVisibility(section);
|
||||
$event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<div className="sk-menu-panel-column">
|
||||
<div className="sk-menu-panel-header-title">{section.name}</div>
|
||||
{section.hidden && <div>…</div>}
|
||||
{section.deprecation && !section.hidden && (
|
||||
<div className="sk-menu-panel-header-subtitle">
|
||||
{section.deprecation}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{section.loading && <div className="sk-spinner small loading" />}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{section.error && !section.hidden && (
|
||||
<MenuRow
|
||||
faded={true}
|
||||
label="Error loading actions"
|
||||
subtitle="Please try again later."
|
||||
/>
|
||||
)}
|
||||
|
||||
{!section.rows?.length && !section.hidden && (
|
||||
<MenuRow faded={true} label="No Actions Available" />
|
||||
)}
|
||||
|
||||
{!section.hidden &&
|
||||
!section.loading &&
|
||||
!section.error &&
|
||||
section.rows?.map((action, index) => {
|
||||
return (
|
||||
<MenuRow
|
||||
key={index}
|
||||
action={() => {
|
||||
this.executeAction(action, section);
|
||||
}}
|
||||
label={action.label}
|
||||
disabled={action.running}
|
||||
spinnerClass={action.running ? 'info' : undefined}
|
||||
subtitle={action.desc}
|
||||
>
|
||||
{action.access_type && (
|
||||
<div className="sk-sublabel">
|
||||
{'Uses '}
|
||||
<strong>{action.access_type}</strong>
|
||||
{' access to this note.'}
|
||||
</div>
|
||||
)}
|
||||
</MenuRow>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="sn-component">
|
||||
<div className="sk-menu-panel dropdown-menu">
|
||||
{this.state.menuSections.length == 0 && (
|
||||
<MenuRow label="No Actions" />
|
||||
)}
|
||||
{this.state.menuSections.map((extension) =>
|
||||
this.renderMenuSection(extension)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import { RevisionHistoryModalWrapper } from './RevisionHistoryModal/RevisionHist
|
||||
import { PremiumModalProvider } from './Premium';
|
||||
import { ConfirmSignoutContainer } from './ConfirmSignoutModal';
|
||||
import { TagsContextMenu } from './Tags/TagContextMenu';
|
||||
import { ToastContainer } from '@standardnotes/stylekit';
|
||||
|
||||
type Props = {
|
||||
application: WebApplication;
|
||||
@@ -207,7 +208,10 @@ export class ApplicationView extends PureComponent<Props, State> {
|
||||
const renderAppContents = !this.state.needsUnlock && this.state.launched;
|
||||
|
||||
return (
|
||||
<PremiumModalProvider state={this.appState?.features}>
|
||||
<PremiumModalProvider
|
||||
application={this.application}
|
||||
appState={this.appState}
|
||||
>
|
||||
<div className={this.platformString + ' main-ui-view sn-component'}>
|
||||
{renderAppContents && (
|
||||
<div
|
||||
@@ -280,6 +284,8 @@ export class ApplicationView extends PureComponent<Props, State> {
|
||||
appState={this.appState}
|
||||
application={this.application}
|
||||
/>
|
||||
|
||||
<ToastContainer />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -130,6 +130,9 @@ export const ChangeEditorButton: FunctionComponent<Props> = observer(
|
||||
setSelectedEditor={setCurrentEditor}
|
||||
note={note}
|
||||
groups={editorMenuGroups}
|
||||
closeMenu={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</DisclosurePanel>
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
EyeIcon,
|
||||
EyeOffIcon,
|
||||
HashtagIcon,
|
||||
HashtagOffIcon,
|
||||
HelpIcon,
|
||||
HistoryIcon,
|
||||
InfoIcon,
|
||||
@@ -38,7 +39,7 @@ import {
|
||||
MarkdownIcon,
|
||||
MenuArrowDownAlt,
|
||||
MenuArrowDownIcon,
|
||||
MenuArrowRight,
|
||||
MenuArrowRightIcon,
|
||||
MenuCloseIcon,
|
||||
MoreIcon,
|
||||
NotesIcon,
|
||||
@@ -85,15 +86,16 @@ const ICONS = {
|
||||
'chevron-right': ChevronRightIcon,
|
||||
'cloud-off': CloudOffIcon,
|
||||
'eye-off': EyeOffIcon,
|
||||
'hashtag-off': HashtagOffIcon,
|
||||
'link-off': LinkOffIcon,
|
||||
'list-bulleted': ListBulleted,
|
||||
'lock-filled': LockFilledIcon,
|
||||
'menu-arrow-down-alt': MenuArrowDownAlt,
|
||||
'menu-arrow-down': MenuArrowDownIcon,
|
||||
'menu-arrow-right': MenuArrowRight,
|
||||
'menu-arrow-right': MenuArrowRightIcon,
|
||||
'menu-close': MenuCloseIcon,
|
||||
'pencil-off': PencilOffIcon,
|
||||
'pencil-filled': PencilFilledIcon,
|
||||
'pencil-off': PencilOffIcon,
|
||||
'pin-filled': PinFilledIcon,
|
||||
'plain-text': PlainTextIcon,
|
||||
'premium-feature': PremiumFeatureIcon,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SmartTagsSection } from '@/components/Tags/SmartTagsSection';
|
||||
import { SmartViewsSection } from '@/components/Tags/SmartViewsSection';
|
||||
import { TagsSection } from '@/components/Tags/TagsSection';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { PANEL_NAME_NAVIGATION } from '@/constants';
|
||||
@@ -65,7 +65,7 @@ export const Navigation: FunctionComponent<Props> = observer(
|
||||
</div>
|
||||
</div>
|
||||
<div className="scrollable">
|
||||
<SmartTagsSection appState={appState} />
|
||||
<SmartViewsSection appState={appState} />
|
||||
<TagsSection appState={appState} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,6 @@ import { Icon } from '../Icon';
|
||||
import { PinNoteButton } from '../PinNoteButton';
|
||||
import { NotesOptionsPanel } from '../NotesOptionsPanel';
|
||||
import { NoteTagsContainer } from '../NoteTagsContainer';
|
||||
import { ActionsMenu } from '../ActionsMenu';
|
||||
import { ComponentView } from '../ComponentView';
|
||||
import { PanelSide, PanelResizer, PanelResizeType } from '../PanelResizer';
|
||||
import { ElementIds } from '@/element_ids';
|
||||
@@ -107,7 +106,6 @@ type State = {
|
||||
noteLocked: boolean;
|
||||
noteStatus?: NoteStatus;
|
||||
saveError?: any;
|
||||
showActionsMenu: boolean;
|
||||
showLockedIcon: boolean;
|
||||
showProtectedWarning: boolean;
|
||||
spellcheck: boolean;
|
||||
@@ -173,7 +171,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
lockText: 'Note Editing Disabled',
|
||||
noteStatus: undefined,
|
||||
noteLocked: this.controller.note.locked,
|
||||
showActionsMenu: false,
|
||||
showLockedIcon: true,
|
||||
showProtectedWarning: false,
|
||||
spellcheck: true,
|
||||
@@ -319,7 +316,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
async onAppLaunch() {
|
||||
await super.onAppLaunch();
|
||||
this.streamItems();
|
||||
this.registerComponentManagerEventObserver();
|
||||
}
|
||||
|
||||
/** @override */
|
||||
@@ -505,32 +501,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
setMenuState(menu: string, state: boolean) {
|
||||
this.setState({
|
||||
[menu]: state,
|
||||
});
|
||||
this.closeAllMenus(menu);
|
||||
}
|
||||
|
||||
toggleMenu = (menu: keyof State) => {
|
||||
this.setMenuState(menu, !this.state[menu]);
|
||||
this.application.getAppState().notes.setContextMenuOpen(false);
|
||||
};
|
||||
|
||||
closeAllMenus = (exclude?: string) => {
|
||||
if (!this.state.showActionsMenu) {
|
||||
return;
|
||||
}
|
||||
const allMenus = ['showActionsMenu'];
|
||||
const menuState: any = {};
|
||||
for (const candidate of allMenus) {
|
||||
if (candidate !== exclude) {
|
||||
menuState[candidate] = false;
|
||||
}
|
||||
}
|
||||
this.setState(menuState);
|
||||
};
|
||||
|
||||
hasAvailableExtensions() {
|
||||
return (
|
||||
this.application.actionsManager.extensionsInContextOfItem(this.note)
|
||||
@@ -646,10 +616,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
document.getElementById(ElementIds.NoteTitleEditor)?.focus();
|
||||
}
|
||||
|
||||
clickedTextArea = () => {
|
||||
this.closeAllMenus();
|
||||
};
|
||||
|
||||
onContentFocus = () => {
|
||||
this.application
|
||||
.getAppState()
|
||||
@@ -772,18 +738,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
|
||||
/** @components */
|
||||
|
||||
registerComponentManagerEventObserver() {
|
||||
this.removeComponentManagerObserver =
|
||||
this.application.componentManager.addEventObserver((eventName, data) => {
|
||||
if (eventName === ComponentManagerEvent.ViewerDidFocus) {
|
||||
const viewer = data?.componentViewer;
|
||||
if (viewer?.component.isEditor) {
|
||||
this.closeAllMenus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async reloadStackComponents() {
|
||||
const stackComponents = sortAlphabetically(
|
||||
this.application.componentManager
|
||||
@@ -1103,30 +1057,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{this.note && (
|
||||
<div className="sn-component">
|
||||
<div id="editor-menu-bar" className="sk-app-bar no-edges">
|
||||
<div className="left">
|
||||
<div
|
||||
className={
|
||||
(this.state.showActionsMenu ? 'selected' : '') +
|
||||
' sk-app-bar-item'
|
||||
}
|
||||
onClick={() => this.toggleMenu('showActionsMenu')}
|
||||
>
|
||||
<div className="sk-label">Actions</div>
|
||||
{this.state.showActionsMenu && (
|
||||
<ActionsMenu
|
||||
note={this.note}
|
||||
application={this.application}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!this.note.errorDecrypting && (
|
||||
<div
|
||||
id={ElementIds.EditorContent}
|
||||
@@ -1171,7 +1101,6 @@ export class NoteView extends PureComponent<Props, State> {
|
||||
onChange={this.onTextAreaChange}
|
||||
value={this.state.editorText}
|
||||
readonly={this.state.noteLocked}
|
||||
onClick={this.clickedTextArea}
|
||||
onFocus={this.onContentFocus}
|
||||
spellcheck={this.state.spellcheck}
|
||||
ref={(ref) => this.onSystemEditorLoad(ref)}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { WebApplication } from '@/ui_models/application';
|
||||
import { KeyboardKey } from '@/services/ioService';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { DisplayOptions } from '@/ui_models/app_state/notes_view_state';
|
||||
import { SNNote } from '@standardnotes/snjs';
|
||||
import { SNNote, SNTag } from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { NotesListItem } from './NotesListItem';
|
||||
@@ -42,7 +42,7 @@ export const NotesList: FunctionComponent<Props> = observer(
|
||||
return [];
|
||||
}
|
||||
const tags = appState.getNoteTags(note);
|
||||
if (!selectedTag.isSmartTag && tags.length === 1) {
|
||||
if (selectedTag instanceof SNTag && tags.length === 1) {
|
||||
return [];
|
||||
}
|
||||
return tags.map((tag) => tag.title).sort();
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { KeyboardKey } from '@/services/ioService';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import {
|
||||
MENU_MARGIN_FROM_APP_BORDER,
|
||||
MAX_MENU_SIZE_MULTIPLIER,
|
||||
} from '@/constants';
|
||||
import {
|
||||
Disclosure,
|
||||
DisclosureButton,
|
||||
@@ -21,6 +17,10 @@ import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { Icon } from '../Icon';
|
||||
import { createEditorMenuGroups } from './changeEditor/createEditorMenuGroups';
|
||||
import { ChangeEditorMenu } from './changeEditor/ChangeEditorMenu';
|
||||
import {
|
||||
calculateSubmenuStyle,
|
||||
SubmenuStyle,
|
||||
} from '@/utils/calculateSubmenuStyle';
|
||||
|
||||
type ChangeEditorOptionProps = {
|
||||
appState: AppState;
|
||||
@@ -44,92 +44,6 @@ export type EditorMenuItem = {
|
||||
|
||||
export type EditorMenuGroup = AccordionMenuGroup<EditorMenuItem>;
|
||||
|
||||
type MenuPositionStyle = {
|
||||
top?: number | 'auto';
|
||||
right?: number | 'auto';
|
||||
bottom: number | 'auto';
|
||||
left?: number | 'auto';
|
||||
visibility?: 'hidden' | 'visible';
|
||||
};
|
||||
|
||||
const calculateMenuPosition = (
|
||||
button: HTMLButtonElement | null,
|
||||
menu?: HTMLDivElement | null
|
||||
): MenuPositionStyle | undefined => {
|
||||
const defaultFontSize = window.getComputedStyle(
|
||||
document.documentElement
|
||||
).fontSize;
|
||||
|
||||
const maxChangeEditorMenuSize =
|
||||
parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER;
|
||||
|
||||
const { clientWidth, clientHeight } = document.documentElement;
|
||||
|
||||
const buttonRect = button?.getBoundingClientRect();
|
||||
|
||||
const buttonParentRect = button?.parentElement?.getBoundingClientRect();
|
||||
|
||||
const menuBoundingRect = menu?.getBoundingClientRect();
|
||||
|
||||
const footerElementRect = document
|
||||
.getElementById('footer-bar')
|
||||
?.getBoundingClientRect();
|
||||
|
||||
const footerHeightInPx = footerElementRect?.height ?? 0;
|
||||
|
||||
let position: MenuPositionStyle = {
|
||||
bottom: 'auto',
|
||||
};
|
||||
|
||||
if (buttonRect && buttonParentRect) {
|
||||
let positionBottom =
|
||||
clientHeight - buttonRect.bottom - buttonRect.height / 2;
|
||||
|
||||
if (positionBottom < footerHeightInPx) {
|
||||
positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER;
|
||||
}
|
||||
|
||||
if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) {
|
||||
position = {
|
||||
bottom: positionBottom,
|
||||
right: clientWidth - buttonRect.left,
|
||||
visibility: 'hidden',
|
||||
};
|
||||
} else {
|
||||
position = {
|
||||
bottom: positionBottom,
|
||||
left: buttonRect.right,
|
||||
visibility: 'hidden',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (menuBoundingRect && menuBoundingRect.height && buttonRect) {
|
||||
if (menuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) {
|
||||
if (
|
||||
buttonRect.right + maxChangeEditorMenuSize >
|
||||
document.documentElement.clientWidth
|
||||
) {
|
||||
return {
|
||||
...position,
|
||||
top: MENU_MARGIN_FROM_APP_BORDER + buttonRect.top - buttonRect.height,
|
||||
bottom: 'auto',
|
||||
visibility: 'visible',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...position,
|
||||
top: MENU_MARGIN_FROM_APP_BORDER,
|
||||
bottom: 'auto',
|
||||
visibility: 'visible',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
};
|
||||
|
||||
export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
application,
|
||||
closeOnBlur,
|
||||
@@ -137,14 +51,11 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
}) => {
|
||||
const [changeEditorMenuOpen, setChangeEditorMenuOpen] = useState(false);
|
||||
const [changeEditorMenuVisible, setChangeEditorMenuVisible] = useState(false);
|
||||
const [changeEditorMenuMaxHeight, setChangeEditorMenuMaxHeight] = useState<
|
||||
number | 'auto'
|
||||
>('auto');
|
||||
const [changeEditorMenuPosition, setChangeEditorMenuPosition] =
|
||||
useState<MenuPositionStyle>({
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
});
|
||||
const [menuStyle, setMenuStyle] = useState<SubmenuStyle>({
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
maxHeight: 'auto',
|
||||
});
|
||||
const changeEditorMenuRef = useRef<HTMLDivElement>(null);
|
||||
const changeEditorButtonRef = useRef<HTMLButtonElement>(null);
|
||||
const [editors] = useState<SNComponent[]>(() =>
|
||||
@@ -171,9 +82,9 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
|
||||
const toggleChangeEditorMenu = () => {
|
||||
if (!changeEditorMenuOpen) {
|
||||
const menuPosition = calculateMenuPosition(changeEditorButtonRef.current);
|
||||
if (menuPosition) {
|
||||
setChangeEditorMenuPosition(menuPosition);
|
||||
const menuStyle = calculateSubmenuStyle(changeEditorButtonRef.current);
|
||||
if (menuStyle) {
|
||||
setMenuStyle(menuStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,32 +94,13 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
useEffect(() => {
|
||||
if (changeEditorMenuOpen) {
|
||||
setTimeout(() => {
|
||||
const newMenuPosition = calculateMenuPosition(
|
||||
const newMenuStyle = calculateSubmenuStyle(
|
||||
changeEditorButtonRef.current,
|
||||
changeEditorMenuRef.current
|
||||
);
|
||||
|
||||
if (newMenuPosition) {
|
||||
const { clientHeight } = document.documentElement;
|
||||
const footerElementRect = document
|
||||
.getElementById('footer-bar')
|
||||
?.getBoundingClientRect();
|
||||
const footerHeightInPx = footerElementRect?.height;
|
||||
|
||||
if (
|
||||
footerHeightInPx &&
|
||||
newMenuPosition.top &&
|
||||
newMenuPosition.top !== 'auto'
|
||||
) {
|
||||
setChangeEditorMenuMaxHeight(
|
||||
clientHeight -
|
||||
newMenuPosition.top -
|
||||
footerHeightInPx -
|
||||
MENU_MARGIN_FROM_APP_BORDER
|
||||
);
|
||||
}
|
||||
|
||||
setChangeEditorMenuPosition(newMenuPosition);
|
||||
if (newMenuStyle) {
|
||||
setMenuStyle(newMenuStyle);
|
||||
setChangeEditorMenuVisible(true);
|
||||
}
|
||||
});
|
||||
@@ -242,8 +134,7 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
...changeEditorMenuPosition,
|
||||
maxHeight: changeEditorMenuMaxHeight,
|
||||
...menuStyle,
|
||||
position: 'fixed',
|
||||
}}
|
||||
className="sn-dropdown flex flex-col max-h-120 min-w-68 fixed overflow-y-auto"
|
||||
@@ -257,6 +148,9 @@ export const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({
|
||||
note={note}
|
||||
groups={editorMenuGroups}
|
||||
isOpen={changeEditorMenuVisible}
|
||||
closeMenu={() => {
|
||||
setChangeEditorMenuOpen(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</DisclosurePanel>
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import {
|
||||
calculateSubmenuStyle,
|
||||
SubmenuStyle,
|
||||
} from '@/utils/calculateSubmenuStyle';
|
||||
import {
|
||||
Disclosure,
|
||||
DisclosureButton,
|
||||
DisclosurePanel,
|
||||
} from '@reach/disclosure';
|
||||
import { Action, ListedAccount, SNNote } from '@standardnotes/snjs';
|
||||
import { Fragment, FunctionComponent } from 'preact';
|
||||
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
type Props = {
|
||||
application: WebApplication;
|
||||
note: SNNote;
|
||||
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void;
|
||||
};
|
||||
|
||||
type ListedMenuGroup = {
|
||||
name: string;
|
||||
account: ListedAccount;
|
||||
actions: Action[];
|
||||
};
|
||||
|
||||
type ListedMenuItemProps = {
|
||||
action: Action;
|
||||
note: SNNote;
|
||||
group: ListedMenuGroup;
|
||||
application: WebApplication;
|
||||
reloadMenuGroup: (group: ListedMenuGroup) => Promise<void>;
|
||||
};
|
||||
|
||||
const ListedMenuItem: FunctionComponent<ListedMenuItemProps> = ({
|
||||
action,
|
||||
note,
|
||||
application,
|
||||
group,
|
||||
reloadMenuGroup,
|
||||
}) => {
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
|
||||
const handleClick = async () => {
|
||||
if (isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsRunning(true);
|
||||
|
||||
await application.actionsManager.runAction(action, note);
|
||||
|
||||
setIsRunning(false);
|
||||
|
||||
reloadMenuGroup(group);
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
key={action.url}
|
||||
onClick={handleClick}
|
||||
className="sn-dropdown-item flex justify-between py-2 text-input focus:bg-info-backdrop focus:shadow-none"
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<div className="font-semibold">{action.label}</div>
|
||||
{action.access_type && (
|
||||
<div className="text-xs mt-0.5 color-grey-0">
|
||||
{'Uses '}
|
||||
<strong>{action.access_type}</strong>
|
||||
{' access to this note.'}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{isRunning && <div className="sk-spinner spinner-info w-3 h-3" />}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
type ListedActionsMenuProps = {
|
||||
application: WebApplication;
|
||||
note: SNNote;
|
||||
recalculateMenuStyle: () => void;
|
||||
};
|
||||
|
||||
const ListedActionsMenu: FunctionComponent<ListedActionsMenuProps> = ({
|
||||
application,
|
||||
note,
|
||||
recalculateMenuStyle,
|
||||
}) => {
|
||||
const [menuGroups, setMenuGroups] = useState<ListedMenuGroup[]>([]);
|
||||
const [isFetchingAccounts, setIsFetchingAccounts] = useState(true);
|
||||
|
||||
const reloadMenuGroup = async (group: ListedMenuGroup) => {
|
||||
const updatedAccountInfo = await application.getListedAccountInfo(
|
||||
group.account,
|
||||
note.uuid
|
||||
);
|
||||
|
||||
if (!updatedAccountInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedGroup: ListedMenuGroup = {
|
||||
name: updatedAccountInfo.display_name,
|
||||
account: group.account,
|
||||
actions: updatedAccountInfo.actions,
|
||||
};
|
||||
|
||||
const updatedGroups = menuGroups.map((group) => {
|
||||
if (updatedGroup.account.authorId === group.account.authorId) {
|
||||
return updatedGroup;
|
||||
} else {
|
||||
return group;
|
||||
}
|
||||
});
|
||||
|
||||
setMenuGroups(updatedGroups);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchListedAccounts = async () => {
|
||||
if (!application.hasAccount()) {
|
||||
setIsFetchingAccounts(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const listedAccountEntries = await application.getListedAccounts();
|
||||
|
||||
if (!listedAccountEntries.length) {
|
||||
throw new Error('No Listed accounts found');
|
||||
}
|
||||
|
||||
const menuGroups: ListedMenuGroup[] = [];
|
||||
|
||||
await Promise.all(
|
||||
listedAccountEntries.map(async (account) => {
|
||||
const accountInfo = await application.getListedAccountInfo(
|
||||
account,
|
||||
note.uuid
|
||||
);
|
||||
|
||||
if (accountInfo) {
|
||||
menuGroups.push({
|
||||
name: accountInfo.display_name,
|
||||
account,
|
||||
actions: accountInfo.actions,
|
||||
});
|
||||
} else {
|
||||
menuGroups.push({
|
||||
name: account.authorId,
|
||||
account,
|
||||
actions: [],
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
setMenuGroups(
|
||||
menuGroups.sort((a, b) => {
|
||||
return a.name.toString().toLowerCase() <
|
||||
b.name.toString().toLowerCase()
|
||||
? -1
|
||||
: 1;
|
||||
})
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
setIsFetchingAccounts(false);
|
||||
setTimeout(() => {
|
||||
recalculateMenuStyle();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fetchListedAccounts();
|
||||
}, [application, note.uuid, recalculateMenuStyle]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{isFetchingAccounts && (
|
||||
<div className="w-full flex items-center justify-center p-4">
|
||||
<div className="sk-spinner w-5 h-5 spinner-info" />
|
||||
</div>
|
||||
)}
|
||||
{!isFetchingAccounts && menuGroups.length ? (
|
||||
<>
|
||||
{menuGroups.map((group, index) => (
|
||||
<Fragment key={group.account.authorId}>
|
||||
<div
|
||||
className={`w-full flex items-center px-2.5 py-2 text-input font-semibold color-text border-0 border-y-1px border-solid border-main ${
|
||||
index === 0 ? 'border-t-0 mb-1' : 'my-1'
|
||||
}`}
|
||||
>
|
||||
<Icon type="notes" className="mr-2 color-info" /> {group.name}
|
||||
</div>
|
||||
{group.actions.length ? (
|
||||
group.actions.map((action) => (
|
||||
<ListedMenuItem
|
||||
action={action}
|
||||
note={note}
|
||||
key={action.url}
|
||||
group={group}
|
||||
application={application}
|
||||
reloadMenuGroup={reloadMenuGroup}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<div className="px-3 py-2 color-grey-0 select-none">
|
||||
No actions available
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
))}
|
||||
</>
|
||||
) : null}
|
||||
{!isFetchingAccounts && !menuGroups.length ? (
|
||||
<div className="w-full flex items-center justify-center px-4 py-6">
|
||||
<div className="color-grey-0 select-none">
|
||||
No Listed accounts found
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const ListedActionsOption: FunctionComponent<Props> = ({
|
||||
application,
|
||||
note,
|
||||
closeOnBlur,
|
||||
}) => {
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
const menuButtonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const [menuStyle, setMenuStyle] = useState<SubmenuStyle>({
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
maxHeight: 'auto',
|
||||
});
|
||||
|
||||
const toggleListedMenu = () => {
|
||||
if (!isMenuOpen) {
|
||||
const menuPosition = calculateSubmenuStyle(menuButtonRef.current);
|
||||
if (menuPosition) {
|
||||
setMenuStyle(menuPosition);
|
||||
}
|
||||
}
|
||||
|
||||
setIsMenuOpen(!isMenuOpen);
|
||||
};
|
||||
|
||||
const recalculateMenuStyle = useCallback(() => {
|
||||
const newMenuPosition = calculateSubmenuStyle(
|
||||
menuButtonRef.current,
|
||||
menuRef.current
|
||||
);
|
||||
|
||||
if (newMenuPosition) {
|
||||
setMenuStyle(newMenuPosition);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isMenuOpen) {
|
||||
setTimeout(() => {
|
||||
recalculateMenuStyle();
|
||||
});
|
||||
}
|
||||
}, [isMenuOpen, recalculateMenuStyle]);
|
||||
|
||||
return (
|
||||
<Disclosure open={isMenuOpen} onChange={toggleListedMenu}>
|
||||
<DisclosureButton
|
||||
ref={menuButtonRef}
|
||||
onBlur={closeOnBlur}
|
||||
className="sn-dropdown-item justify-between"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<Icon type="listed" className="color-neutral mr-2" />
|
||||
Listed actions
|
||||
</div>
|
||||
<Icon type="chevron-right" className="color-neutral" />
|
||||
</DisclosureButton>
|
||||
<DisclosurePanel
|
||||
ref={menuRef}
|
||||
style={{
|
||||
...menuStyle,
|
||||
position: 'fixed',
|
||||
}}
|
||||
className="sn-dropdown flex flex-col max-h-120 min-w-68 pb-1 fixed overflow-y-auto"
|
||||
>
|
||||
{isMenuOpen && (
|
||||
<ListedActionsMenu
|
||||
application={application}
|
||||
note={note}
|
||||
recalculateMenuStyle={recalculateMenuStyle}
|
||||
/>
|
||||
)}
|
||||
</DisclosurePanel>
|
||||
</Disclosure>
|
||||
);
|
||||
};
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
MAX_MENU_SIZE_MULTIPLIER,
|
||||
BYTES_IN_ONE_MEGABYTE,
|
||||
} from '@/constants';
|
||||
import { ListedActionsOption } from './ListedActionsOption';
|
||||
|
||||
export type NotesOptionsProps = {
|
||||
application: WebApplication;
|
||||
@@ -602,6 +603,12 @@ export const NotesOptions = observer(
|
||||
)}
|
||||
{notes.length === 1 ? (
|
||||
<>
|
||||
<div className="min-h-1px my-2 bg-border"></div>
|
||||
<ListedActionsOption
|
||||
application={application}
|
||||
closeOnBlur={closeOnBlur}
|
||||
note={notes[0]}
|
||||
/>
|
||||
<div className="min-h-1px my-2 bg-border"></div>
|
||||
<SpellcheckOptions appState={appState} note={notes[0]} />
|
||||
<div className="min-h-1px my-2 bg-border"></div>
|
||||
|
||||
@@ -26,6 +26,7 @@ import { PLAIN_EDITOR_NAME } from './createEditorMenuGroups';
|
||||
type ChangeEditorMenuProps = {
|
||||
application: WebApplication;
|
||||
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void;
|
||||
closeMenu: () => void;
|
||||
groups: EditorMenuGroup[];
|
||||
isOpen: boolean;
|
||||
currentEditor: SNComponent | undefined;
|
||||
@@ -39,6 +40,7 @@ const getGroupId = (group: EditorMenuGroup) =>
|
||||
export const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
|
||||
application,
|
||||
closeOnBlur,
|
||||
closeMenu,
|
||||
groups,
|
||||
isOpen,
|
||||
currentEditor,
|
||||
@@ -169,6 +171,8 @@ export const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
|
||||
if (shouldSelectEditor) {
|
||||
selectComponent(itemToBeSelected.component ?? null, note);
|
||||
}
|
||||
|
||||
closeMenu();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -76,7 +76,7 @@ export const createEditorMenuGroups = (
|
||||
name: editor.name,
|
||||
component: editor,
|
||||
isEntitled:
|
||||
application.getFeatureStatus(editor.identifier) ===
|
||||
application.features.getFeatureStatus(editor.identifier) ===
|
||||
FeatureStatus.Entitled,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { FeaturesState } from '@/ui_models/app_state/features_state';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionalComponent } from 'preact';
|
||||
import { useContext } from 'preact/hooks';
|
||||
@@ -24,24 +25,33 @@ export const usePremiumModal = (): PremiumModalContextData => {
|
||||
};
|
||||
|
||||
interface Props {
|
||||
state: FeaturesState;
|
||||
application: WebApplication;
|
||||
appState: AppState;
|
||||
}
|
||||
|
||||
export const PremiumModalProvider: FunctionalComponent<Props> = observer(
|
||||
({ state, children }) => {
|
||||
const featureName = state._premiumAlertFeatureName;
|
||||
const activate = state.showPremiumAlert;
|
||||
const close = state.closePremiumAlert;
|
||||
({ application, appState, children }) => {
|
||||
const featureName = appState.features._premiumAlertFeatureName;
|
||||
const activate = appState.features.showPremiumAlert;
|
||||
const close = appState.features.closePremiumAlert;
|
||||
|
||||
const showModal = !!featureName;
|
||||
|
||||
const hasSubscription = Boolean(
|
||||
appState.subscription.userSubscription &&
|
||||
!appState.subscription.isUserSubscriptionExpired &&
|
||||
!appState.subscription.isUserSubscriptionCanceled
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{showModal && (
|
||||
<PremiumFeaturesModal
|
||||
showModal={!!featureName}
|
||||
application={application}
|
||||
featureName={featureName}
|
||||
hasSubscription={hasSubscription}
|
||||
onClose={close}
|
||||
showModal={!!featureName}
|
||||
/>
|
||||
)}
|
||||
<PremiumModalProvider_ value={{ activate }}>
|
||||
|
||||
@@ -7,23 +7,31 @@ import { FunctionalComponent } from 'preact';
|
||||
import { Icon } from './Icon';
|
||||
import { PremiumIllustration } from '@standardnotes/stylekit';
|
||||
import { useRef } from 'preact/hooks';
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { openSubscriptionDashboard } from '@/hooks/manageSubscription';
|
||||
|
||||
type Props = {
|
||||
application: WebApplication;
|
||||
featureName: string;
|
||||
hasSubscription: boolean;
|
||||
onClose: () => void;
|
||||
showModal: boolean;
|
||||
};
|
||||
|
||||
export const PremiumFeaturesModal: FunctionalComponent<Props> = ({
|
||||
application,
|
||||
featureName,
|
||||
hasSubscription,
|
||||
onClose,
|
||||
showModal,
|
||||
}) => {
|
||||
const plansButtonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const onClickPlans = () => {
|
||||
if (window._plans_url) {
|
||||
window.location.assign(window._plans_url);
|
||||
const handleClick = () => {
|
||||
if (hasSubscription) {
|
||||
openSubscriptionDashboard(application);
|
||||
} else if (window.plansUrl) {
|
||||
window.location.assign(window.plansUrl);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -61,11 +69,11 @@ export const PremiumFeaturesModal: FunctionalComponent<Props> = ({
|
||||
</AlertDialogDescription>
|
||||
<div className="p-4">
|
||||
<button
|
||||
onClick={onClickPlans}
|
||||
onClick={handleClick}
|
||||
className="w-full rounded no-border py-2 font-bold bg-info color-info-contrast hover:brightness-130 focus:brightness-130 cursor-pointer"
|
||||
ref={plansButtonRef}
|
||||
>
|
||||
See Plans
|
||||
{hasSubscription ? 'Upgrade Plan' : 'See Plans'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@ export const FocusModeSwitch: FunctionComponent<Props> = ({
|
||||
}) => {
|
||||
const premiumModal = usePremiumModal();
|
||||
const isEntitled =
|
||||
application.getFeatureStatus(FeatureIdentifier.FocusMode) ===
|
||||
application.features.getFeatureStatus(FeatureIdentifier.FocusMode) ===
|
||||
FeatureStatus.Entitled;
|
||||
|
||||
const toggle = useCallback(
|
||||
|
||||
@@ -22,12 +22,13 @@ export const ThemesMenuButton: FunctionComponent<Props> = ({
|
||||
const premiumModal = usePremiumModal();
|
||||
|
||||
const isThirdPartyTheme = useMemo(
|
||||
() => application.isThirdPartyFeature(item.identifier),
|
||||
() => application.features.isThirdPartyFeature(item.identifier),
|
||||
[application, item.identifier]
|
||||
);
|
||||
const isEntitledToTheme = useMemo(
|
||||
() =>
|
||||
application.getFeatureStatus(item.identifier) === FeatureStatus.Entitled,
|
||||
application.features.getFeatureStatus(item.identifier) ===
|
||||
FeatureStatus.Entitled,
|
||||
[application, item.identifier]
|
||||
);
|
||||
const canActivateTheme = useMemo(
|
||||
|
||||
@@ -155,7 +155,9 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
async (revisionListEntry: RevisionListEntry) => {
|
||||
setShowContentLockedScreen(false);
|
||||
|
||||
if (application.hasMinimumRole(revisionListEntry.required_role)) {
|
||||
if (
|
||||
application.features.hasMinimumRole(revisionListEntry.required_role)
|
||||
) {
|
||||
setIsFetchingSelectedRevision(true);
|
||||
setSelectedRevision(undefined);
|
||||
setSelectedRemoteEntry(undefined);
|
||||
@@ -202,7 +204,6 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
<div className={`min-h-0 overflow-auto py-1.5 h-full`}>
|
||||
{selectedTab === RevisionListTabType.Session && (
|
||||
<SessionHistoryList
|
||||
selectedTab={selectedTab}
|
||||
sessionHistory={sessionHistory}
|
||||
setSelectedRevision={setSelectedRevision}
|
||||
setSelectedRemoteEntry={setSelectedRemoteEntry}
|
||||
@@ -214,12 +215,10 @@ export const HistoryListContainer: FunctionComponent<Props> = observer(
|
||||
remoteHistory={remoteHistory}
|
||||
isFetchingRemoteHistory={isFetchingRemoteHistory}
|
||||
fetchAndSetRemoteRevision={fetchAndSetRemoteRevision}
|
||||
selectedTab={selectedTab}
|
||||
/>
|
||||
)}
|
||||
{selectedTab === RevisionListTabType.Legacy && (
|
||||
<LegacyHistoryList
|
||||
selectedTab={selectedTab}
|
||||
legacyHistory={legacyHistory}
|
||||
setSelectedRevision={setSelectedRevision}
|
||||
setSelectedRemoteEntry={setSelectedRemoteEntry}
|
||||
|
||||
@@ -9,12 +9,10 @@ import {
|
||||
useState,
|
||||
} from 'preact/hooks';
|
||||
import { useListKeyboardNavigation } from '../utils';
|
||||
import { RevisionListTabType } from './HistoryListContainer';
|
||||
import { HistoryListItem } from './HistoryListItem';
|
||||
import { LegacyHistoryEntry } from './utils';
|
||||
|
||||
type Props = {
|
||||
selectedTab: RevisionListTabType;
|
||||
legacyHistory: Action[] | undefined;
|
||||
setSelectedRevision: StateUpdater<
|
||||
HistoryEntry | LegacyHistoryEntry | undefined
|
||||
@@ -25,7 +23,6 @@ type Props = {
|
||||
|
||||
export const LegacyHistoryList: FunctionComponent<Props> = ({
|
||||
legacyHistory,
|
||||
selectedTab,
|
||||
setSelectedRevision,
|
||||
setSelectedRemoteEntry,
|
||||
fetchAndSetLegacyRevision,
|
||||
@@ -56,13 +53,6 @@ export const LegacyHistoryList: FunctionComponent<Props> = ({
|
||||
}
|
||||
}, [firstEntry, selectFirstEntry, selectedItemUrl, setSelectedRevision]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTab === RevisionListTabType.Legacy) {
|
||||
selectFirstEntry();
|
||||
legacyHistoryListRef.current?.focus();
|
||||
}
|
||||
}, [selectFirstEntry, selectedTab]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col w-full h-full focus:shadow-none ${
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from 'preact/hooks';
|
||||
import { Icon } from '../Icon';
|
||||
import { useListKeyboardNavigation } from '../utils';
|
||||
import { RevisionListTabType } from './HistoryListContainer';
|
||||
import { HistoryListItem } from './HistoryListItem';
|
||||
import { previewHistoryEntryTitle, RemoteRevisionListGroup } from './utils';
|
||||
|
||||
@@ -22,7 +21,6 @@ type RemoteHistoryListProps = {
|
||||
fetchAndSetRemoteRevision: (
|
||||
revisionListEntry: RevisionListEntry
|
||||
) => Promise<void>;
|
||||
selectedTab: RevisionListTabType;
|
||||
};
|
||||
|
||||
export const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> =
|
||||
@@ -32,7 +30,6 @@ export const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> =
|
||||
remoteHistory,
|
||||
isFetchingRemoteHistory,
|
||||
fetchAndSetRemoteRevision,
|
||||
selectedTab,
|
||||
}) => {
|
||||
const remoteHistoryListRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -69,13 +66,6 @@ export const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> =
|
||||
selectedEntryUuid.length,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTab === RevisionListTabType.Remote) {
|
||||
selectFirstEntry();
|
||||
remoteHistoryListRef.current?.focus();
|
||||
}
|
||||
}, [selectFirstEntry, selectedTab]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col w-full h-full focus:shadow-none ${
|
||||
@@ -105,9 +95,9 @@ export const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> =
|
||||
>
|
||||
<div className="flex flex-grow items-center justify-between">
|
||||
<div>{previewHistoryEntryTitle(entry)}</div>
|
||||
{!application.hasMinimumRole(entry.required_role) && (
|
||||
<Icon type="premium-feature" />
|
||||
)}
|
||||
{!application.features.hasMinimumRole(
|
||||
entry.required_role
|
||||
) && <Icon type="premium-feature" />}
|
||||
</div>
|
||||
</HistoryListItem>
|
||||
))}
|
||||
|
||||
@@ -49,8 +49,8 @@ export const RevisionContentLocked: FunctionComponent<{
|
||||
type="primary"
|
||||
label="Discover plans"
|
||||
onClick={() => {
|
||||
if (window._plans_url) {
|
||||
window.location.assign(window._plans_url);
|
||||
if (window.plansUrl) {
|
||||
window.location.assign(window.plansUrl);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -13,12 +13,10 @@ import {
|
||||
useState,
|
||||
} from 'preact/hooks';
|
||||
import { useListKeyboardNavigation } from '../utils';
|
||||
import { RevisionListTabType } from './HistoryListContainer';
|
||||
import { HistoryListItem } from './HistoryListItem';
|
||||
import { LegacyHistoryEntry, ListGroup } from './utils';
|
||||
|
||||
type Props = {
|
||||
selectedTab: RevisionListTabType;
|
||||
sessionHistory: ListGroup<NoteHistoryEntry>[];
|
||||
setSelectedRevision: StateUpdater<
|
||||
HistoryEntry | LegacyHistoryEntry | undefined
|
||||
@@ -28,7 +26,6 @@ type Props = {
|
||||
|
||||
export const SessionHistoryList: FunctionComponent<Props> = ({
|
||||
sessionHistory,
|
||||
selectedTab,
|
||||
setSelectedRevision,
|
||||
setSelectedRemoteEntry,
|
||||
}) => {
|
||||
@@ -67,13 +64,6 @@ export const SessionHistoryList: FunctionComponent<Props> = ({
|
||||
setSelectedRevision,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedTab === RevisionListTabType.Session) {
|
||||
selectFirstEntry();
|
||||
sessionHistoryListRef.current?.focus();
|
||||
}
|
||||
}, [selectFirstEntry, selectedTab]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col w-full h-full focus:shadow-none ${
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { SmartTagsListItem } from './SmartTagsListItem';
|
||||
import { SmartViewsListItem } from './SmartViewsListItem';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
};
|
||||
|
||||
export const SmartTagsList: FunctionComponent<Props> = observer(
|
||||
export const SmartViewsList: FunctionComponent<Props> = observer(
|
||||
({ appState }) => {
|
||||
const allTags = appState.tags.smartTags;
|
||||
const allViews = appState.tags.smartViews;
|
||||
|
||||
return (
|
||||
<>
|
||||
{allTags.map((tag) => {
|
||||
{allViews.map((view) => {
|
||||
return (
|
||||
<SmartTagsListItem
|
||||
key={tag.uuid}
|
||||
tag={tag}
|
||||
<SmartViewsListItem
|
||||
key={view.uuid}
|
||||
view={view}
|
||||
tagsState={appState.tags}
|
||||
features={appState.features}
|
||||
/>
|
||||
@@ -2,13 +2,18 @@ import { Icon } from '@/components/Icon';
|
||||
import { FeaturesState } from '@/ui_models/app_state/features_state';
|
||||
import { TagsState } from '@/ui_models/app_state/tags_state';
|
||||
import '@reach/tooltip/styles.css';
|
||||
import { SNSmartTag, IconType } from '@standardnotes/snjs';
|
||||
import {
|
||||
SmartView,
|
||||
SystemViewId,
|
||||
IconType,
|
||||
isSystemView,
|
||||
} from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
|
||||
|
||||
type Props = {
|
||||
tag: SNSmartTag;
|
||||
view: SmartView;
|
||||
tagsState: TagsState;
|
||||
features: FeaturesState;
|
||||
};
|
||||
@@ -16,40 +21,44 @@ type Props = {
|
||||
const PADDING_BASE_PX = 14;
|
||||
const PADDING_PER_LEVEL_PX = 21;
|
||||
|
||||
const smartTagIconType = (tag: SNSmartTag): IconType => {
|
||||
if (tag.isAllTag) {
|
||||
const smartViewIconType = (view: SmartView): IconType => {
|
||||
if (view.uuid === SystemViewId.AllNotes) {
|
||||
return 'notes';
|
||||
}
|
||||
if (tag.isArchiveTag) {
|
||||
if (view.uuid === SystemViewId.ArchivedNotes) {
|
||||
return 'archive';
|
||||
}
|
||||
if (tag.isTrashTag) {
|
||||
if (view.uuid === SystemViewId.TrashedNotes) {
|
||||
return 'trash';
|
||||
}
|
||||
if (view.uuid === SystemViewId.UntaggedNotes) {
|
||||
return 'hashtag-off';
|
||||
}
|
||||
|
||||
return 'hashtag';
|
||||
};
|
||||
|
||||
export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
({ tag, tagsState, features }) => {
|
||||
const [title, setTitle] = useState(tag.title || '');
|
||||
export const SmartViewsListItem: FunctionComponent<Props> = observer(
|
||||
({ view, tagsState }) => {
|
||||
const [title, setTitle] = useState(view.title || '');
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const level = 0;
|
||||
const isSelected = tagsState.selected === tag;
|
||||
const isEditing = tagsState.editingTag === tag;
|
||||
const isSelected = tagsState.selected === view;
|
||||
const isEditing = tagsState.editingTag === view;
|
||||
|
||||
useEffect(() => {
|
||||
setTitle(tag.title || '');
|
||||
}, [setTitle, tag]);
|
||||
setTitle(view.title || '');
|
||||
}, [setTitle, view]);
|
||||
|
||||
const selectCurrentTag = useCallback(() => {
|
||||
tagsState.selected = tag;
|
||||
}, [tagsState, tag]);
|
||||
tagsState.selected = view;
|
||||
}, [tagsState, view]);
|
||||
|
||||
const onBlur = useCallback(() => {
|
||||
tagsState.save(tag, title);
|
||||
setTitle(tag.title);
|
||||
}, [tagsState, tag, title, setTitle]);
|
||||
tagsState.save(view, title);
|
||||
setTitle(view.title);
|
||||
}, [tagsState, view, title, setTitle]);
|
||||
|
||||
const onInput = useCallback(
|
||||
(e: Event) => {
|
||||
@@ -76,19 +85,19 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
}, [inputRef, isEditing]);
|
||||
|
||||
const onClickRename = useCallback(() => {
|
||||
tagsState.editingTag = tag;
|
||||
}, [tagsState, tag]);
|
||||
tagsState.editingTag = view;
|
||||
}, [tagsState, view]);
|
||||
|
||||
const onClickSave = useCallback(() => {
|
||||
inputRef.current?.blur();
|
||||
}, [inputRef]);
|
||||
|
||||
const onClickDelete = useCallback(() => {
|
||||
tagsState.remove(tag, true);
|
||||
}, [tagsState, tag]);
|
||||
tagsState.remove(view, true);
|
||||
}, [tagsState, view]);
|
||||
|
||||
const isFaded = !tag.isAllTag;
|
||||
const iconType = smartTagIconType(tag);
|
||||
const isFaded = false;
|
||||
const iconType = smartViewIconType(view);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -101,7 +110,7 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
paddingLeft: `${level * PADDING_PER_LEVEL_PX + PADDING_BASE_PX}px`,
|
||||
}}
|
||||
>
|
||||
{!tag.errorDecrypting ? (
|
||||
{!view.errorDecrypting ? (
|
||||
<div className="tag-info">
|
||||
<div className={`tag-icon mr-1`}>
|
||||
<Icon
|
||||
@@ -112,7 +121,7 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
<input
|
||||
className={`title ${isEditing ? 'editing' : ''}`}
|
||||
disabled={!isEditing}
|
||||
id={`react-tag-${tag.uuid}`}
|
||||
id={`react-tag-${view.uuid}`}
|
||||
onBlur={onBlur}
|
||||
onInput={onInput}
|
||||
value={title}
|
||||
@@ -121,21 +130,21 @@ export const SmartTagsListItem: FunctionComponent<Props> = observer(
|
||||
ref={inputRef}
|
||||
/>
|
||||
<div className="count">
|
||||
{tag.isAllTag && tagsState.allNotesCount}
|
||||
{view.uuid === SystemViewId.AllNotes && tagsState.allNotesCount}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{!tag.isSystemSmartTag && (
|
||||
{!isSystemView(view) && (
|
||||
<div className="meta">
|
||||
{tag.conflictOf && (
|
||||
{view.conflictOf && (
|
||||
<div className="danger small-text font-bold">
|
||||
Conflicted Copy {tag.conflictOf}
|
||||
Conflicted Copy {view.conflictOf}
|
||||
</div>
|
||||
)}
|
||||
{tag.errorDecrypting && !tag.waitingForKey && (
|
||||
{view.errorDecrypting && !view.waitingForKey && (
|
||||
<div className="danger small-text font-bold">Missing Keys</div>
|
||||
)}
|
||||
{tag.errorDecrypting && tag.waitingForKey && (
|
||||
{view.errorDecrypting && view.waitingForKey && (
|
||||
<div className="info small-text font-bold">
|
||||
Waiting For Keys
|
||||
</div>
|
||||
@@ -1,17 +1,17 @@
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { SmartTagsList } from './SmartTagsList';
|
||||
import { SmartViewsList } from './SmartViewsList';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
};
|
||||
|
||||
export const SmartTagsSection: FunctionComponent<Props> = observer(
|
||||
export const SmartViewsSection: FunctionComponent<Props> = observer(
|
||||
({ appState }) => {
|
||||
return (
|
||||
<section>
|
||||
<SmartTagsList appState={appState} />
|
||||
<SmartViewsList appState={appState} />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { Menu } from '../menu/Menu';
|
||||
import { MenuItem, MenuItemType } from '../menu/MenuItem';
|
||||
import { usePremiumModal } from '../Premium';
|
||||
import { useCloseOnBlur } from '../utils';
|
||||
import { SNTag } from '@standardnotes/snjs';
|
||||
|
||||
type Props = {
|
||||
appState: AppState;
|
||||
@@ -17,7 +18,7 @@ export const TagsContextMenu: FunctionComponent<Props> = observer(
|
||||
const premiumModal = usePremiumModal();
|
||||
const selectedTag = appState.tags.selected;
|
||||
|
||||
if (!selectedTag) {
|
||||
if (!selectedTag || !(selectedTag instanceof SNTag)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ export function openSubscriptionDashboard(application: SNApplication): void {
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
window.open(
|
||||
`${window._dashboard_url}?subscription_token=${token}`
|
||||
);
|
||||
window.open(`${window.dashboardUrl}?subscription_token=${token}`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export const Appearance: FunctionComponent<Props> = observer(
|
||||
({ application }) => {
|
||||
const premiumModal = usePremiumModal();
|
||||
const isEntitledToMidnightTheme =
|
||||
application.getFeatureStatus(FeatureIdentifier.MidnightTheme) ===
|
||||
application.features.getFeatureStatus(FeatureIdentifier.MidnightTheme) ===
|
||||
FeatureStatus.Entitled;
|
||||
|
||||
const [themeItems, setThemeItems] = useState<DropdownItem[]>([]);
|
||||
|
||||
@@ -58,7 +58,7 @@ export const Extensions: FunctionComponent<{
|
||||
};
|
||||
|
||||
const submitExtensionUrl = async (url: string) => {
|
||||
const component = await application.downloadExternalFeature(url);
|
||||
const component = await application.features.downloadExternalFeature(url);
|
||||
if (component) {
|
||||
setConfirmableExtension(component);
|
||||
}
|
||||
|
||||
@@ -27,15 +27,17 @@ export const OfflineSubscription: FunctionalComponent<IProps> = observer(
|
||||
useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (application.hasOfflineRepo()) {
|
||||
if (application.features.hasOfflineRepo()) {
|
||||
setHasUserPreviouslyStoredCode(true);
|
||||
}
|
||||
}, [application]);
|
||||
|
||||
const shouldShowOfflineSubscription = () => {
|
||||
return !application.hasAccount() ||
|
||||
return (
|
||||
!application.hasAccount() ||
|
||||
application.isThirdPartyHostUsed() ||
|
||||
hasUserPreviouslyStoredCode;
|
||||
hasUserPreviouslyStoredCode
|
||||
);
|
||||
};
|
||||
|
||||
const handleSubscriptionCodeSubmit = async (
|
||||
@@ -43,7 +45,9 @@ export const OfflineSubscription: FunctionalComponent<IProps> = observer(
|
||||
) => {
|
||||
event.preventDefault();
|
||||
|
||||
const result = await application.setOfflineFeaturesCode(activationCode);
|
||||
const result = await application.features.setOfflineFeaturesCode(
|
||||
activationCode
|
||||
);
|
||||
|
||||
if (result?.error) {
|
||||
await application.alertService.alert(result.error);
|
||||
@@ -55,7 +59,7 @@ export const OfflineSubscription: FunctionalComponent<IProps> = observer(
|
||||
};
|
||||
|
||||
const handleRemoveOfflineKey = async () => {
|
||||
await application.deleteOfflineFeatureRepo();
|
||||
await application.features.deleteOfflineFeatureRepo();
|
||||
|
||||
setIsSuccessfullyActivated(false);
|
||||
setHasUserPreviouslyStoredCode(false);
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { FunctionalComponent } from "preact";
|
||||
import { FunctionalComponent } from 'preact';
|
||||
import { LinkButton, Text } from '@/preferences/components';
|
||||
import { Button } from '@/components/Button';
|
||||
import { WebApplication } from "@/ui_models/application";
|
||||
import { useState } from "preact/hooks";
|
||||
import { loadPurchaseFlowUrl } from "@/purchaseFlow/PurchaseFlowWrapper";
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { useState } from 'preact/hooks';
|
||||
import { loadPurchaseFlowUrl } from '@/purchaseFlow/PurchaseFlowWrapper';
|
||||
|
||||
export const NoSubscription: FunctionalComponent<{
|
||||
application: WebApplication;
|
||||
}> = ({ application }) => {
|
||||
const [isLoadingPurchaseFlow, setIsLoadingPurchaseFlow] = useState(false);
|
||||
const [purchaseFlowError, setPurchaseFlowError] = useState<string | undefined>(undefined);
|
||||
const [purchaseFlowError, setPurchaseFlowError] = useState<
|
||||
string | undefined
|
||||
>(undefined);
|
||||
|
||||
const onPurchaseClick = async () => {
|
||||
const errorMessage = 'There was an error when attempting to redirect you to the subscription page.';
|
||||
const errorMessage =
|
||||
'There was an error when attempting to redirect you to the subscription page.';
|
||||
setIsLoadingPurchaseFlow(true);
|
||||
try {
|
||||
if (!await loadPurchaseFlowUrl(application)) {
|
||||
if (!(await loadPurchaseFlowUrl(application))) {
|
||||
setPurchaseFlowError(errorMessage);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -29,29 +32,25 @@ export const NoSubscription: FunctionalComponent<{
|
||||
<>
|
||||
<Text>You don't have a Standard Notes subscription yet.</Text>
|
||||
{isLoadingPurchaseFlow && (
|
||||
<Text>
|
||||
Redirecting you to the subscription page...
|
||||
</Text>
|
||||
<Text>Redirecting you to the subscription page...</Text>
|
||||
)}
|
||||
{purchaseFlowError && (
|
||||
<Text className="color-danger">
|
||||
{purchaseFlowError}
|
||||
</Text>
|
||||
<Text className="color-danger">{purchaseFlowError}</Text>
|
||||
)}
|
||||
<div className="flex">
|
||||
<LinkButton
|
||||
className="min-w-20 mt-3 mr-3"
|
||||
label="Learn More"
|
||||
link={window._plans_url as string}
|
||||
link={window.plansUrl as string}
|
||||
/>
|
||||
{application.hasAccount() &&
|
||||
{application.hasAccount() && (
|
||||
<Button
|
||||
className="min-w-20 mt-3"
|
||||
type="primary"
|
||||
label="Subscribe"
|
||||
onClick={onPurchaseClick}
|
||||
/>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -62,7 +62,7 @@ export const EmailBackups = observer(({ application }: Props) => {
|
||||
}, [application]);
|
||||
|
||||
useEffect(() => {
|
||||
const emailBackupsFeatureStatus = application.getFeatureStatus(
|
||||
const emailBackupsFeatureStatus = application.features.getFeatureStatus(
|
||||
FeatureIdentifier.DailyEmailBackup
|
||||
);
|
||||
setIsEntitledToEmailBackups(
|
||||
|
||||
@@ -65,13 +65,13 @@ export const CloudLink: FunctionComponent<Props> = ({ application }) => {
|
||||
}, [application]);
|
||||
|
||||
useEffect(() => {
|
||||
const dailyDropboxBackupStatus = application.getFeatureStatus(
|
||||
const dailyDropboxBackupStatus = application.features.getFeatureStatus(
|
||||
FeatureIdentifier.DailyDropboxBackup
|
||||
);
|
||||
const dailyGdriveBackupStatus = application.getFeatureStatus(
|
||||
const dailyGdriveBackupStatus = application.features.getFeatureStatus(
|
||||
FeatureIdentifier.DailyGDriveBackup
|
||||
);
|
||||
const dailyOneDriveBackupStatus = application.getFeatureStatus(
|
||||
const dailyOneDriveBackupStatus = application.features.getFeatureStatus(
|
||||
FeatureIdentifier.DailyOneDriveBackup
|
||||
);
|
||||
const isCloudBackupsAllowed = [
|
||||
|
||||
@@ -74,7 +74,9 @@ export const ExtensionItem: FunctionComponent<ExtensionItemProps> = ({
|
||||
};
|
||||
|
||||
const localInstallable = extension.package_info.download_url;
|
||||
const isThirParty = application.isThirdPartyFeature(extension.identifier);
|
||||
const isThirParty = application.features.isThirdPartyFeature(
|
||||
extension.identifier
|
||||
);
|
||||
|
||||
return (
|
||||
<PreferencesSegment classes={'mb-5'}>
|
||||
|
||||
@@ -16,11 +16,11 @@ export const getPurchaseFlowUrl = async (
|
||||
const currentUrl = window.location.origin;
|
||||
const successUrl = isDesktopApplication() ? `standardnotes://` : currentUrl;
|
||||
if (application.noAccount()) {
|
||||
return `${window._purchase_url}/offline?&success_url=${successUrl}`;
|
||||
return `${window.purchaseUrl}/offline?&success_url=${successUrl}`;
|
||||
}
|
||||
const token = await application.getNewSubscriptionToken();
|
||||
if (token) {
|
||||
return `${window._purchase_url}?subscription_token=${token}&success_url=${successUrl}`;
|
||||
return `${window.purchaseUrl}?subscription_token=${token}&success_url=${successUrl}`;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -99,6 +99,7 @@ export class AlertService implements SNAlertService {
|
||||
const alert = new SKAlert({
|
||||
title: title && sanitizeHtmlString(title),
|
||||
text: sanitizeHtmlString(text),
|
||||
buttons: [],
|
||||
});
|
||||
alert.present();
|
||||
return () => {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
import { WebAppEvent, WebApplication } from '@/ui_models/application';
|
||||
import { isDesktopApplication } from '@/utils';
|
||||
import { Bridge, ElectronDesktopCallbacks } from './bridge';
|
||||
import { InternalEventBus } from '@standardnotes/services';
|
||||
|
||||
/**
|
||||
* An interface used by the Desktop application to interact with SN
|
||||
@@ -31,7 +32,7 @@ export class DesktopManager
|
||||
lastSearchedText?: string;
|
||||
|
||||
constructor(application: WebApplication, private bridge: Bridge) {
|
||||
super(application);
|
||||
super(application, new InternalEventBus());
|
||||
}
|
||||
|
||||
get webApplication() {
|
||||
|
||||
@@ -25,7 +25,7 @@ export function startErrorReporting(): void {
|
||||
*/
|
||||
isNullOrUndefined(disableErrorReporting) ||
|
||||
disableErrorReporting ||
|
||||
!window._bugsnag_api_key
|
||||
!window.bugsnagApiKey
|
||||
) {
|
||||
SNLog.onError = console.error;
|
||||
return;
|
||||
@@ -41,7 +41,7 @@ export function startErrorReporting(): void {
|
||||
}
|
||||
|
||||
Bugsnag.start({
|
||||
apiKey: window._bugsnag_api_key,
|
||||
apiKey: window.bugsnagApiKey,
|
||||
appType: isDesktopApplication() ? 'desktop' : 'web',
|
||||
appVersion: getDesktopVersion() || WebAppVersion,
|
||||
collectUserIp: false,
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
PayloadSource,
|
||||
PrefKey,
|
||||
} from '@standardnotes/snjs';
|
||||
import { InternalEventBus } from '@standardnotes/services';
|
||||
|
||||
const CACHED_THEMES_KEY = 'cachedThemes';
|
||||
|
||||
@@ -21,7 +22,7 @@ export class ThemeManager extends ApplicationService {
|
||||
private unregisterStream!: () => void;
|
||||
|
||||
constructor(application: WebApplication) {
|
||||
super(application);
|
||||
super(application, new InternalEventBus());
|
||||
this.colorSchemeEventHandler = this.colorSchemeEventHandler.bind(this);
|
||||
}
|
||||
|
||||
@@ -127,7 +128,9 @@ export class ThemeManager extends ApplicationService {
|
||||
this.deactivateTheme(themeUuid);
|
||||
hasChange = true;
|
||||
} else {
|
||||
const status = this.application.getFeatureStatus(theme.identifier);
|
||||
const status = this.application.features.getFeatureStatus(
|
||||
theme.identifier
|
||||
);
|
||||
if (status !== FeatureStatus.Entitled) {
|
||||
if (theme.active) {
|
||||
this.application.toggleTheme(theme);
|
||||
@@ -212,7 +215,7 @@ export class ThemeManager extends ApplicationService {
|
||||
|
||||
if (
|
||||
!skipEntitlementCheck &&
|
||||
this.application.getFeatureStatus(theme.identifier) !==
|
||||
this.application.features.getFeatureStatus(theme.identifier) !==
|
||||
FeatureStatus.Entitled
|
||||
) {
|
||||
return;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Bridge } from "./services/bridge";
|
||||
import { Bridge } from './services/bridge';
|
||||
|
||||
export type StartApplication = (
|
||||
defaultSyncServerHost: string,
|
||||
defaultFilesHostHost: string,
|
||||
bridge: Bridge,
|
||||
enableUnfinishedFeatures: boolean,
|
||||
webSocketUrl: string,
|
||||
webSocketUrl: string
|
||||
) => Promise<void>;
|
||||
|
||||
1
app/assets/javascripts/typings/stylekit.d.ts
vendored
1
app/assets/javascripts/typings/stylekit.d.ts
vendored
@@ -1 +0,0 @@
|
||||
declare module '@standardnotes/stylekit';
|
||||
@@ -75,9 +75,9 @@ export class AccountMenuState {
|
||||
this.appEventListeners.push(
|
||||
this.application.addEventObserver(async () => {
|
||||
runInAction(() => {
|
||||
if (isDev && window._devAccountServer) {
|
||||
this.setServer(window._devAccountServer);
|
||||
this.application.setCustomHost(window._devAccountServer);
|
||||
if (isDev && window.devAccountServer) {
|
||||
this.setServer(window.devAccountServer);
|
||||
this.application.setCustomHost(window.devAccountServer);
|
||||
} else {
|
||||
this.setServer(this.application.getHost());
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ import {
|
||||
PayloadSource,
|
||||
PrefKey,
|
||||
SNNote,
|
||||
SNSmartTag,
|
||||
SmartView,
|
||||
SNTag,
|
||||
SystemViewId,
|
||||
} from '@standardnotes/snjs';
|
||||
import pull from 'lodash/pull';
|
||||
import {
|
||||
@@ -62,7 +63,7 @@ type ObserverCallback = (event: AppStateEvent, data?: any) => Promise<void>;
|
||||
|
||||
export class AppState {
|
||||
readonly enableUnfinishedFeatures: boolean =
|
||||
window?._enable_unfinished_features;
|
||||
window?.enabledUnfinishedFeatures;
|
||||
|
||||
application: WebApplication;
|
||||
observers: ObserverCallback[] = [];
|
||||
@@ -241,7 +242,9 @@ export class AppState {
|
||||
const selectedTag = this.selectedTag;
|
||||
|
||||
const activeRegularTagUuid =
|
||||
selectedTag && !selectedTag.isSmartTag ? selectedTag.uuid : undefined;
|
||||
selectedTag && selectedTag instanceof SNTag
|
||||
? selectedTag.uuid
|
||||
: undefined;
|
||||
|
||||
await this.application.noteControllerGroup.createNoteView(
|
||||
undefined,
|
||||
@@ -313,11 +316,11 @@ export class AppState {
|
||||
);
|
||||
}
|
||||
|
||||
public get selectedTag(): SNTag | SNSmartTag | undefined {
|
||||
public get selectedTag(): SNTag | SmartView | undefined {
|
||||
return this.tags.selected;
|
||||
}
|
||||
|
||||
public set selectedTag(tag: SNTag | SNSmartTag | undefined) {
|
||||
public set selectedTag(tag: SNTag | SmartView | undefined) {
|
||||
this.tags.selected = tag;
|
||||
}
|
||||
|
||||
@@ -341,13 +344,19 @@ export class AppState {
|
||||
this.closeNoteController(noteController);
|
||||
} else if (
|
||||
note.trashed &&
|
||||
!selectedTag?.isTrashTag &&
|
||||
!(
|
||||
selectedTag instanceof SmartView &&
|
||||
selectedTag.uuid === SystemViewId.TrashedNotes
|
||||
) &&
|
||||
!this.searchOptions.includeTrashed
|
||||
) {
|
||||
this.closeNoteController(noteController);
|
||||
} else if (
|
||||
note.archived &&
|
||||
!selectedTag?.isArchiveTag &&
|
||||
!(
|
||||
selectedTag instanceof SmartView &&
|
||||
selectedTag.uuid === SystemViewId.ArchivedNotes
|
||||
) &&
|
||||
!this.searchOptions.includeArchived &&
|
||||
!this.application.getPreference(PrefKey.NotesShowArchived, false)
|
||||
) {
|
||||
|
||||
@@ -25,22 +25,22 @@ export const SMART_TAGS_FEATURE_NAME = 'Smart Tags';
|
||||
*/
|
||||
export class FeaturesState {
|
||||
readonly enableUnfinishedFeatures: boolean =
|
||||
window?._enable_unfinished_features;
|
||||
window?.enabledUnfinishedFeatures;
|
||||
|
||||
_hasFolders = false;
|
||||
_hasSmartTags = false;
|
||||
_hasSmartViews = false;
|
||||
_premiumAlertFeatureName: string | undefined;
|
||||
|
||||
private unsub: () => void;
|
||||
|
||||
constructor(private application: WebApplication) {
|
||||
this._hasFolders = this.hasNativeFolders();
|
||||
this._hasSmartTags = this.hasNativeSmartTags();
|
||||
this._hasSmartViews = this.hasNativeSmartViews();
|
||||
this._premiumAlertFeatureName = undefined;
|
||||
|
||||
makeObservable(this, {
|
||||
_hasFolders: observable,
|
||||
_hasSmartTags: observable,
|
||||
_hasSmartViews: observable,
|
||||
hasFolders: computed,
|
||||
_premiumAlertFeatureName: observable,
|
||||
showPremiumAlert: action,
|
||||
@@ -56,7 +56,7 @@ export class FeaturesState {
|
||||
case ApplicationEvent.Launched:
|
||||
runInAction(() => {
|
||||
this._hasFolders = this.hasNativeFolders();
|
||||
this._hasSmartTags = this.hasNativeSmartTags();
|
||||
this._hasSmartViews = this.hasNativeSmartViews();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@@ -73,8 +73,8 @@ export class FeaturesState {
|
||||
return this._hasFolders;
|
||||
}
|
||||
|
||||
public get hasSmartTags(): boolean {
|
||||
return this._hasSmartTags;
|
||||
public get hasSmartViews(): boolean {
|
||||
return this._hasSmartViews;
|
||||
}
|
||||
|
||||
public async showPremiumAlert(featureName: string): Promise<void> {
|
||||
@@ -87,15 +87,15 @@ export class FeaturesState {
|
||||
}
|
||||
|
||||
private hasNativeFolders(): boolean {
|
||||
const status = this.application.getFeatureStatus(
|
||||
const status = this.application.features.getFeatureStatus(
|
||||
FeatureIdentifier.TagNesting
|
||||
);
|
||||
|
||||
return status === FeatureStatus.Entitled;
|
||||
}
|
||||
|
||||
private hasNativeSmartTags(): boolean {
|
||||
const status = this.application.getFeatureStatus(
|
||||
private hasNativeSmartViews(): boolean {
|
||||
const status = this.application.features.getFeatureStatus(
|
||||
FeatureIdentifier.SmartFilters
|
||||
);
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ import {
|
||||
findInArray,
|
||||
NotesDisplayCriteria,
|
||||
PrefKey,
|
||||
SmartView,
|
||||
SNNote,
|
||||
SNTag,
|
||||
SystemViewId,
|
||||
UuidString,
|
||||
} from '@standardnotes/snjs';
|
||||
import {
|
||||
@@ -79,7 +81,10 @@ export class NotesViewState {
|
||||
const discarded = activeNote.deleted || activeNote.trashed;
|
||||
if (
|
||||
discarded &&
|
||||
!this.appState?.selectedTag?.isTrashTag &&
|
||||
!(
|
||||
this.appState.selectedTag instanceof SmartView &&
|
||||
this.appState.selectedTag?.uuid === SystemViewId.TrashedNotes
|
||||
) &&
|
||||
!this.appState?.searchOptions.includeTrashed
|
||||
) {
|
||||
this.selectNextOrCreateNew();
|
||||
@@ -116,7 +121,8 @@ export class NotesViewState {
|
||||
this.reloadNotes();
|
||||
if (
|
||||
this.notes.length === 0 &&
|
||||
this.appState.selectedTag?.isAllTag &&
|
||||
this.appState.selectedTag instanceof SmartView &&
|
||||
this.appState.selectedTag.uuid === SystemViewId.AllNotes &&
|
||||
this.noteFilterText === '' &&
|
||||
!this.appState.notes.activeNoteController
|
||||
) {
|
||||
@@ -246,7 +252,8 @@ export class NotesViewState {
|
||||
const criteria = NotesDisplayCriteria.Create({
|
||||
sortProperty: this.displayOptions.sortBy as CollectionSort,
|
||||
sortDirection: this.displayOptions.sortReverse ? 'asc' : 'dsc',
|
||||
tags: tag ? [tag] : [],
|
||||
tags: tag instanceof SNTag ? [tag] : [],
|
||||
views: tag instanceof SmartView ? [tag] : [],
|
||||
includeArchived,
|
||||
includeTrashed,
|
||||
includePinned: !this.displayOptions.hidePinned,
|
||||
@@ -353,7 +360,11 @@ export class NotesViewState {
|
||||
|
||||
createPlaceholderNote = () => {
|
||||
const selectedTag = this.appState.selectedTag;
|
||||
if (selectedTag && selectedTag.isSmartTag && !selectedTag.isAllTag) {
|
||||
if (
|
||||
selectedTag &&
|
||||
selectedTag instanceof SmartView &&
|
||||
selectedTag.uuid !== SystemViewId.AllNotes
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return this.createNewNote();
|
||||
|
||||
@@ -9,10 +9,11 @@ import {
|
||||
ContentType,
|
||||
MessageData,
|
||||
SNApplication,
|
||||
SNSmartTag,
|
||||
SmartView,
|
||||
SNTag,
|
||||
TagMutator,
|
||||
UuidString,
|
||||
isSystemView,
|
||||
} from '@standardnotes/snjs';
|
||||
import {
|
||||
action,
|
||||
@@ -25,7 +26,7 @@ import {
|
||||
import { WebApplication } from '../application';
|
||||
import { FeaturesState, SMART_TAGS_FEATURE_NAME } from './features_state';
|
||||
|
||||
type AnyTag = SNTag | SNSmartTag;
|
||||
type AnyTag = SNTag | SmartView;
|
||||
|
||||
const rootTags = (application: SNApplication): SNTag[] => {
|
||||
const hasNoParent = (tag: SNTag) => !application.getTagParent(tag);
|
||||
@@ -71,11 +72,11 @@ const isValidFutureSiblings = (
|
||||
|
||||
export class TagsState {
|
||||
tags: SNTag[] = [];
|
||||
smartTags: SNSmartTag[] = [];
|
||||
smartViews: SmartView[] = [];
|
||||
allNotesCount_ = 0;
|
||||
selected_: AnyTag | undefined;
|
||||
previouslySelected_: AnyTag | undefined;
|
||||
editing_: SNTag | undefined;
|
||||
editing_: SNTag | SmartView | undefined;
|
||||
addingSubtagTo: SNTag | undefined;
|
||||
|
||||
contextMenuOpen = false;
|
||||
@@ -100,12 +101,12 @@ export class TagsState {
|
||||
this.editing_ = undefined;
|
||||
this.addingSubtagTo = undefined;
|
||||
|
||||
this.smartTags = this.application.getSmartTags();
|
||||
this.selected_ = this.smartTags[0];
|
||||
this.smartViews = this.application.getSmartViews();
|
||||
this.selected_ = this.smartViews[0];
|
||||
|
||||
makeObservable(this, {
|
||||
tags: observable.ref,
|
||||
smartTags: observable.ref,
|
||||
smartViews: observable.ref,
|
||||
hasAtLeastOneFolder: computed,
|
||||
allNotesCount_: observable,
|
||||
allNotesCount: computed,
|
||||
@@ -144,28 +145,28 @@ export class TagsState {
|
||||
|
||||
appEventListeners.push(
|
||||
this.application.streamItems(
|
||||
[ContentType.Tag, ContentType.SmartTag],
|
||||
[ContentType.Tag, ContentType.SmartView],
|
||||
(items) => {
|
||||
runInAction(() => {
|
||||
this.tags = this.application.getDisplayableItems(
|
||||
this.tags = this.application.getDisplayableItems<SNTag>(
|
||||
ContentType.Tag
|
||||
) as SNTag[];
|
||||
this.smartTags = this.application.getSmartTags();
|
||||
);
|
||||
this.smartViews = this.application.getSmartViews();
|
||||
|
||||
const selectedTag = this.selected_;
|
||||
if (selectedTag) {
|
||||
if (selectedTag && !isSystemView(selectedTag as SmartView)) {
|
||||
const matchingTag = items.find(
|
||||
(candidate) => candidate.uuid === selectedTag.uuid
|
||||
);
|
||||
) as AnyTag;
|
||||
if (matchingTag) {
|
||||
if (matchingTag.deleted) {
|
||||
this.selected_ = this.smartTags[0];
|
||||
this.selected_ = this.smartViews[0];
|
||||
} else {
|
||||
this.selected_ = matchingTag as AnyTag;
|
||||
this.selected_ = matchingTag;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.selected_ = this.smartTags[0];
|
||||
this.selected_ = this.smartViews[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -193,7 +194,9 @@ export class TagsState {
|
||||
return;
|
||||
}
|
||||
|
||||
const createdTag = await this.application.createTagOrSmartTag(title);
|
||||
const createdTag = (await this.application.createTagOrSmartView(
|
||||
title
|
||||
)) as SNTag;
|
||||
|
||||
const futureSiblings = this.application.getTagChildren(parent);
|
||||
|
||||
@@ -294,7 +297,10 @@ export class TagsState {
|
||||
}
|
||||
|
||||
public get allLocalRootTags(): SNTag[] {
|
||||
if (this.editing_ && this.application.isTemplateItem(this.editing_)) {
|
||||
if (
|
||||
this.editing_ instanceof SNTag &&
|
||||
this.application.isTemplateItem(this.editing_)
|
||||
) {
|
||||
return [this.editing_, ...this.rootTags];
|
||||
}
|
||||
return this.rootTags;
|
||||
@@ -309,9 +315,7 @@ export class TagsState {
|
||||
return [];
|
||||
}
|
||||
|
||||
const children = this.application
|
||||
.getTagChildren(tag)
|
||||
.filter((tag) => !tag.isSmartTag);
|
||||
const children = this.application.getTagChildren(tag);
|
||||
|
||||
const childrenUuids = children.map((childTag) => childTag.uuid);
|
||||
const childrenTags = this.tags.filter((tag) =>
|
||||
@@ -414,11 +418,11 @@ export class TagsState {
|
||||
return this.selected_?.uuid;
|
||||
}
|
||||
|
||||
public get editingTag(): SNTag | undefined {
|
||||
public get editingTag(): SNTag | SmartView | undefined {
|
||||
return this.editing_;
|
||||
}
|
||||
|
||||
public set editingTag(editingTag: SNTag | undefined) {
|
||||
public set editingTag(editingTag: SNTag | SmartView | undefined) {
|
||||
this.editing_ = editingTag;
|
||||
this.selected = editingTag;
|
||||
}
|
||||
@@ -442,11 +446,11 @@ export class TagsState {
|
||||
|
||||
public undoCreateNewTag() {
|
||||
this.editing_ = undefined;
|
||||
const previousTag = this.previouslySelected_ || this.smartTags[0];
|
||||
const previousTag = this.previouslySelected_ || this.smartViews[0];
|
||||
this.selected = previousTag;
|
||||
}
|
||||
|
||||
public async remove(tag: SNTag, userTriggered: boolean) {
|
||||
public async remove(tag: SNTag | SmartView, userTriggered: boolean) {
|
||||
let shouldDelete = !userTriggered;
|
||||
if (userTriggered) {
|
||||
shouldDelete = await confirmDialog({
|
||||
@@ -456,16 +460,17 @@ export class TagsState {
|
||||
}
|
||||
if (shouldDelete) {
|
||||
this.application.deleteItem(tag);
|
||||
this.selected = this.smartTags[0];
|
||||
this.selected = this.smartViews[0];
|
||||
}
|
||||
}
|
||||
|
||||
public async save(tag: SNTag, newTitle: string) {
|
||||
public async save(tag: SNTag | SmartView, newTitle: string) {
|
||||
const hasEmptyTitle = newTitle.length === 0;
|
||||
const hasNotChangedTitle = newTitle === tag.title;
|
||||
const isTemplateChange = this.application.isTemplateItem(tag);
|
||||
|
||||
const siblings = tagSiblings(this.application, tag);
|
||||
const siblings =
|
||||
tag instanceof SNTag ? tagSiblings(this.application, tag) : [];
|
||||
const hasDuplicatedTitle = siblings.some(
|
||||
(other) => other.title.toLowerCase() === newTitle.toLowerCase()
|
||||
);
|
||||
@@ -492,16 +497,16 @@ export class TagsState {
|
||||
}
|
||||
|
||||
if (isTemplateChange) {
|
||||
const isSmartTagTitle = this.application.isSmartTagTitle(newTitle);
|
||||
const isSmartViewTitle = this.application.isSmartViewTitle(newTitle);
|
||||
|
||||
if (isSmartTagTitle) {
|
||||
if (!this.features.hasSmartTags) {
|
||||
if (isSmartViewTitle) {
|
||||
if (!this.features.hasSmartViews) {
|
||||
await this.features.showPremiumAlert(SMART_TAGS_FEATURE_NAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const insertedTag = await this.application.createTagOrSmartTag(newTitle);
|
||||
const insertedTag = await this.application.createTagOrSmartView(newTitle);
|
||||
this.application.sync();
|
||||
runInAction(() => {
|
||||
this.selected = insertedTag as SNTag;
|
||||
@@ -529,7 +534,7 @@ export class TagsState {
|
||||
|
||||
if (
|
||||
item.content_type === ContentType.Tag ||
|
||||
item.content_type === ContentType.SmartTag
|
||||
item.content_type === ContentType.SmartView
|
||||
) {
|
||||
const matchingTag = this.application.findItem(item.uuid);
|
||||
|
||||
@@ -539,7 +544,7 @@ export class TagsState {
|
||||
}
|
||||
}
|
||||
} else if (action === ComponentAction.ClearSelection) {
|
||||
this.selected = this.smartTags[0];
|
||||
this.selected = this.smartViews[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,23 +48,24 @@ export class WebApplication extends SNApplication {
|
||||
platform: Platform,
|
||||
identifier: string,
|
||||
defaultSyncServerHost: string,
|
||||
defaultFilesHostHost: string,
|
||||
public bridge: Bridge,
|
||||
webSocketUrl: string,
|
||||
runtime: Runtime
|
||||
) {
|
||||
super(
|
||||
bridge.environment,
|
||||
platform,
|
||||
deviceInterface,
|
||||
WebCrypto,
|
||||
new AlertService(),
|
||||
super({
|
||||
environment: bridge.environment,
|
||||
platform: platform,
|
||||
deviceInterface: deviceInterface,
|
||||
crypto: WebCrypto,
|
||||
alertService: new AlertService(),
|
||||
identifier,
|
||||
[],
|
||||
defaultSyncServerHost,
|
||||
bridge.appVersion,
|
||||
webSocketUrl,
|
||||
runtime
|
||||
);
|
||||
defaultHost: defaultSyncServerHost,
|
||||
defaultFilesHost: defaultFilesHostHost,
|
||||
appVersion: bridge.appVersion,
|
||||
webSocketUrl: webSocketUrl,
|
||||
runtime,
|
||||
});
|
||||
deviceInterface.setApplication(this);
|
||||
this.noteControllerGroup = new NoteGroupController(this);
|
||||
this.iconsController = new IconsController();
|
||||
|
||||
@@ -16,10 +16,12 @@ import { IOService } from '@/services/ioService';
|
||||
import { AutolockService } from '@/services/autolock_service';
|
||||
import { StatusManager } from '@/services/statusManager';
|
||||
import { ThemeManager } from '@/services/themeManager';
|
||||
import { InternalEventBus } from '@standardnotes/services';
|
||||
|
||||
export class ApplicationGroup extends SNApplicationGroup {
|
||||
constructor(
|
||||
private defaultSyncServerHost: string,
|
||||
private defaultFilesHostHost: string,
|
||||
private bridge: Bridge,
|
||||
private runtime: Runtime,
|
||||
private webSocketUrl: string
|
||||
@@ -50,6 +52,7 @@ export class ApplicationGroup extends SNApplicationGroup {
|
||||
platform,
|
||||
descriptor.identifier,
|
||||
this.defaultSyncServerHost,
|
||||
this.defaultFilesHostHost,
|
||||
this.bridge,
|
||||
this.webSocketUrl,
|
||||
this.runtime
|
||||
@@ -60,7 +63,10 @@ export class ApplicationGroup extends SNApplicationGroup {
|
||||
const io = new IOService(
|
||||
platform === Platform.MacWeb || platform === Platform.MacDesktop
|
||||
);
|
||||
const autolockService = new AutolockService(application);
|
||||
const autolockService = new AutolockService(
|
||||
application,
|
||||
new InternalEventBus()
|
||||
);
|
||||
const statusManager = new StatusManager();
|
||||
const themeService = new ThemeManager(application);
|
||||
application.setWebServices({
|
||||
|
||||
77
app/assets/javascripts/utils/calculateSubmenuStyle.tsx
Normal file
77
app/assets/javascripts/utils/calculateSubmenuStyle.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
MAX_MENU_SIZE_MULTIPLIER,
|
||||
MENU_MARGIN_FROM_APP_BORDER,
|
||||
} from '@/constants';
|
||||
|
||||
export type SubmenuStyle = {
|
||||
top?: number | 'auto';
|
||||
right?: number | 'auto';
|
||||
bottom: number | 'auto';
|
||||
left?: number | 'auto';
|
||||
visibility?: 'hidden' | 'visible';
|
||||
maxHeight: number | 'auto';
|
||||
};
|
||||
|
||||
export const calculateSubmenuStyle = (
|
||||
button: HTMLButtonElement | null,
|
||||
menu?: HTMLDivElement | null
|
||||
): SubmenuStyle | undefined => {
|
||||
const defaultFontSize = window.getComputedStyle(
|
||||
document.documentElement
|
||||
).fontSize;
|
||||
const maxChangeEditorMenuSize =
|
||||
parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER;
|
||||
const { clientWidth, clientHeight } = document.documentElement;
|
||||
const buttonRect = button?.getBoundingClientRect();
|
||||
const buttonParentRect = button?.parentElement?.getBoundingClientRect();
|
||||
const menuBoundingRect = menu?.getBoundingClientRect();
|
||||
const footerElementRect = document
|
||||
.getElementById('footer-bar')
|
||||
?.getBoundingClientRect();
|
||||
const footerHeightInPx = footerElementRect?.height ?? 0;
|
||||
|
||||
let position: SubmenuStyle = {
|
||||
bottom: 'auto',
|
||||
maxHeight: 'auto',
|
||||
};
|
||||
|
||||
if (buttonRect && buttonParentRect) {
|
||||
let positionBottom =
|
||||
clientHeight - buttonRect.bottom - buttonRect.height / 2;
|
||||
|
||||
if (positionBottom < footerHeightInPx) {
|
||||
positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER;
|
||||
}
|
||||
|
||||
position = {
|
||||
bottom: positionBottom,
|
||||
visibility: 'hidden',
|
||||
maxHeight: 'auto',
|
||||
};
|
||||
|
||||
if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) {
|
||||
position.right = clientWidth - buttonRect.left;
|
||||
} else {
|
||||
position.left = buttonRect.right;
|
||||
}
|
||||
}
|
||||
|
||||
if (menuBoundingRect?.height && buttonRect && position.bottom !== 'auto') {
|
||||
position.visibility = 'visible';
|
||||
|
||||
if (menuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) {
|
||||
position.bottom =
|
||||
position.bottom + menuBoundingRect.y - MENU_MARGIN_FROM_APP_BORDER * 2;
|
||||
}
|
||||
|
||||
if (footerElementRect && menuBoundingRect.height > footerElementRect.y) {
|
||||
position.bottom = footerElementRect.height + MENU_MARGIN_FROM_APP_BORDER;
|
||||
position.maxHeight =
|
||||
clientHeight -
|
||||
footerElementRect.height -
|
||||
MENU_MARGIN_FROM_APP_BORDER * 2;
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
};
|
||||
@@ -34,7 +34,7 @@ $heading-height: 75px;
|
||||
padding-bottom: 10px;
|
||||
padding-right: 14px;
|
||||
|
||||
border-bottom: none;
|
||||
border-bottom: 1px solid var(--sn-stylekit-border-color);
|
||||
z-index: $z-index-editor-title-bar;
|
||||
|
||||
height: auto;
|
||||
@@ -66,8 +66,8 @@ $heading-height: 75px;
|
||||
|
||||
#save-status-container {
|
||||
position: relative;
|
||||
min-width: 15ch;
|
||||
max-width: 15ch;
|
||||
min-width: 16ch;
|
||||
max-width: 16ch;
|
||||
overflow: visible;
|
||||
margin-right: 20px;
|
||||
}
|
||||
@@ -118,7 +118,6 @@ $heading-height: 75px;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 15px;
|
||||
padding-top: 11px;
|
||||
font-size: var(--sn-stylekit-font-size-editor);
|
||||
resize: none;
|
||||
}
|
||||
|
||||
@@ -32,22 +32,6 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.sn-icon {
|
||||
@extend .h-5;
|
||||
@extend .w-5;
|
||||
@extend .fill-current;
|
||||
|
||||
&.sn-icon--small {
|
||||
@extend .h-3\.5;
|
||||
@extend .w-3\.5;
|
||||
}
|
||||
|
||||
&.sn-icon--mid {
|
||||
@extend .w-4;
|
||||
@extend .h-4;
|
||||
}
|
||||
}
|
||||
|
||||
.sn-dropdown {
|
||||
@extend .bg-default;
|
||||
@extend .rounded;
|
||||
@@ -257,9 +241,6 @@
|
||||
.ml-3 {
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
.ml-4 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.mr-2\.5 {
|
||||
margin-right: 0.625rem;
|
||||
@@ -296,6 +277,10 @@
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.mt-0\.5 {
|
||||
margin-top: 0.125rem;
|
||||
}
|
||||
|
||||
.mt-2\.5 {
|
||||
margin-top: 0.625rem;
|
||||
}
|
||||
@@ -435,6 +420,10 @@
|
||||
min-height: 1.5rem;
|
||||
}
|
||||
|
||||
.min-h-16 {
|
||||
min-height: 4rem;
|
||||
}
|
||||
|
||||
.max-h-5 {
|
||||
max-height: 1.25rem;
|
||||
}
|
||||
@@ -575,10 +564,6 @@
|
||||
padding-bottom: 2.25rem;
|
||||
}
|
||||
|
||||
.select-none {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.placeholder-dark-red::placeholder {
|
||||
@extend .color-dark-red;
|
||||
}
|
||||
@@ -711,11 +696,6 @@
|
||||
background: var(--sn-stylekit-grey-4);
|
||||
}
|
||||
|
||||
.sn-component .spinner-info {
|
||||
border-color: var(--sn-stylekit-info-color);
|
||||
border-right-color: transparent;
|
||||
}
|
||||
|
||||
@keyframes slide-up {
|
||||
0% {
|
||||
opacity: 1;
|
||||
@@ -899,10 +879,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.leading-140\% {
|
||||
line-height: 140%;
|
||||
}
|
||||
@@ -913,10 +889,6 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.last\:hidden:last-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -210,10 +210,6 @@ $screen-md-max: ($screen-lg-min - 1) !default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.fill-current {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.font-editor {
|
||||
font-family: var(--sn-stylekit-editor-font-family);
|
||||
}
|
||||
|
||||
@@ -31,13 +31,14 @@
|
||||
<meta name="og:description" content="Standard Notes is an easy-to-use encrypted note-taking app for digitalists and professionals. Capture your notes, documents, and life's work all in one place."/>
|
||||
|
||||
<script>
|
||||
window._default_sync_server = "<%= ENV['DEFAULT_SYNC_SERVER'] %>";
|
||||
window._bugsnag_api_key = "<%= ENV['BUGSNAG_API_KEY'] %>";
|
||||
window._enable_unfinished_features = "<%= ENV['ENABLE_UNFINISHED_FEATURES'] %>" === 'true';
|
||||
window._websocket_url = "<%= ENV['WEBSOCKET_URL'] %>";
|
||||
window._purchase_url = "<%= ENV['PURCHASE_URL'] %>";
|
||||
window._plans_url = "<%= ENV['PLANS_URL'] %>";
|
||||
window._dashboard_url = "<%= ENV['DASHBOARD_URL'] %>";
|
||||
window.defaultSyncServer = "<%= ENV['DEFAULT_SYNC_SERVER'] %>";
|
||||
window.defaultFilesHost = "<%= ENV['DEFAULT_FILES_HOST'] %>";
|
||||
window.bugsnagApiKey = "<%= ENV['BUGSNAG_API_KEY'] %>";
|
||||
window.enabledUnfinishedFeatures = "<%= ENV['ENABLE_UNFINISHED_FEATURES'] %>" === 'true';
|
||||
window.websocketUrl = "<%= ENV['WEBSOCKET_URL'] %>";
|
||||
window.purchaseUrl = "<%= ENV['PURCHASE_URL'] %>";
|
||||
window.plansUrl = "<%= ENV['PLANS_URL'] %>";
|
||||
window.dashboardUrl = "<%= ENV['DASHBOARD_URL'] %>";
|
||||
</script>
|
||||
|
||||
<% if Rails.env.development? %>
|
||||
|
||||
28
index.html
28
index.html
@@ -29,10 +29,11 @@
|
||||
</head>
|
||||
|
||||
<body
|
||||
data-default-sync-server="<%= env.DEV_DEFAULT_SYNC_SERVER %>"
|
||||
data-bugsnag-api-key="<%= env.DEV_BUGSNAG_API_KEY %>"
|
||||
data-default-sync-server="<%= env.DEFAULT_SYNC_SERVER %>"
|
||||
data-default-files-host="<%= env.DEFAULT_FILES_HOST %>"
|
||||
data-bugsnag-api-key="<%= env.BUGSNAG_API_KEY %>"
|
||||
data-enable-unfinished-features="<%= env.ENABLE_UNFINISHED_FEATURES %>"
|
||||
data-web-socket-url="<%= env.DEV_WEBSOCKET_URL %>"
|
||||
data-web-socket-url="<%= env.WEBSOCKET_URL %>"
|
||||
data-purchase-url="<%= env.PURCHASE_URL %>"
|
||||
data-plans-url="<%= env.PLANS_URL %>"
|
||||
data-dashboard-url="<%= env.DASHBOARD_URL %>"
|
||||
@@ -41,16 +42,17 @@
|
||||
data-dev-account-server="<%= env.DEV_ACCOUNT_SERVER %>"
|
||||
>
|
||||
<script>
|
||||
window._default_sync_server = document.body.dataset.defaultSyncServer || "https://api.standardnotes.com";
|
||||
window._bugsnag_api_key = document.body.dataset.bugsnagApiKey;
|
||||
window._enable_unfinished_features = document.body.dataset.enableUnfinishedFeatures === 'true';
|
||||
window._websocket_url = document.body.dataset.webSocketUrl;
|
||||
window._purchase_url = document.body.dataset.purchaseUrl;
|
||||
window._plans_url = document.body.dataset.plansUrl;
|
||||
window._dashboard_url = document.body.dataset.dashboardUrl;
|
||||
window._devAccountEmail = document.body.dataset.devAccountEmail;
|
||||
window._devAccountPassword = document.body.dataset.devAccountPassword;
|
||||
window._devAccountServer = document.body.dataset.devAccountServer;
|
||||
window.defaultSyncServer = document.body.dataset.defaultSyncServer || "https://api.standardnotes.com";
|
||||
window.defaultFilesHost = document.body.dataset.defaultFilesHost;
|
||||
window.bugsnagApiKey = document.body.dataset.bugsnagApiKey;
|
||||
window.enabledUnfinishedFeatures = document.body.dataset.enableUnfinishedFeatures === 'true';
|
||||
window.websocketUrl = document.body.dataset.webSocketUrl;
|
||||
window.purchaseUrl = document.body.dataset.purchaseUrl;
|
||||
window.plansUrl = document.body.dataset.plansUrl;
|
||||
window.dashboardUrl = document.body.dataset.dashboardUrl;
|
||||
window.devAccountEmail = document.body.dataset.devAccountEmail;
|
||||
window.devAccountPassword = document.body.dataset.devAccountPassword;
|
||||
window.devAccountServer = document.body.dataset.devAccountServer;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
38
package.json
38
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "standard-notes-web",
|
||||
"version": "3.11.2",
|
||||
"version": "3.12.0",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -27,12 +27,15 @@
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
"@reach/disclosure": "^0.16.2",
|
||||
"@reach/visually-hidden": "^0.16.0",
|
||||
"@standardnotes/responses": "^1.1.5",
|
||||
"@standardnotes/services": "^1.4.0",
|
||||
"@standardnotes/stylekit": "5.14.0",
|
||||
"@svgr/webpack": "^6.2.1",
|
||||
"@types/jest": "^27.4.0",
|
||||
"@types/lodash": "^4.14.178",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/react": "^17.0.39",
|
||||
"@typescript-eslint/eslint-plugin": "^5.12.1",
|
||||
"@typescript-eslint/parser": "^5.12.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||
"@typescript-eslint/parser": "^5.13.0",
|
||||
"apply-loader": "^2.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.3",
|
||||
@@ -40,9 +43,9 @@
|
||||
"copy-webpack-plugin": "^10.2.4",
|
||||
"css-loader": "^6.6.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.9.0",
|
||||
"eslint-config-prettier": "^8.4.0",
|
||||
"eslint-plugin-react": "^7.28.0",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-react": "^7.29.2",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
@@ -57,13 +60,12 @@
|
||||
"pretty-quick": "^3.1.3",
|
||||
"sass-loader": "^12.6.0",
|
||||
"serve-static": "^1.14.2",
|
||||
"@standardnotes/stylekit": "5.9.0",
|
||||
"svg-jest": "^1.0.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript": "4.5.5",
|
||||
"ts-loader": "^9.2.7",
|
||||
"typescript": "4.6.2",
|
||||
"typescript-eslint": "0.0.1-alpha.0",
|
||||
"webpack": "^5.69.1",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.7.4",
|
||||
"webpack-merge": "^5.8.0"
|
||||
@@ -76,12 +78,12 @@
|
||||
"@reach/dialog": "^0.16.2",
|
||||
"@reach/listbox": "^0.16.2",
|
||||
"@reach/tooltip": "^0.16.2",
|
||||
"@standardnotes/components": "1.7.5",
|
||||
"@standardnotes/features": "1.32.11",
|
||||
"@standardnotes/snjs": "2.63.1",
|
||||
"@standardnotes/settings": "^1.11.3",
|
||||
"@standardnotes/sncrypto-web": "1.7.0",
|
||||
"mobx": "^6.4.1",
|
||||
"@standardnotes/components": "1.7.8",
|
||||
"@standardnotes/features": "1.34.0",
|
||||
"@standardnotes/settings": "^1.11.5",
|
||||
"@standardnotes/sncrypto-web": "1.7.3",
|
||||
"@standardnotes/snjs": "2.72.0",
|
||||
"mobx": "^6.4.2",
|
||||
"mobx-react-lite": "^3.3.0",
|
||||
"preact": "^10.6.6",
|
||||
"qrcode.react": "^1.0.1",
|
||||
|
||||
525
yarn.lock
525
yarn.lock
@@ -1804,10 +1804,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3"
|
||||
integrity sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==
|
||||
|
||||
"@eslint/eslintrc@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3"
|
||||
integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==
|
||||
"@eslint/eslintrc@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a"
|
||||
integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
@@ -2052,6 +2052,11 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@nanostores/preact@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@nanostores/preact/-/preact-0.1.3.tgz#aeac0a1d8de1e067bc0b156c1fdd62a6b7bf6069"
|
||||
integrity sha512-uiX1ned0LrzASot+sPUjyJzr8Js3pX075omazgsSdLf0zPp4ss8xwTiuNh5FSKigTSQEVqZFiS+W8CnHIrX62A==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
|
||||
@@ -2111,14 +2116,6 @@
|
||||
prop-types "^15.7.2"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/auto-id@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.15.2.tgz#289640b47545a32f3621469ba497ba5c040b349c"
|
||||
integrity sha512-K7d5qhYBlBHIjy+IpSEAyMeB5VTZ9m0tZdr7xyNd5Fr6oeefHEvJiJGuQpubP5bDoe7ShC3y0VQGFmT0g7KcZg==
|
||||
dependencies:
|
||||
"@reach/utils" "0.15.2"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/auto-id@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.16.0.tgz#dfabc3227844e8c04f8e6e45203a8e14a8edbaed"
|
||||
@@ -2139,14 +2136,6 @@
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/descendants@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.15.2.tgz#b0641f0bc864d91271364678dea51cf86b2e5c66"
|
||||
integrity sha512-GdQXWVpscss89MOhWh+sL4TnIn0qX1y+Te3wE72aKQrz/QCR69JFEW4wftovmF7rFm4/kDZcp14lMy512U6VlA==
|
||||
dependencies:
|
||||
"@reach/utils" "0.15.2"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/descendants@0.16.1":
|
||||
version "0.16.1"
|
||||
resolved "https://registry.yarnpkg.com/@reach/descendants/-/descendants-0.16.1.tgz#fa3d89c0503565369707f32985d87eef61985d9f"
|
||||
@@ -2178,17 +2167,16 @@
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/listbox@^0.15.0":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/listbox/-/listbox-0.15.2.tgz#21aacc5340deb1b819d522f7f7fd4caac093c8a4"
|
||||
integrity sha512-bXXelcm+PvAWAmhHQEaEVU6IQvTieIdoYcIrs5JsKzH98M+pp940Gdm0d2uDcmFatx/I9OMTAsOTJ129RPECrA==
|
||||
"@reach/dropdown@0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/dropdown/-/dropdown-0.16.2.tgz#4aa7df0f716cb448d01bc020d54df595303d5fa6"
|
||||
integrity sha512-l4nNiX6iUpMdHQNbZMhgW5APtw0AUwJuRnkqE93vkjvdtrYl/sNJy1Jr6cGG7TrZIABLSOsfwbXU3C+qwJ3ftQ==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.15.2"
|
||||
"@reach/descendants" "0.15.2"
|
||||
"@reach/machine" "0.15.2"
|
||||
"@reach/popover" "0.15.2"
|
||||
"@reach/utils" "0.15.2"
|
||||
prop-types "^15.7.2"
|
||||
"@reach/auto-id" "0.16.0"
|
||||
"@reach/descendants" "0.16.1"
|
||||
"@reach/popover" "0.16.2"
|
||||
"@reach/utils" "0.16.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/listbox@^0.16.2":
|
||||
version "0.16.2"
|
||||
@@ -2202,15 +2190,6 @@
|
||||
"@reach/utils" "0.16.0"
|
||||
prop-types "^15.7.2"
|
||||
|
||||
"@reach/machine@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/machine/-/machine-0.15.2.tgz#f1558e63a6b304e6cc12feefb0d0dd315b32c962"
|
||||
integrity sha512-op8Duhp6rNCReZgdVScbIzoXMPFYP4nje6dvg4g2GKo8hUkyQpebsUFnUNNNv6NWdbmhIRiKHFlTgSl2gIlh5Q==
|
||||
dependencies:
|
||||
"@reach/utils" "0.15.2"
|
||||
"@xstate/fsm" "1.4.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/machine@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/machine/-/machine-0.16.0.tgz#0504ba47ac09ed495bd341bf5fdd6625bcade0e3"
|
||||
@@ -2220,15 +2199,14 @@
|
||||
"@xstate/fsm" "1.4.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/menu-button@^0.15.1":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.15.2.tgz#00f91402be3ff23d3b4cfe377529f4f9e82a78fe"
|
||||
integrity sha512-slEji1AnfnH134YDZSTwst4nZHYNrfyg9GF+A8p1+kGc8N3JsPysHc7uIUZ/IsK+PdaOCB+r9kuL1QWBgNO+jw==
|
||||
"@reach/menu-button@^0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/menu-button/-/menu-button-0.16.2.tgz#664e33e70de431f88abf1f8537c48b1b6ce87e88"
|
||||
integrity sha512-p4n6tFVaJZHJZEznHWy0YH2Xr3I+W7tsQWAT72PqKGT+uryGRdtgEQqi76f/8cRaw/00ueazBk5lwLG7UKGFaA==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.15.2"
|
||||
"@reach/descendants" "0.15.2"
|
||||
"@reach/popover" "0.15.2"
|
||||
"@reach/utils" "0.15.2"
|
||||
"@reach/dropdown" "0.16.2"
|
||||
"@reach/popover" "0.16.2"
|
||||
"@reach/utils" "0.16.0"
|
||||
prop-types "^15.7.2"
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
@@ -2238,17 +2216,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2"
|
||||
integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==
|
||||
|
||||
"@reach/popover@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.15.2.tgz#e310e2afe82afa35929354f1fd1a747cdebb7654"
|
||||
integrity sha512-92Ov7VPXjn4ciOVupeekki03lSMz9NAmw2BjWYE9mVvYWKyDx5jx2srtbkIqUaSCkAVV3KEsFUia8aMm60FDZg==
|
||||
dependencies:
|
||||
"@reach/portal" "0.15.2"
|
||||
"@reach/rect" "0.15.2"
|
||||
"@reach/utils" "0.15.2"
|
||||
tabbable "^4.0.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/popover@0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/popover/-/popover-0.16.2.tgz#71d7af3002ca49d791476b22dee1840dd1719c19"
|
||||
@@ -2260,14 +2227,6 @@
|
||||
tabbable "^4.0.0"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/portal@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.15.2.tgz#fe7aa3d9a475ec07686c39bab3a0d85093fa91fb"
|
||||
integrity sha512-5x+dchGr4btRnLazwmyCYbSPVJAIrw0eXwhz7Vj9uT/EIp43WzOtTcODdLOoH6Ol2QLjX1Yt/fBjdK9+UAKxSA==
|
||||
dependencies:
|
||||
"@reach/utils" "0.15.2"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/portal@0.16.2":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.16.2.tgz#ca83696215ee03acc2bb25a5ae5d8793eaaf2f64"
|
||||
@@ -2277,17 +2236,6 @@
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/rect@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.15.2.tgz#734e3f17a499d6e22bd2ea95856c801c41ed66fd"
|
||||
integrity sha512-S2lzvvfclUHdvgcfW/eoz0i729HJvG5f6ayVaXcKz+X6LKF9i9Jdhfwsz7b3UmnSCihKNs0cX5tyWfWr1E1JFw==
|
||||
dependencies:
|
||||
"@reach/observe-rect" "1.2.0"
|
||||
"@reach/utils" "0.15.2"
|
||||
prop-types "^15.7.2"
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/rect@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.16.0.tgz#78cf6acefe2e83d3957fa84f938f6e1fc5700f16"
|
||||
@@ -2313,14 +2261,6 @@
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/utils@0.15.2":
|
||||
version "0.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.15.2.tgz#a63a761eb36266bf33d65cb91520dd85a04ae116"
|
||||
integrity sha512-Lr1SJ5X4hEjD/M0TAonURM8wytM/JuPSuIP7t+e5cil34pThyLsBvTGeNfmpSgaLJ5vlsv0x9u6g4SRAEr84Og==
|
||||
dependencies:
|
||||
tiny-warning "^1.0.3"
|
||||
tslib "^2.3.0"
|
||||
|
||||
"@reach/utils@0.16.0":
|
||||
version "0.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.16.0.tgz#5b0777cf16a7cab1ddd4728d5d02762df0ba84ce"
|
||||
@@ -2366,99 +2306,133 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@standardnotes/auth@^3.16.4":
|
||||
version "3.16.4"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.16.4.tgz#6293bd67cdc4055229f1d520b6f44b39c6053a7a"
|
||||
integrity sha512-2tHsDnwQgGD3pOzKuSjo4yj8hLjATb70jzFnEWoEpyCdHTuGys9qSBElfi672hU4vg+/nXaHpdVUuD5DPzLaXg==
|
||||
"@standardnotes/applications@^1.1.3":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/applications/-/applications-1.1.3.tgz#7f19ab3e1a5d7754e18be9b6b37ed66cbacdbd05"
|
||||
integrity sha512-B5kJ9S9F7ikGl+KHWgokbBYGwB15XWQSlwpxCw0IAseZuf/b2J8PAS1oeNhRNK73nvXercrQE15X42ORbjSb1Q==
|
||||
dependencies:
|
||||
"@standardnotes/common" "^1.14.0"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
|
||||
"@standardnotes/auth@^3.17.3":
|
||||
version "3.17.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-3.17.3.tgz#a00f10faa0fb2a7dd76509d3b678f85818aad63c"
|
||||
integrity sha512-tb5ylXuDBPhgeZZynNsMk83N74NMMV9z6M9hyrwuK5HbKWM5r5L9U8lwFawG8flqTKpYzPeWxmaRFZT/5qR22Q==
|
||||
dependencies:
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
jsonwebtoken "^8.5.1"
|
||||
|
||||
"@standardnotes/common@^1.14.0":
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.14.0.tgz#c3b8e06fb8120524da8d135f2dc594998e5a5c3a"
|
||||
integrity sha512-QA8JhWty7y/N62jdLyWuXzsVvDDeFwcQAH/DB/g5Mmaqlz9VlKcsbRmVl4wHLG3ur6n5Qj68aOhzCQd0p7f/WA==
|
||||
"@standardnotes/common@^1.15.3":
|
||||
version "1.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/common/-/common-1.15.3.tgz#0b8ce48b81b260abe2d405431fb04aacb44b5a01"
|
||||
integrity sha512-9oh/W3sFQYyA5Vabcbu6BUkLVkFq/25Q5EK9KCd4aT9QnDJ9JQlTtzDmTk1jYuM6rnccsJ6SW2pcWjbi9FVniw==
|
||||
|
||||
"@standardnotes/components@1.7.5":
|
||||
version "1.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.5.tgz#2f199350779a8f99e9e536223d318b822bdf369f"
|
||||
integrity sha512-7nyrrcgPAkCf6pjbAIO8qOM+22KQU0jMCIDX3b4GAS1jXM7DJDy5Frnk3oMHd9NeFhnbf0TQH4Nz4uEeid6/HA==
|
||||
"@standardnotes/components@1.7.8":
|
||||
version "1.7.8"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.8.tgz#2717f54afe013b8b8ca66a8f5197a753d0570d6e"
|
||||
integrity sha512-6xaUFMvzpisTASmEFKt88QtXIisWxNuZYpOZ2niE4KWTfiknjdMR3m5MSNG6FVI5jbKwaJENkeXVRuKCoIpeIA==
|
||||
|
||||
"@standardnotes/domain-events@^2.23.14":
|
||||
version "2.23.14"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.14.tgz#733e340c6d42935c90858380d7721150d1804574"
|
||||
integrity sha512-DRPD0lGdVn/tbVyl97QGyyAcdUZd4qsETICCO882mG33HBN8Yc7st176U+izu3T5W3dlnTqE+MJUASj3UxVCvw==
|
||||
"@standardnotes/domain-events@^2.23.20":
|
||||
version "2.23.20"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.20.tgz#8ba0fe7a4f13d91ecf37af6478b5c782e09d2b2c"
|
||||
integrity sha512-ZIQ/+mZ+II/T8rjgliBhKAuZ4Z2IpAkNIj7GZtcs830tgc5wg9cC92P7aYnLEDzH2J1KCm+UTndEi8fE+fOWyg==
|
||||
dependencies:
|
||||
"@standardnotes/auth" "^3.16.4"
|
||||
"@standardnotes/features" "^1.32.11"
|
||||
"@standardnotes/auth" "^3.17.3"
|
||||
"@standardnotes/features" "^1.34.0"
|
||||
|
||||
"@standardnotes/features@1.32.11", "@standardnotes/features@^1.32.11":
|
||||
version "1.32.11"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.32.11.tgz#43417e541bdf0ce8a10dfd68e8073fc1338f1888"
|
||||
integrity sha512-ZheQibMz4t2A6LKWcTDDGc5760AnPLFnHFwsSp0O8YydI3yz+qjm3pFF8XNeAEwgSvOX1W1nlX3E/X5tCp5LgQ==
|
||||
"@standardnotes/features@1.34.0", "@standardnotes/features@^1.34.0":
|
||||
version "1.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.34.0.tgz#88a48a4b70d2894b459dadc3f01db912afc7ffdb"
|
||||
integrity sha512-ipmrCNGsy3zyJRgfTfiN9U1RN1vnzsHXftbhhRECXvYuq+QXyeytJrxCw6SSpZpW/DNOjV6jeIaX8WmaIQfvdA==
|
||||
dependencies:
|
||||
"@standardnotes/auth" "^3.16.4"
|
||||
"@standardnotes/common" "^1.14.0"
|
||||
"@standardnotes/auth" "^3.17.3"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
|
||||
"@standardnotes/services@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.1.0.tgz#42f743f58fb4ab85627368ae6bcdf513079ef708"
|
||||
integrity sha512-r4lqUO30iHmjWodUTv+2D8xeCgpYFvJrNzR/pBIlZsAKMSjskxPyIUvBdQvHWs0o4vjf7ZedhpEwi68XwUqO3w==
|
||||
"@standardnotes/payloads@^1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.3.0.tgz#0db372b21069ae5168cfcd1d6dc55bcb3247fb6b"
|
||||
integrity sha512-2NUP22oevR2sBQ6blukLZCOkBt/3PoGh+x7nuCt6hdc2OfngcxtKmZ0XEscT1Pq5sAdXxLL4LrQzd0VLH1M0ZQ==
|
||||
dependencies:
|
||||
"@standardnotes/common" "^1.14.0"
|
||||
"@standardnotes/utils" "^1.1.1"
|
||||
"@standardnotes/applications" "^1.1.3"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
"@standardnotes/features" "^1.34.0"
|
||||
"@standardnotes/utils" "^1.2.3"
|
||||
|
||||
"@standardnotes/settings@^1.11.3":
|
||||
version "1.11.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.11.3.tgz#f7735da40807dab6eaf81cc82d8d30f5461d26d5"
|
||||
integrity sha512-95nqPYIZt57HMrymf4FTMDHOibM13AmV/8JEj7mPbIqcNKvVD486BURsaqpoBgkqB4Q43LbT8dfTrBPDgmIdxg==
|
||||
|
||||
"@standardnotes/sncrypto-common@^1.7.0":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.7.0.tgz#6ad96afeaa031c26e45cbaf527bb511b803f998d"
|
||||
integrity sha512-Dke13reJMLQFXa7y9EqZYEeZG5Ouy+32qWEsQISLjLRPrTuNwyNXee2mdPh6c9uNZxOQwrdHxVGfqzJ2iy3RpQ==
|
||||
|
||||
"@standardnotes/sncrypto-web@1.7.0":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.7.0.tgz#e3a6e69019210f375ccf8b9abb789c7dd7147cf6"
|
||||
integrity sha512-7NM1QJjtdvmUlBeQLjZukg5LovKKhoM8oX/FLOnBgl04TqDSGtvx+HDncm+laCnHZkAJ6VCSmUUxgfs1sQzyPw==
|
||||
"@standardnotes/responses@^1.1.5":
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.1.5.tgz#565f8ae7cae95fab539904df8e56fd80dcf961d9"
|
||||
integrity sha512-bk55ByUL07s92L38v4POfLKKBfCdxw/3dzHBRzF3FqDTH2bMOk4+qduqsTmdGDB4N9SuqZkv5/aMuZOw8PF6eA==
|
||||
dependencies:
|
||||
"@standardnotes/sncrypto-common" "^1.7.0"
|
||||
"@standardnotes/auth" "^3.17.3"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
"@standardnotes/features" "^1.34.0"
|
||||
"@standardnotes/payloads" "^1.3.0"
|
||||
|
||||
"@standardnotes/services@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.4.0.tgz#776ee5d022e4512844af1a284a2e90f599217218"
|
||||
integrity sha512-wO0LQ+qMG0bfH0HNPulsO8nZ2Z1Y84NLP0fZdMdtqiuaCi1GrM/PUlcL/fpXCJKNeTKoYa8Dh4PfF8DOjalKXg==
|
||||
dependencies:
|
||||
"@standardnotes/applications" "^1.1.3"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
"@standardnotes/utils" "^1.2.3"
|
||||
|
||||
"@standardnotes/settings@^1.11.5":
|
||||
version "1.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.11.5.tgz#792bf3e0505065486f521b2f19c2bf1081b8fa5e"
|
||||
integrity sha512-n6StAS3nBgs7Lia5mOt3+H4Xd6hatCcHFx83paFq9kdI1cKbqn7oFF4g/rUbWPy4nsx+96zBehB6EhsJ2MGzyQ==
|
||||
|
||||
"@standardnotes/sncrypto-common@^1.7.3":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.7.3.tgz#1e62a14800393be44cdb376d1d72fbc064334fc1"
|
||||
integrity sha512-twwYeBL+COkNF9IUM5bWrLZ4gXjg41tRxBMR3r3JcbrkyYjcNqVHf9L+YdBcndjSV3/9xwWl2pYWK1RB3UR2Xg==
|
||||
|
||||
"@standardnotes/sncrypto-web@1.7.3":
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-web/-/sncrypto-web-1.7.3.tgz#4fadaa8d41f301a5077db7a539c770db1cca9413"
|
||||
integrity sha512-eudCOPQvuhEXUreBz8I+zN8NKNDkLZ1goxbi5nDC7THz+iGPxLFpYhhe9RzacA1oPjOQrBnkrWlByQD13XkvrA==
|
||||
dependencies:
|
||||
"@standardnotes/sncrypto-common" "^1.7.3"
|
||||
buffer "^6.0.3"
|
||||
libsodium-wrappers "^0.7.9"
|
||||
|
||||
"@standardnotes/snjs@2.63.1":
|
||||
version "2.63.1"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.63.1.tgz#0759be39e77304fcca11ea902aa9be7bb737e756"
|
||||
integrity sha512-d32CE7/yS+qEGlOfHTDc0NPzCFXPaK2zxlCi/j68R9lT/3LuV/uc1o9eNK9a5Fgcbtbk55vbW0rUYjQQVwUF8A==
|
||||
"@standardnotes/snjs@2.72.0":
|
||||
version "2.72.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.72.0.tgz#bf807b94a326e0d33acc15fe418f727f49737935"
|
||||
integrity sha512-MIpfeZgJ/AHeHfNDGsG1te9SjmMAugOK1HFp8pY/LyEUw4uQJSKbPpwM6q81ExUPROFy3KbE4mn9IN2Kk/5c0A==
|
||||
dependencies:
|
||||
"@standardnotes/auth" "^3.16.4"
|
||||
"@standardnotes/common" "^1.14.0"
|
||||
"@standardnotes/domain-events" "^2.23.14"
|
||||
"@standardnotes/features" "^1.32.11"
|
||||
"@standardnotes/services" "^1.1.0"
|
||||
"@standardnotes/settings" "^1.11.3"
|
||||
"@standardnotes/sncrypto-common" "^1.7.0"
|
||||
"@standardnotes/utils" "^1.1.1"
|
||||
"@standardnotes/applications" "^1.1.3"
|
||||
"@standardnotes/auth" "^3.17.3"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
"@standardnotes/domain-events" "^2.23.20"
|
||||
"@standardnotes/features" "^1.34.0"
|
||||
"@standardnotes/payloads" "^1.3.0"
|
||||
"@standardnotes/responses" "^1.1.5"
|
||||
"@standardnotes/services" "^1.4.0"
|
||||
"@standardnotes/settings" "^1.11.5"
|
||||
"@standardnotes/sncrypto-common" "^1.7.3"
|
||||
"@standardnotes/utils" "^1.2.3"
|
||||
|
||||
"@standardnotes/stylekit@5.9.0":
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.9.0.tgz#16d62623335091062238c850a930dedaa5ad6f1d"
|
||||
integrity sha512-lIlEKwxKkQT+AttSmN40zvzWzfqpfI4VPTscZvRnWRqMQjYDEnSbcA1h0UDcT5tvnrna4RtsOiUL9o0KDx56sg==
|
||||
"@standardnotes/stylekit@5.14.0":
|
||||
version "5.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/stylekit/-/stylekit-5.14.0.tgz#806b7d896fb94de8be72e762dd205beefff05fd7"
|
||||
integrity sha512-zCB8QFPUTe+063RsLNCudkP6FY6ujKC3iE2pD6ak4htpXtW6DndwYbhEffuiWIjbRzDGAy0YyQ7y8V19Jw7ElQ==
|
||||
dependencies:
|
||||
"@reach/listbox" "^0.15.0"
|
||||
"@reach/menu-button" "^0.15.1"
|
||||
"@nanostores/preact" "^0.1.3"
|
||||
"@reach/listbox" "^0.16.2"
|
||||
"@reach/menu-button" "^0.16.2"
|
||||
"@svgr/webpack" "^6.2.1"
|
||||
prop-types "^15.7.2"
|
||||
nanoid "^3.3.1"
|
||||
nanostores "^0.5.10"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
"@standardnotes/utils@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.1.1.tgz#a936edd328b4e10b43b11ffc8b1626a499fa6659"
|
||||
integrity sha512-LaB1Y4arvwuABT0fybJ9At6pPEAwsDooaldYPuvqyfQAWdeqRCBMHxRDCX6yunrrwBwk7UoTie9MRw6DF1igwg==
|
||||
"@standardnotes/utils@^1.2.3":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@standardnotes/utils/-/utils-1.2.3.tgz#2ff61f3214645c84dd6603858feb964db31cb19f"
|
||||
integrity sha512-0/pSx+kJKRBdQ56oPPFRcMXBvTm/U4/zEE4Kqyx2vlm3EL0tXv4UKNuPSDbsbI5yUn8KpVSZ6LS4LZhhMU4IUA==
|
||||
dependencies:
|
||||
"@standardnotes/common" "^1.14.0"
|
||||
dompurify "^2.3.4"
|
||||
lodash "^4.17.19"
|
||||
"@standardnotes/common" "^1.15.3"
|
||||
dompurify "^2.3.6"
|
||||
lodash "^4.17.21"
|
||||
|
||||
"@svgr/babel-plugin-add-jsx-attribute@^6.0.0":
|
||||
version "6.0.0"
|
||||
@@ -2720,12 +2694,12 @@
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report" "*"
|
||||
|
||||
"@types/jest@^27.4.0":
|
||||
version "27.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed"
|
||||
integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ==
|
||||
"@types/jest@^27.4.1":
|
||||
version "27.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.1.tgz#185cbe2926eaaf9662d340cc02e548ce9e11ab6d"
|
||||
integrity sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==
|
||||
dependencies:
|
||||
jest-diff "^27.0.0"
|
||||
jest-matcher-utils "^27.0.0"
|
||||
pretty-format "^27.0.0"
|
||||
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
|
||||
@@ -2738,10 +2712,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
|
||||
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
|
||||
|
||||
"@types/lodash@^4.14.178":
|
||||
version "4.14.178"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8"
|
||||
integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==
|
||||
"@types/lodash@^4.14.179":
|
||||
version "4.14.179"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5"
|
||||
integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.2"
|
||||
@@ -2858,14 +2832,14 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.12.1.tgz#b2cd3e288f250ce8332d5035a2ff65aba3374ac4"
|
||||
integrity sha512-M499lqa8rnNK7mUv74lSFFttuUsubIRdAbHcVaP93oFcKkEmHmLqy2n7jM9C8DVmFMYK61ExrZU6dLYhQZmUpw==
|
||||
"@typescript-eslint/eslint-plugin@^5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.13.0.tgz#2809052b85911ced9c54a60dac10e515e9114497"
|
||||
integrity sha512-vLktb2Uec81fxm/cfz2Hd6QaWOs8qdmVAZXLdOBX6JFJDhf6oDZpMzZ4/LZ6SFM/5DgDcxIMIvy3F+O9yZBuiQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.12.1"
|
||||
"@typescript-eslint/type-utils" "5.12.1"
|
||||
"@typescript-eslint/utils" "5.12.1"
|
||||
"@typescript-eslint/scope-manager" "5.13.0"
|
||||
"@typescript-eslint/type-utils" "5.13.0"
|
||||
"@typescript-eslint/utils" "5.13.0"
|
||||
debug "^4.3.2"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
ignore "^5.1.8"
|
||||
@@ -2873,69 +2847,69 @@
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.12.1.tgz#b090289b553b8aa0899740d799d0f96e6f49771b"
|
||||
integrity sha512-6LuVUbe7oSdHxUWoX/m40Ni8gsZMKCi31rlawBHt7VtW15iHzjbpj2WLiToG2758KjtCCiLRKZqfrOdl3cNKuw==
|
||||
"@typescript-eslint/parser@^5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.13.0.tgz#0394ed8f2f849273c0bf4b811994d177112ced5c"
|
||||
integrity sha512-GdrU4GvBE29tm2RqWOM0P5QfCtgCyN4hXICj/X9ibKED16136l9ZpoJvCL5pSKtmJzA+NRDzQ312wWMejCVVfg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.12.1"
|
||||
"@typescript-eslint/types" "5.12.1"
|
||||
"@typescript-eslint/typescript-estree" "5.12.1"
|
||||
"@typescript-eslint/scope-manager" "5.13.0"
|
||||
"@typescript-eslint/types" "5.13.0"
|
||||
"@typescript-eslint/typescript-estree" "5.13.0"
|
||||
debug "^4.3.2"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.12.1.tgz#58734fd45d2d1dec49641aacc075fba5f0968817"
|
||||
integrity sha512-J0Wrh5xS6XNkd4TkOosxdpObzlYfXjAFIm9QxYLCPOcHVv1FyyFCPom66uIh8uBr0sZCrtS+n19tzufhwab8ZQ==
|
||||
"@typescript-eslint/scope-manager@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.13.0.tgz#cf6aff61ca497cb19f0397eea8444a58f46156b6"
|
||||
integrity sha512-T4N8UvKYDSfVYdmJq7g2IPJYCRzwtp74KyDZytkR4OL3NRupvswvmJQJ4CX5tDSurW2cvCc1Ia1qM7d0jpa7IA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.12.1"
|
||||
"@typescript-eslint/visitor-keys" "5.12.1"
|
||||
"@typescript-eslint/types" "5.13.0"
|
||||
"@typescript-eslint/visitor-keys" "5.13.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.12.1.tgz#8d58c6a0bb176b5e9a91581cda1a7f91a114d3f0"
|
||||
integrity sha512-Gh8feEhsNLeCz6aYqynh61Vsdy+tiNNkQtc+bN3IvQvRqHkXGUhYkUi+ePKzP0Mb42se7FDb+y2SypTbpbR/Sg==
|
||||
"@typescript-eslint/type-utils@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.13.0.tgz#b0efd45c85b7bab1125c97b752cab3a86c7b615d"
|
||||
integrity sha512-/nz7qFizaBM1SuqAKb7GLkcNn2buRdDgZraXlkhz+vUGiN1NZ9LzkA595tHHeduAiS2MsHqMNhE2zNzGdw43Yg==
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "5.12.1"
|
||||
"@typescript-eslint/utils" "5.13.0"
|
||||
debug "^4.3.2"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.12.1.tgz#46a36a28ff4d946821b58fe5a73c81dc2e12aa89"
|
||||
integrity sha512-hfcbq4qVOHV1YRdhkDldhV9NpmmAu2vp6wuFODL71Y0Ixak+FLeEU4rnPxgmZMnGreGEghlEucs9UZn5KOfHJA==
|
||||
"@typescript-eslint/types@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.13.0.tgz#da1de4ae905b1b9ff682cab0bed6b2e3be9c04e5"
|
||||
integrity sha512-LmE/KO6DUy0nFY/OoQU0XelnmDt+V8lPQhh8MOVa7Y5k2gGRd6U9Kp3wAjhB4OHg57tUO0nOnwYQhRRyEAyOyg==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.1.tgz#6a9425b9c305bcbc38e2d1d9a24c08e15e02b722"
|
||||
integrity sha512-ahOdkIY9Mgbza7L9sIi205Pe1inCkZWAHE1TV1bpxlU4RZNPtXaDZfiiFWcL9jdxvW1hDYZJXrFm+vlMkXRbBw==
|
||||
"@typescript-eslint/typescript-estree@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.13.0.tgz#b37c07b748ff030a3e93d87c842714e020b78141"
|
||||
integrity sha512-Q9cQow0DeLjnp5DuEDjLZ6JIkwGx3oYZe+BfcNuw/POhtpcxMTy18Icl6BJqTSd+3ftsrfuVb7mNHRZf7xiaNA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.12.1"
|
||||
"@typescript-eslint/visitor-keys" "5.12.1"
|
||||
"@typescript-eslint/types" "5.13.0"
|
||||
"@typescript-eslint/visitor-keys" "5.13.0"
|
||||
debug "^4.3.2"
|
||||
globby "^11.0.4"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.12.1.tgz#447c24a05d9c33f9c6c64cb48f251f2371eef920"
|
||||
integrity sha512-Qq9FIuU0EVEsi8fS6pG+uurbhNTtoYr4fq8tKjBupsK5Bgbk2I32UGm0Sh+WOyjOPgo/5URbxxSNV6HYsxV4MQ==
|
||||
"@typescript-eslint/utils@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.13.0.tgz#2328feca700eb02837298339a2e49c46b41bd0af"
|
||||
integrity sha512-+9oHlPWYNl6AwwoEt5TQryEHwiKRVjz7Vk6kaBeD3/kwHE5YqTGHtm/JZY8Bo9ITOeKutFaXnBlMgSATMJALUQ==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@typescript-eslint/scope-manager" "5.12.1"
|
||||
"@typescript-eslint/types" "5.12.1"
|
||||
"@typescript-eslint/typescript-estree" "5.12.1"
|
||||
"@typescript-eslint/scope-manager" "5.13.0"
|
||||
"@typescript-eslint/types" "5.13.0"
|
||||
"@typescript-eslint/typescript-estree" "5.13.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.1.tgz#f722da106c8f9695ae5640574225e45af3e52ec3"
|
||||
integrity sha512-l1KSLfupuwrXx6wc0AuOmC7Ko5g14ZOQ86wJJqRbdLbXLK02pK/DPiDDqCc7BqqiiA04/eAA6ayL0bgOrAkH7A==
|
||||
"@typescript-eslint/visitor-keys@5.13.0":
|
||||
version "5.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.13.0.tgz#f45ff55bcce16403b221ac9240fbeeae4764f0fd"
|
||||
integrity sha512-HLKEAS/qA1V7d9EzcpLFykTePmOQqOFim8oCvhY3pZgQ8Hi38hYpHd9e5GN6nQBFQNecNhws5wkS9Y5XIO0s/g==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.12.1"
|
||||
"@typescript-eslint/types" "5.13.0"
|
||||
eslint-visitor-keys "^3.0.0"
|
||||
|
||||
"@webassemblyjs/ast@1.11.1":
|
||||
@@ -4395,11 +4369,6 @@ detect-node@^2.0.4:
|
||||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
||||
|
||||
diff-sequences@^27.4.0:
|
||||
version "27.4.0"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5"
|
||||
integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==
|
||||
|
||||
diff-sequences@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
|
||||
@@ -4495,7 +4464,7 @@ domhandler@^4.0.0, domhandler@^4.2.0:
|
||||
dependencies:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
dompurify@^2.3.4:
|
||||
dompurify@^2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
|
||||
integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
|
||||
@@ -4601,7 +4570,7 @@ end-of-stream@^1.1.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.3:
|
||||
enhanced-resolve@^5.0.0:
|
||||
version "5.8.3"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0"
|
||||
integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA==
|
||||
@@ -4609,6 +4578,14 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.3:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
|
||||
enhanced-resolve@^5.9.2:
|
||||
version "5.9.2"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9"
|
||||
integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
|
||||
entities@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
@@ -4760,32 +4737,32 @@ escodegen@^2.0.0:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-prettier@^8.4.0:
|
||||
version "8.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.4.0.tgz#8e6d17c7436649e98c4c2189868562921ef563de"
|
||||
integrity sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw==
|
||||
eslint-config-prettier@^8.5.0:
|
||||
version "8.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
|
||||
integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
|
||||
|
||||
eslint-plugin-react-hooks@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
|
||||
integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
|
||||
|
||||
eslint-plugin-react@^7.28.0:
|
||||
version "7.28.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf"
|
||||
integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw==
|
||||
eslint-plugin-react@^7.29.2:
|
||||
version "7.29.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c"
|
||||
integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w==
|
||||
dependencies:
|
||||
array-includes "^3.1.4"
|
||||
array.prototype.flatmap "^1.2.5"
|
||||
doctrine "^2.1.0"
|
||||
estraverse "^5.3.0"
|
||||
jsx-ast-utils "^2.4.1 || ^3.0.0"
|
||||
minimatch "^3.0.4"
|
||||
minimatch "^3.1.2"
|
||||
object.entries "^1.1.5"
|
||||
object.fromentries "^2.0.5"
|
||||
object.hasown "^1.1.0"
|
||||
object.values "^1.1.5"
|
||||
prop-types "^15.7.2"
|
||||
prop-types "^15.8.1"
|
||||
resolve "^2.0.0-next.3"
|
||||
semver "^6.3.0"
|
||||
string.prototype.matchall "^4.0.6"
|
||||
@@ -4833,12 +4810,12 @@ eslint-visitor-keys@^3.3.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||
|
||||
eslint@^8.9.0:
|
||||
version "8.9.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb"
|
||||
integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==
|
||||
eslint@^8.10.0:
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d"
|
||||
integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^1.1.0"
|
||||
"@eslint/eslintrc" "^1.2.0"
|
||||
"@humanwhocodes/config-array" "^0.9.2"
|
||||
ajv "^6.10.0"
|
||||
chalk "^4.0.0"
|
||||
@@ -6279,16 +6256,6 @@ jest-config@^27.5.1:
|
||||
slash "^3.0.0"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
jest-diff@^27.0.0:
|
||||
version "27.4.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.2.tgz#786b2a5211d854f848e2dcc1e324448e9481f36f"
|
||||
integrity sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
diff-sequences "^27.4.0"
|
||||
jest-get-type "^27.4.0"
|
||||
pretty-format "^27.4.2"
|
||||
|
||||
jest-diff@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
|
||||
@@ -6342,11 +6309,6 @@ jest-environment-node@^27.5.1:
|
||||
jest-mock "^27.5.1"
|
||||
jest-util "^27.5.1"
|
||||
|
||||
jest-get-type@^27.4.0:
|
||||
version "27.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5"
|
||||
integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==
|
||||
|
||||
jest-get-type@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
|
||||
@@ -6403,7 +6365,7 @@ jest-leak-detector@^27.5.1:
|
||||
jest-get-type "^27.5.1"
|
||||
pretty-format "^27.5.1"
|
||||
|
||||
jest-matcher-utils@^27.5.1:
|
||||
jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
|
||||
integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
|
||||
@@ -7215,6 +7177,13 @@ minimatch@^3.0.4, minimatch@~3.0.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist-options@4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
|
||||
@@ -7307,10 +7276,10 @@ mobx-react-lite@^3.3.0:
|
||||
resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.3.0.tgz#7174e807201943beff6f9d3701492314c9fc0db3"
|
||||
integrity sha512-U/kMSFtV/bNVgY01FuiGWpRkaQVHozBq5CEBZltFvPt4FcV111hEWkgwqVg9GPPZSEuEdV438PEz8mk8mKpYlA==
|
||||
|
||||
mobx@^6.4.1:
|
||||
version "6.4.1"
|
||||
resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.4.1.tgz#c1d0eeb37ceb31bb2020a85f6bf856782d47fe60"
|
||||
integrity sha512-NFXx0uMbGBgsa0uxhH099L8cMuoRQWh01q6Sf0ZX/3hFU7svJ7yfTD+1LnLMa5wzY/b7gImAeMsR1p0wordDnA==
|
||||
mobx@^6.4.2:
|
||||
version "6.4.2"
|
||||
resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.4.2.tgz#d25cd358a46b7a8fe2d8299259bc71008a2aa5b3"
|
||||
integrity sha512-b4xQJYiH8sb0sEbfq/Ws3N77DEJtSihUFD1moeiz2jNoJ5B+mqJutt54ouO9iEfkp7Wk4jQDsVUOh7DPEW3wEw==
|
||||
|
||||
mri@^1.1.5:
|
||||
version "1.2.0"
|
||||
@@ -7366,11 +7335,16 @@ nan@^2.13.2:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||
|
||||
nanoid@^3.2.0:
|
||||
nanoid@^3.2.0, nanoid@^3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35"
|
||||
integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==
|
||||
|
||||
nanostores@^0.5.10:
|
||||
version "0.5.10"
|
||||
resolved "https://registry.yarnpkg.com/nanostores/-/nanostores-0.5.10.tgz#16488776f01fa288b09c026400ff535da55c3583"
|
||||
integrity sha512-8Y7C8sF8PsHGpLVJochWT+ytEY34XrNRDA30hDqgvLcl5Ih4d/IFb7gUSFIwmgFAaht1pLwKZHTeFoJrNz88RQ==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
@@ -7922,7 +7896,7 @@ pretty-error@^4.0.0:
|
||||
lodash "^4.17.20"
|
||||
renderkid "^3.0.0"
|
||||
|
||||
pretty-format@^27.0.0, pretty-format@^27.4.2:
|
||||
pretty-format@^27.0.0:
|
||||
version "27.4.2"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.2.tgz#e4ce92ad66c3888423d332b40477c87d1dac1fb8"
|
||||
integrity sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==
|
||||
@@ -7988,6 +7962,15 @@ prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.8.1"
|
||||
|
||||
prop-types@^15.8.1:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
dependencies:
|
||||
loose-envify "^1.4.0"
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
proxy-addr@~2.0.5:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
||||
@@ -8110,7 +8093,7 @@ react-focus-lock@^2.5.2:
|
||||
use-callback-ref "^1.2.5"
|
||||
use-sidecar "^1.0.5"
|
||||
|
||||
react-is@^16.7.0, react-is@^16.8.1:
|
||||
react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
@@ -9273,10 +9256,10 @@ ts-jest@^27.1.3:
|
||||
semver "7.x"
|
||||
yargs-parser "20.x"
|
||||
|
||||
ts-loader@^9.2.6:
|
||||
version "9.2.6"
|
||||
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74"
|
||||
integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw==
|
||||
ts-loader@^9.2.7:
|
||||
version "9.2.7"
|
||||
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.7.tgz#948654099ca96992b62ec47bd9cee5632006e101"
|
||||
integrity sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg==
|
||||
dependencies:
|
||||
chalk "^4.1.0"
|
||||
enhanced-resolve "^5.0.0"
|
||||
@@ -9386,10 +9369,10 @@ typescript-eslint@0.0.1-alpha.0:
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-0.0.1-alpha.0.tgz#285d68a4e96588295cd436278801bcb6a6b916c1"
|
||||
integrity sha512-1hNKM37dAWML/2ltRXupOq2uqcdRQyDFphl+341NTPXFLLLiDhErXx8VtaSLh3xP7SyHZdcCgpt9boYYVb3fQg==
|
||||
|
||||
typescript@4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
typescript@4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
|
||||
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
|
||||
|
||||
unbox-primitive@^1.0.1:
|
||||
version "1.0.1"
|
||||
@@ -9674,10 +9657,10 @@ webpack-sources@^3.2.3:
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
|
||||
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
|
||||
|
||||
webpack@^5.69.1:
|
||||
version "5.69.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5"
|
||||
integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==
|
||||
webpack@^5.70.0:
|
||||
version "5.70.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d"
|
||||
integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.3"
|
||||
"@types/estree" "^0.0.51"
|
||||
@@ -9688,7 +9671,7 @@ webpack@^5.69.1:
|
||||
acorn-import-assertions "^1.7.6"
|
||||
browserslist "^4.14.5"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.8.3"
|
||||
enhanced-resolve "^5.9.2"
|
||||
es-module-lexer "^0.9.0"
|
||||
eslint-scope "5.1.1"
|
||||
events "^3.2.0"
|
||||
|
||||
Reference in New Issue
Block a user