feat: snjs with auto integrity resolution (#912)

This commit is contained in:
Mo
2022-03-07 10:34:23 -06:00
committed by GitHub
parent 39c503ca1d
commit ae5b182ac1
14 changed files with 78 additions and 199 deletions

View File

@@ -24,23 +24,23 @@ export const GeneralAccountMenu: FunctionComponent<Props> = observer(
({ application, appState, setMenuPane, closeMenu }) => { ({ application, appState, setMenuPane, closeMenu }) => {
const [isSyncingInProgress, setIsSyncingInProgress] = useState(false); const [isSyncingInProgress, setIsSyncingInProgress] = useState(false);
const [lastSyncDate, setLastSyncDate] = useState( const [lastSyncDate, setLastSyncDate] = useState(
formatLastSyncDate(application.getLastSyncDate() as Date) formatLastSyncDate(application.sync.getLastSyncDate() as Date)
); );
const doSynchronization = async () => { const doSynchronization = async () => {
setIsSyncingInProgress(true); setIsSyncingInProgress(true);
application application.sync
.sync({ .sync({
queueStrategy: SyncQueueStrategy.ForceSpawnNew, queueStrategy: SyncQueueStrategy.ForceSpawnNew,
checkIntegrity: true, checkIntegrity: true,
}) })
.then((res) => { .then((res) => {
if (res && res.error) { if (res && (res as any).error) {
throw new Error(); throw new Error();
} else { } else {
setLastSyncDate( setLastSyncDate(
formatLastSyncDate(application.getLastSyncDate() as Date) formatLastSyncDate(application.sync.getLastSyncDate() as Date)
); );
} }
}) })

View File

@@ -145,7 +145,7 @@ export class ApplicationView extends PureComponent<Props, State> {
this.setState({ appClass }); this.setState({ appClass });
} else if (eventName === AppStateEvent.WindowDidFocus) { } else if (eventName === AppStateEvent.WindowDidFocus) {
if (!(await this.application.isLocked())) { if (!(await this.application.isLocked())) {
this.application.sync(); this.application.sync.sync();
} }
} }
} }

View File

@@ -256,7 +256,7 @@ export class Footer extends PureComponent<Props, State> {
updateSyncStatus() { updateSyncStatus() {
const statusManager = this.application.getStatusManager(); const statusManager = this.application.getStatusManager();
const syncStatus = this.application.getSyncStatus(); const syncStatus = this.application.sync.getSyncStatus();
const stats = syncStatus.getStats(); const stats = syncStatus.getStats();
if (syncStatus.hasError()) { if (syncStatus.hasError()) {
statusManager.setMessage('Unable to Sync'); statusManager.setMessage('Unable to Sync');
@@ -290,7 +290,7 @@ export class Footer extends PureComponent<Props, State> {
updateLocalDataStatus() { updateLocalDataStatus() {
const statusManager = this.application.getStatusManager(); const statusManager = this.application.getStatusManager();
const syncStatus = this.application.getSyncStatus(); const syncStatus = this.application.sync.getSyncStatus();
const stats = syncStatus.getStats(); const stats = syncStatus.getStats();
const encryption = this.application.isEncryptionAvailable(); const encryption = this.application.isEncryptionAvailable();
if (stats.localDataDone) { if (stats.localDataDone) {
@@ -312,7 +312,7 @@ export class Footer extends PureComponent<Props, State> {
findErrors() { findErrors() {
this.setState({ this.setState({
hasError: this.application.getSyncStatus().hasError(), hasError: this.application.sync.getSyncStatus().hasError(),
}); });
} }

View File

@@ -681,7 +681,7 @@ export class NoteView extends PureComponent<Props, State> {
if (left !== undefined && left !== null) { if (left !== undefined && left !== null) {
await this.application.setPreference(PrefKey.EditorLeft, left); await this.application.setPreference(PrefKey.EditorLeft, left);
} }
this.application.sync(); this.application.sync.sync();
}; };
async reloadSpellcheck() { async reloadSpellcheck() {
@@ -797,7 +797,7 @@ export class NoteView extends PureComponent<Props, State> {
} else { } else {
await this.disassociateComponentWithCurrentNote(component); await this.disassociateComponentWithCurrentNote(component);
} }
this.application.sync(); this.application.sync.sync();
}; };
async disassociateComponentWithCurrentNote(component: SNComponent) { async disassociateComponentWithCurrentNote(component: SNComponent) {

View File

@@ -153,7 +153,7 @@ export const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
await application.runTransactionalMutations(transactions); await application.runTransactionalMutations(transactions);
/** Dirtying can happen above */ /** Dirtying can happen above */
application.sync(); application.sync.sync();
setCurrentEditor(application.componentManager.editorForNote(note)); setCurrentEditor(application.componentManager.editorForNote(note));
}; };

View File

@@ -1,6 +1,5 @@
import { WebApplication } from '@/ui_models/application'; import { WebApplication } from '@/ui_models/application';
import { PureComponent } from './Abstract/PureComponent'; import { PureComponent } from './Abstract/PureComponent';
import { Fragment } from 'preact';
type Props = { type Props = {
application: WebApplication; application: WebApplication;
@@ -8,43 +7,13 @@ type Props = {
}; };
export class SyncResolutionMenu extends PureComponent<Props> { export class SyncResolutionMenu extends PureComponent<Props> {
private status: Partial<{
backupFinished: boolean;
resolving: boolean;
attemptedResolution: boolean;
success: boolean;
fail: boolean;
}> = {};
constructor(props: Props) { constructor(props: Props) {
super(props, props.application); super(props, props.application);
} }
downloadBackup(encrypted: boolean) { close = () => {
this.props.application.getArchiveService().downloadBackup(encrypted);
this.status.backupFinished = true;
}
skipBackup() {
this.status.backupFinished = true;
}
async performSyncResolution() {
this.status.resolving = true;
await this.props.application.resolveOutOfSync();
this.status.resolving = false;
this.status.attemptedResolution = true;
if (this.props.application.isOutOfSync()) {
this.status.fail = true;
} else {
this.status.success = true;
}
}
close() {
this.props.close(); this.props.close();
} };
render() { render() {
return ( return (
@@ -59,13 +28,15 @@ export class SyncResolutionMenu extends PureComponent<Props> {
<div className="sk-panel-content"> <div className="sk-panel-content">
<div className="sk-panel-section"> <div className="sk-panel-section">
<div className="sk-panel-row sk-p"> <div className="sk-panel-row sk-p">
We've detected that the data on the server may not match the We've detected that the data in the current application session
data in the current application session. may not match the data on the server. An attempt was made to
auto-resolve the issue, but it was unable to reconcile the
differences.
</div> </div>
<div className="sk-p sk-panel-row"> <div className="sk-p sk-panel-row">
<div className="sk-panel-column"> <div className="sk-panel-column">
<strong className="sk-panel-row"> <strong className="sk-panel-row">
Option 1 Restart App: Option 1 Restart Application:
</strong> </strong>
<div className="sk-p"> <div className="sk-p">
Quit the application and re-open it. Sometimes, this may Quit the application and re-open it. Sometimes, this may
@@ -76,108 +47,15 @@ export class SyncResolutionMenu extends PureComponent<Props> {
<div className="sk-p sk-panel-row"> <div className="sk-p sk-panel-row">
<div className="sk-panel-column"> <div className="sk-panel-column">
<strong className="sk-panel-row"> <strong className="sk-panel-row">
Option 2 (recommended) Sign Out: Option 2 Sign Out and Back In:
</strong> </strong>
<div className="sk-p"> <div className="sk-p">
Sign out of your account, then sign back in. This will Sign out of your account, then sign back in. This will
ensure your data is consistent with the server. ensure your data is consistent with the server. Be sure to
</div> download a backup of your data before doing so.
Be sure to download a backup of your data before doing so.
</div>
</div>
<div className="sk-p sk-panel-row">
<div className="sk-panel-column">
<strong className="sk-panel-row">
Option 3 Sync Resolution:
</strong>
<div className="sk-p">
We can attempt to reconcile changes by downloading all data
from the server. No existing data will be overwritten. If
the local contents of an item differ from what the server
has, a conflicted copy will be created.
</div> </div>
</div> </div>
</div> </div>
{!this.status.backupFinished && (
<Fragment>
<div className="sk-p sk-panel-row">
Please download a backup before we attempt to perform a full
account sync resolution.
</div>
<div className="sk-panel-row">
<div className="flex gap-2">
<button
onClick={() => this.downloadBackup(true)}
className="sn-button small info"
>
Encrypted
</button>
<button
onClick={() => this.downloadBackup(false)}
className="sn-button small info"
>
Decrypted
</button>
<button
onClick={this.skipBackup}
className="sn-button small danger"
>
Skip
</button>
</div>
</div>
</Fragment>
)}
{this.status.backupFinished && (
<div>
{!this.status.resolving && !this.status.attemptedResolution && (
<div className="sk-panel-row">
<button
onClick={this.performSyncResolution}
className="sn-button small info"
>
Perform Sync Resolution
</button>
</div>
)}
{this.status.resolving && (
<div className="sk-panel-row justify-left">
<div className="sk-horizontal-group">
<div className="sk-spinner small info" />
<div className="sk-label">
Attempting sync resolution...
</div>
</div>
</div>
)}
{this.status.fail && (
<div className="sk-panel-column">
<div className="sk-panel-row sk-label danger">
Sync Resolution Failed
</div>
<div className="sk-p sk-panel-row">
We attempted to reconcile local content and server
content, but were unable to do so. At this point, we
recommend signing out of your account and signing back
in. You may wish to download a data backup before doing
so.
</div>
</div>
)}
{this.status.success && (
<div className="sk-panel-column">
<div className="sk-panel-row sk-label success">
Sync Resolution Success
</div>
<div className="sk-p sk-panel-row">
Your local data is now in sync with the server. You may
close this window.
</div>
</div>
)}
</div>
)}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -74,7 +74,7 @@ export const Extensions: FunctionComponent<{
const confirmExtension = async () => { const confirmExtension = async () => {
await application.insertItem(confirmableExtension as SNComponent); await application.insertItem(confirmableExtension as SNComponent);
application.sync(); application.sync.sync();
setExtensions(loadExtensions(application)); setExtensions(loadExtensions(application));
}; };

View File

@@ -24,22 +24,22 @@ export const Sync: FunctionComponent<Props> = observer(
({ application }: Props) => { ({ application }: Props) => {
const [isSyncingInProgress, setIsSyncingInProgress] = useState(false); const [isSyncingInProgress, setIsSyncingInProgress] = useState(false);
const [lastSyncDate, setLastSyncDate] = useState( const [lastSyncDate, setLastSyncDate] = useState(
formatLastSyncDate(application.getLastSyncDate() as Date) formatLastSyncDate(application.sync.getLastSyncDate() as Date)
); );
const doSynchronization = async () => { const doSynchronization = async () => {
setIsSyncingInProgress(true); setIsSyncingInProgress(true);
const response = await application.sync({ const response = await application.sync.sync({
queueStrategy: SyncQueueStrategy.ForceSpawnNew, queueStrategy: SyncQueueStrategy.ForceSpawnNew,
checkIntegrity: true, checkIntegrity: true,
}); });
setIsSyncingInProgress(false); setIsSyncingInProgress(false);
if (response && response.error) { if (response && (response as any).error) {
application.alertService!.alert(STRING_GENERIC_SYNC_ERROR); application.alertService.alert(STRING_GENERIC_SYNC_ERROR);
} else { } else {
setLastSyncDate( setLastSyncDate(
formatLastSyncDate(application.getLastSyncDate() as Date) formatLastSyncDate(application.sync.getLastSyncDate() as Date)
); );
} }
}; };

View File

@@ -381,7 +381,7 @@ export class AppState {
} }
break; break;
case ApplicationEvent.SyncStatusChanged: case ApplicationEvent.SyncStatusChanged:
this.sync.update(this.application.getSyncStatus()); this.sync.update(this.application.sync.getSyncStatus());
break; break;
} }
}); });

View File

@@ -181,7 +181,7 @@ export class NoteTagsState {
if (activeNote) { if (activeNote) {
await this.application.addTagHierarchyToNote(activeNote, tag); await this.application.addTagHierarchyToNote(activeNote, tag);
this.application.sync(); this.application.sync.sync();
this.reloadTags(); this.reloadTags();
} }
} }
@@ -192,7 +192,7 @@ export class NoteTagsState {
await this.application.changeItem(tag.uuid, (mutator) => { await this.application.changeItem(tag.uuid, (mutator) => {
mutator.removeItemAsRelationship(activeNote); mutator.removeItemAsRelationship(activeNote);
}); });
this.application.sync(); this.application.sync.sync();
this.reloadTags(); this.reloadTags();
} }
} }

View File

@@ -265,7 +265,7 @@ export class NotesState {
mutate, mutate,
false false
); );
this.application.sync(); this.application.sync.sync();
} }
setHideSelectedNotePreviews(hide: boolean): void { setHideSelectedNotePreviews(hide: boolean): void {
@@ -403,7 +403,7 @@ export class NotesState {
}, },
false false
); );
this.application.sync(); this.application.sync.sync();
} }
async addTagToSelectedNotes(tag: SNTag): Promise<void> { async addTagToSelectedNotes(tag: SNTag): Promise<void> {
@@ -419,7 +419,7 @@ export class NotesState {
}); });
}) })
); );
this.application.sync(); this.application.sync.sync();
} }
async removeTagFromSelectedNotes(tag: SNTag): Promise<void> { async removeTagFromSelectedNotes(tag: SNTag): Promise<void> {
@@ -429,7 +429,7 @@ export class NotesState {
mutator.removeItemAsRelationship(note); mutator.removeItemAsRelationship(note);
} }
}); });
this.application.sync(); this.application.sync.sync();
} }
isTagInSelectedNotes(tag: SNTag): boolean { isTagInSelectedNotes(tag: SNTag): boolean {
@@ -453,7 +453,7 @@ export class NotesState {
}) })
) { ) {
this.application.emptyTrash(); this.application.emptyTrash();
this.application.sync(); this.application.sync.sync();
} }
} }

