Skip to content

Commit

Permalink
feat: snjs with auto integrity resolution (#912)
Browse files Browse the repository at this point in the history
  • Loading branch information
moughxyz committed Mar 7, 2022
1 parent 39c503c commit ae5b182
Show file tree
Hide file tree
Showing 14 changed files with 78 additions and 199 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@ export const GeneralAccountMenu: FunctionComponent<Props> = observer(
({ application, appState, setMenuPane, closeMenu }) => {
const [isSyncingInProgress, setIsSyncingInProgress] = useState(false);
const [lastSyncDate, setLastSyncDate] = useState(
formatLastSyncDate(application.getLastSyncDate() as Date)
formatLastSyncDate(application.sync.getLastSyncDate() as Date)
);

const doSynchronization = async () => {
setIsSyncingInProgress(true);

application
application.sync
.sync({
queueStrategy: SyncQueueStrategy.ForceSpawnNew,
checkIntegrity: true,
})
.then((res) => {
if (res && res.error) {
if (res && (res as any).error) {
throw new Error();
} else {
setLastSyncDate(
formatLastSyncDate(application.getLastSyncDate() as Date)
formatLastSyncDate(application.sync.getLastSyncDate() as Date)
);
}
})
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/components/ApplicationView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export class ApplicationView extends PureComponent<Props, State> {
this.setState({ appClass });
} else if (eventName === AppStateEvent.WindowDidFocus) {
if (!(await this.application.isLocked())) {
this.application.sync();
this.application.sync.sync();
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions app/assets/javascripts/components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export class Footer extends PureComponent<Props, State> {

updateSyncStatus() {
const statusManager = this.application.getStatusManager();
const syncStatus = this.application.getSyncStatus();
const syncStatus = this.application.sync.getSyncStatus();
const stats = syncStatus.getStats();
if (syncStatus.hasError()) {
statusManager.setMessage('Unable to Sync');
Expand Down Expand Up @@ -290,7 +290,7 @@ export class Footer extends PureComponent<Props, State> {

updateLocalDataStatus() {
const statusManager = this.application.getStatusManager();
const syncStatus = this.application.getSyncStatus();
const syncStatus = this.application.sync.getSyncStatus();
const stats = syncStatus.getStats();
const encryption = this.application.isEncryptionAvailable();
if (stats.localDataDone) {
Expand All @@ -312,7 +312,7 @@ export class Footer extends PureComponent<Props, State> {

findErrors() {
this.setState({
hasError: this.application.getSyncStatus().hasError(),
hasError: this.application.sync.getSyncStatus().hasError(),
});
}

Expand Down
4 changes: 2 additions & 2 deletions app/assets/javascripts/components/NoteView/NoteView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ export class NoteView extends PureComponent<Props, State> {
if (left !== undefined && left !== null) {
await this.application.setPreference(PrefKey.EditorLeft, left);
}
this.application.sync();
this.application.sync.sync();
};

async reloadSpellcheck() {
Expand Down Expand Up @@ -797,7 +797,7 @@ export class NoteView extends PureComponent<Props, State> {
} else {
await this.disassociateComponentWithCurrentNote(component);
}
this.application.sync();
this.application.sync.sync();
};

async disassociateComponentWithCurrentNote(component: SNComponent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({

await application.runTransactionalMutations(transactions);
/** Dirtying can happen above */
application.sync();
application.sync.sync();

setCurrentEditor(application.componentManager.editorForNote(note));
};
Expand Down
142 changes: 10 additions & 132 deletions app/assets/javascripts/components/SyncResolutionMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,19 @@
import { WebApplication } from '@/ui_models/application';
import { PureComponent } from './Abstract/PureComponent';
import { Fragment } from 'preact';

type Props = {
application: WebApplication;
close: () => void;
};

export class SyncResolutionMenu extends PureComponent<Props> {
private status: Partial<{
backupFinished: boolean;
resolving: boolean;
attemptedResolution: boolean;
success: boolean;
fail: boolean;
}> = {};

constructor(props: Props) {
super(props, props.application);
}

downloadBackup(encrypted: boolean) {
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() {
close = () => {
this.props.close();
}
};

render() {
return (
Expand All @@ -59,13 +28,15 @@ export class SyncResolutionMenu extends PureComponent<Props> {
<div className="sk-panel-content">
<div className="sk-panel-section">
<div className="sk-panel-row sk-p">
We've detected that the data on the server may not match the
data in the current application session.
We've detected that the 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 className="sk-p sk-panel-row">
<div className="sk-panel-column">
<strong className="sk-panel-row">
Option 1 — Restart App:
Option 1 — Restart Application:
</strong>
<div className="sk-p">
Quit the application and re-open it. Sometimes, this may
Expand All @@ -76,108 +47,15 @@ export class SyncResolutionMenu extends PureComponent<Props> {
<div className="sk-p sk-panel-row">
<div className="sk-panel-column">
<strong className="sk-panel-row">
Option 2 (recommended) — Sign Out:
Option 2 — Sign Out and Back In:
</strong>
<div className="sk-p">
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
download a backup of your data before doing so.
</div>
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>
{!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>
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/preferences/panes/Extensions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const Extensions: FunctionComponent<{

const confirmExtension = async () => {
await application.insertItem(confirmableExtension as SNComponent);
application.sync();
application.sync.sync();
setExtensions(loadExtensions(application));
};

Expand Down
10 changes: 5 additions & 5 deletions app/assets/javascripts/preferences/panes/account/Sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ export const Sync: FunctionComponent<Props> = observer(
({ application }: Props) => {
const [isSyncingInProgress, setIsSyncingInProgress] = useState(false);
const [lastSyncDate, setLastSyncDate] = useState(
formatLastSyncDate(application.getLastSyncDate() as Date)
formatLastSyncDate(application.sync.getLastSyncDate() as Date)
);

const doSynchronization = async () => {
setIsSyncingInProgress(true);

const response = await application.sync({
const response = await application.sync.sync({
queueStrategy: SyncQueueStrategy.ForceSpawnNew,
checkIntegrity: true,
});
setIsSyncingInProgress(false);
if (response && response.error) {
application.alertService!.alert(STRING_GENERIC_SYNC_ERROR);
if (response && (response as any).error) {
application.alertService.alert(STRING_GENERIC_SYNC_ERROR);
} else {
setLastSyncDate(
formatLastSyncDate(application.getLastSyncDate() as Date)
formatLastSyncDate(application.sync.getLastSyncDate() as Date)
);
}
};
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/ui_models/app_state/app_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ export class AppState {
}
break;
case ApplicationEvent.SyncStatusChanged:
this.sync.update(this.application.getSyncStatus());
this.sync.update(this.application.sync.getSyncStatus());
break;
}
});
Expand Down
4 changes: 2 additions & 2 deletions app/assets/javascripts/ui_models/app_state/note_tags_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class NoteTagsState {

if (activeNote) {
await this.application.addTagHierarchyToNote(activeNote, tag);
this.application.sync();
this.application.sync.sync();
this.reloadTags();
}
}
Expand All @@ -192,7 +192,7 @@ export class NoteTagsState {
await this.application.changeItem(tag.uuid, (mutator) => {
mutator.removeItemAsRelationship(activeNote);
});
this.application.sync();
this.application.sync.sync();
this.reloadTags();
}
}
Expand Down
10 changes: 5 additions & 5 deletions app/assets/javascripts/ui_models/app_state/notes_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export class NotesState {
mutate,
false
);
this.application.sync();
this.application.sync.sync();
}

setHideSelectedNotePreviews(hide: boolean): void {
Expand Down Expand Up @@ -403,7 +403,7 @@ export class NotesState {
},
false
);
this.application.sync();
this.application.sync.sync();
}

async addTagToSelectedNotes(tag: SNTag): Promise<void> {
Expand All @@ -419,7 +419,7 @@ export class NotesState {
});
})
);
this.application.sync();
this.application.sync.sync();
}

async removeTagFromSelectedNotes(tag: SNTag): Promise<void> {
Expand All @@ -429,7 +429,7 @@ export class NotesState {
mutator.removeItemAsRelationship(note);
}
});
this.application.sync();
this.application.sync.sync();
}

isTagInSelectedNotes(tag: SNTag): boolean {
Expand All @@ -453,7 +453,7 @@ export class NotesState {
})
) {
this.application.emptyTrash();
this.application.sync();
this.application.sync.sync();
}
}

Expand Down

0 comments on commit ae5b182

Please sign in to comment.