View File

@@ -208,7 +208,7 @@ export class TagsState {
this.assignParent(createdTag.uuid, parent.uuid); this.assignParent(createdTag.uuid, parent.uuid);
this.application.sync(); this.application.sync.sync();
runInAction(() => { runInAction(() => {
this.selected = createdTag as SNTag; this.selected = createdTag as SNTag;
@@ -364,7 +364,7 @@ export class TagsState {
await this.application.setTagParent(futureParent, tag); await this.application.setTagParent(futureParent, tag);
} }
await this.application.sync(); await this.application.sync.sync();
} }
get rootTags(): SNTag[] { get rootTags(): SNTag[] {
@@ -507,7 +507,7 @@ export class TagsState {
} }
const insertedTag = await this.application.createTagOrSmartView(newTitle); const insertedTag = await this.application.createTagOrSmartView(newTitle);
this.application.sync(); this.application.sync.sync();
runInAction(() => { runInAction(() => {
this.selected = insertedTag as SNTag; this.selected = insertedTag as SNTag;
}); });

View File

@@ -27,8 +27,8 @@
"@babel/preset-typescript": "^7.16.7", "@babel/preset-typescript": "^7.16.7",
"@reach/disclosure": "^0.16.2", "@reach/disclosure": "^0.16.2",
"@reach/visually-hidden": "^0.16.0", "@reach/visually-hidden": "^0.16.0",
"@standardnotes/responses": "^1.1.7", "@standardnotes/responses": "^1.2.0",
"@standardnotes/services": "^1.4.0", "@standardnotes/services": "^1.5.0",
"@standardnotes/stylekit": "5.14.0", "@standardnotes/stylekit": "5.14.0",
"@svgr/webpack": "^6.2.1", "@svgr/webpack": "^6.2.1",
"@types/jest": "^27.4.1", "@types/jest": "^27.4.1",
@@ -80,13 +80,13 @@
"@reach/tooltip": "^0.16.2", "@reach/tooltip": "^0.16.2",
"@standardnotes/components": "1.7.9", "@standardnotes/components": "1.7.9",
"@standardnotes/features": "1.34.1", "@standardnotes/features": "1.34.1",
"@standardnotes/settings": "^1.11.5", "@standardnotes/settings": "^1.12.0",
"@standardnotes/sncrypto-web": "1.7.3", "@standardnotes/sncrypto-web": "1.7.3",
"@standardnotes/snjs": "2.73.2", "@standardnotes/snjs": "2.76.0",
"mobx": "^6.4.2", "mobx": "^6.4.2",
"mobx-react-lite": "^3.3.0", "mobx-react-lite": "^3.3.0",
"preact": "^10.6.6", "preact": "^10.6.6",
"qrcode.react": "^1.0.1", "qrcode.react": "^2.0.0",
"react-dnd": "^15.1.1", "react-dnd": "^15.1.1",
"react-dnd-html5-backend": "^15.1.2", "react-dnd-html5-backend": "^15.1.2",
"react-dnd-touch-backend": "^15.1.1" "react-dnd-touch-backend": "^15.1.1"

View File

@@ -2331,10 +2331,10 @@
resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.9.tgz#41e5fdbcee250b9b3c18045dad8998c6f668307b" resolved "https://registry.yarnpkg.com/@standardnotes/components/-/components-1.7.9.tgz#41e5fdbcee250b9b3c18045dad8998c6f668307b"
integrity sha512-/+Paw6ry/IS9ldYUM/lgC4O6qwl1fukWvNw65IMKyB9LMY3+xTh/I2BfnWynP117pVPxtu3/2+FBEnx04KvQwg== integrity sha512-/+Paw6ry/IS9ldYUM/lgC4O6qwl1fukWvNw65IMKyB9LMY3+xTh/I2BfnWynP117pVPxtu3/2+FBEnx04KvQwg==
"@standardnotes/domain-events@^2.23.21": "@standardnotes/domain-events@^2.23.22":
version "2.23.21" version "2.23.22"
resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.21.tgz#bbf752ee7a0fd08b9fb675e81b46d3c10bbf89e9" resolved "https://registry.yarnpkg.com/@standardnotes/domain-events/-/domain-events-2.23.22.tgz#eb246cc3d8e69af7014678f5aac34fa1d7b494a0"
integrity sha512-YPpwy+QrDziBOpjt5cOIZwY47fOddN3038+NTRSqxi4h/D8hU+U5O8dGl2XktENEq9DqVJ78OVmWBjkA2FlsEQ== integrity sha512-mtw1nFZ/laiMisjTNBXgCsu6RLG/zkW4VtvnKjodG2TEJV3zPxFALGRUnsIlSlwt3YdClzg073sKHtUn4s+sAw==
dependencies: dependencies:
"@standardnotes/auth" "^3.17.3" "@standardnotes/auth" "^3.17.3"
"@standardnotes/features" "^1.34.1" "@standardnotes/features" "^1.34.1"
@@ -2347,39 +2347,40 @@
"@standardnotes/auth" "^3.17.3" "@standardnotes/auth" "^3.17.3"
"@standardnotes/common" "^1.15.3" "@standardnotes/common" "^1.15.3"
"@standardnotes/payloads@^1.3.2": "@standardnotes/payloads@^1.4.0":
version "1.3.2" version "1.4.0"
resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.3.2.tgz#3255abf6e2a2385c73e7998705066b828e5a74e0" resolved "https://registry.yarnpkg.com/@standardnotes/payloads/-/payloads-1.4.0.tgz#e1a5415708c9d462c4f5f4824f7effd7e9d7f791"
integrity sha512-SnDqdQXyEWett/Y33crvNnDGwv4BfCkoHId99fLd+UL5uTgXpuFgkd/AVHg+mOT5xC3+KAR8zdUCmQSXTRuysg== integrity sha512-gAOj3p9KPsQggZ2SjeMjh4XTkTy8ntUYD23kYKbLA/Z7ArCCp8LnZZHASII2kEznaK+vrUAqlSM2/oKwQlohDA==
dependencies: dependencies:
"@standardnotes/applications" "^1.1.3" "@standardnotes/applications" "^1.1.3"
"@standardnotes/common" "^1.15.3" "@standardnotes/common" "^1.15.3"
"@standardnotes/features" "^1.34.1" "@standardnotes/features" "^1.34.1"
"@standardnotes/utils" "^1.2.3" "@standardnotes/utils" "^1.2.3"
"@standardnotes/responses@^1.1.7": "@standardnotes/responses@^1.2.0":
version "1.1.7" version "1.2.0"
resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.1.7.tgz#ab982f94693f2e1f967809bdb5e3863182770b14" resolved "https://registry.yarnpkg.com/@standardnotes/responses/-/responses-1.2.0.tgz#fe295b31751dbc692bb65c8e162972127fb990b2"
integrity sha512-1q8+eGjvttleesciHAOTe6u478W3UpEy+0StT8ZL3miFWzIyCLXJmnxNbYfYCm6oZ+t2rwhW+AzmnMRhG2cOUA== integrity sha512-YuVJQlB4ipdqAlAtD0xPhbHSR38fPzcRbSkntaCadHeAZl7WAdDDf/7pxTCDwhXN8Hls9OXlrq+WNbhorpe0tw==
dependencies: dependencies:
"@standardnotes/auth" "^3.17.3" "@standardnotes/auth" "^3.17.3"
"@standardnotes/common" "^1.15.3" "@standardnotes/common" "^1.15.3"
"@standardnotes/features" "^1.34.1" "@standardnotes/features" "^1.34.1"
"@standardnotes/payloads" "^1.3.2" "@standardnotes/payloads" "^1.4.0"
"@standardnotes/services@^1.4.0": "@standardnotes/services@^1.5.0":
version "1.4.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.4.0.tgz#776ee5d022e4512844af1a284a2e90f599217218" resolved "https://registry.yarnpkg.com/@standardnotes/services/-/services-1.5.0.tgz#ab71393d947bf52a7fb682d8bbcc190acef8fe97"
integrity sha512-wO0LQ+qMG0bfH0HNPulsO8nZ2Z1Y84NLP0fZdMdtqiuaCi1GrM/PUlcL/fpXCJKNeTKoYa8Dh4PfF8DOjalKXg== integrity sha512-vZ7NmV3SVdt5UQDCJ+OsoGtMFr0wsmHBdXpyb8s4rRnR4PgmJsrhuGXEu0t23EyLilL+Yb6WtkfJQhXeQsiT9w==
dependencies: dependencies:
"@standardnotes/applications" "^1.1.3" "@standardnotes/applications" "^1.1.3"
"@standardnotes/common" "^1.15.3" "@standardnotes/common" "^1.15.3"
"@standardnotes/responses" "^1.2.0"
"@standardnotes/utils" "^1.2.3" "@standardnotes/utils" "^1.2.3"
"@standardnotes/settings@^1.11.5": "@standardnotes/settings@^1.12.0":
version "1.11.5" version "1.12.0"
resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.11.5.tgz#792bf3e0505065486f521b2f19c2bf1081b8fa5e" resolved "https://registry.yarnpkg.com/@standardnotes/settings/-/settings-1.12.0.tgz#43f3dd7f015f726b1ed88a48fcc3737899116cd5"
integrity sha512-n6StAS3nBgs7Lia5mOt3+H4Xd6hatCcHFx83paFq9kdI1cKbqn7oFF4g/rUbWPy4nsx+96zBehB6EhsJ2MGzyQ== integrity sha512-w6S5TT7KRpvUb+JsXZ7ucWPjlWRtpKQdsyT7cLs66ynKRXxUn40hf4kA8T9FhuLAKbG+wIYDrAZl3FRk+HvDWQ==
"@standardnotes/sncrypto-common@^1.7.3": "@standardnotes/sncrypto-common@^1.7.3":
version "1.7.3" version "1.7.3"
@@ -2395,20 +2396,20 @@
buffer "^6.0.3" buffer "^6.0.3"
libsodium-wrappers "^0.7.9" libsodium-wrappers "^0.7.9"
"@standardnotes/snjs@2.73.2": "@standardnotes/snjs@2.76.0":
version "2.73.2" version "2.76.0"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.73.2.tgz#5361d73c861b990d06821d5a822dcb0893830a43" resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.76.0.tgz#61cfa03bea5e624529b7bbdd67646b4184ea30b3"
integrity sha512-oGPZmzX+tNWQFxmvrQRtsqlofbW25YUOapyEPN8oVgfwV98r8EVzpUGXHWkog3ZW6oO3aO22Rhtk0D92d0CqtQ== integrity sha512-SWSCMbDsJhdxNpHFHdK60iqaAsgvozvX8pgcAekko+yPlw3kz5Ucp+wwQbiznQRwrxOZPPrG/1NkJa1U/wWcdA==
dependencies: dependencies:
"@standardnotes/applications" "^1.1.3" "@standardnotes/applications" "^1.1.3"
"@standardnotes/auth" "^3.17.3" "@standardnotes/auth" "^3.17.3"
"@standardnotes/common" "^1.15.3" "@standardnotes/common" "^1.15.3"
"@standardnotes/domain-events" "^2.23.21" "@standardnotes/domain-events" "^2.23.22"
"@standardnotes/features" "^1.34.1" "@standardnotes/features" "^1.34.1"
"@standardnotes/payloads" "^1.3.2" "@standardnotes/payloads" "^1.4.0"
"@standardnotes/responses" "^1.1.7" "@standardnotes/responses" "^1.2.0"
"@standardnotes/services" "^1.4.0" "@standardnotes/services" "^1.5.0"
"@standardnotes/settings" "^1.11.5" "@standardnotes/settings" "^1.12.0"
"@standardnotes/sncrypto-common" "^1.7.3" "@standardnotes/sncrypto-common" "^1.7.3"
"@standardnotes/utils" "^1.2.3" "@standardnotes/utils" "^1.2.3"
@@ -8002,10 +8003,10 @@ qr.js@0.0.0:
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8= integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
qrcode.react@^1.0.1: qrcode.react@^2.0.0:
version "1.0.1" version "2.0.0"
resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-1.0.1.tgz#2834bb50e5e275ffe5af6906eff15391fe9e38a5" resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-2.0.0.tgz#20b738eddcfc6958673bbbd1a0c5568ee5c399f5"
integrity sha512-8d3Tackk8IRLXTo67Y+c1rpaiXjoz/Dd2HpcMdW//62/x8J1Nbho14Kh8x974t9prsLHN6XqVgcnRiBGFptQmg== integrity sha512-1CCzwC4KHYCzOLb7M+lKYqHzDMVsppKJBhrU1ZDCuJRHKiD99LeDHOkuvUKCRvnJgDzp9SnB6/WNA7qp6I7ozA==
dependencies: dependencies:
loose-envify "^1.4.0" loose-envify "^1.4.0"
prop-types "^15.6.0" prop-types "^15.6.0"