diff --git a/src/views/onboarding/component.tsx b/src/views/onboarding/component.tsx
index 8300b05..a35ee50 100644
--- a/src/views/onboarding/component.tsx
+++ b/src/views/onboarding/component.tsx
@@ -1,4 +1,7 @@
import { useState, useEffect } from "react";
+import SyncManager from "src/sync-manager";
+import { usePlugin } from "src/views/hooks";
+import { DEFAULT_SETTINGS } from "src/settings/settings";
const STEPS = [
"welcome",
@@ -6,24 +9,33 @@ const STEPS = [
"token",
"folders",
"sync",
- "interface",
"first_sync",
- "done",
] as const;
type Step = (typeof STEPS)[number];
type StepData = {
- repo?: { owner: string; repo: string; branch: string };
- token?: { token: string };
- folders?: { repoFolder: string; vaultFolder: string };
- sync?: {
+ repo: { owner: string; repo: string; branch: string };
+ token: { token: string };
+ folders: { repoFolder: string; vaultFolder: string };
+ sync: {
mode: "manual" | "interval";
syncOnStart: boolean;
onConflict: "ignore" | "ask" | "overwrite";
};
};
+const DEFAULT_STEP_DATA: StepData = {
+ repo: { owner: "", repo: "", branch: "" },
+ token: { token: "" },
+ folders: { repoFolder: "", vaultFolder: "" },
+ sync: {
+ mode: "manual",
+ syncOnStart: false,
+ onConflict: "overwrite",
+ },
+};
+
const WelcomeStepComponent = () => {
return (
{
};
const RepoStepComponent = ({
- values = { owner: "", repo: "", branch: "" },
+ values,
onChange,
}: {
- values?: { owner: string; repo: string; branch: string };
+ values: { owner: string; repo: string; branch: string };
onChange: (values: { owner: string; repo: string; branch: string }) => void;
}) => {
return (
@@ -117,10 +129,10 @@ const RepoStepComponent = ({
};
const TokenStepComponent = ({
- values = { token: "" },
+ values,
onChange,
}: {
- values?: { token: string };
+ values: { token: string };
onChange: (values: { token: string }) => void;
}) => {
return (
@@ -174,10 +186,10 @@ const TokenStepComponent = ({
};
const FoldersStepComponent = ({
- values = { repoFolder: "", vaultFolder: "" },
+ values,
onChange,
}: {
- values?: { repoFolder: string; vaultFolder: string };
+ values: { repoFolder: string; vaultFolder: string };
onChange: (values: { repoFolder: string; vaultFolder: string }) => void;
}) => {
return (
@@ -226,10 +238,10 @@ const FoldersStepComponent = ({
};
const SyncSettingsStepComponent = ({
- values = { mode: "manual", syncOnStart: false, onConflict: "overwrite" },
+ values,
onChange,
}: {
- values?: {
+ values: {
mode: "manual" | "interval";
syncOnStart: boolean;
onConflict: "ignore" | "ask" | "overwrite";
@@ -301,11 +313,71 @@ const SyncSettingsStepComponent = ({
};
const FirstSyncStepComponent = ({
- setIsValid,
+ stepData,
+ onClose,
}: {
- setIsValid: (valid: boolean) => void;
+ stepData: StepData;
+ onClose: () => Promise
;
}) => {
- setIsValid(true);
+ const [syncing, setSyncing] = useState(true);
+ const [error, setError] = useState(null);
+ const [success, setSuccess] = useState(false);
+
+ const plugin = usePlugin();
+ if (!plugin) {
+ // Unlikely to happen, makes TS happy though
+ throw new Error("Plugin is not initialized");
+ }
+ useEffect(() => {
+ (async () => {
+ const settings = {
+ ...DEFAULT_SETTINGS,
+ githubToken: stepData.token.token,
+ githubOwner: stepData.repo.owner,
+ githubRepo: stepData.repo.repo,
+ githubBranch: stepData.repo.branch,
+ repoContentDir: stepData.folders.repoFolder,
+ localContentDir: stepData.folders.vaultFolder,
+ uploadStrategy: stepData.sync.mode,
+ syncOnStartup: stepData.sync.syncOnStart,
+ conflictHandling: stepData.sync.onConflict,
+ };
+ // We don't want to save the settings yet, so we create a new sync manager
+ // used only for the first sync.
+ // After that's sucessful we'll save the settings.
+ const syncManager = new SyncManager(
+ plugin.app.vault,
+ settings,
+ // There can't be any conflicts at this point so we don't need to handle them
+ async (_) => {
+ return [];
+ },
+ );
+ try {
+ await syncManager.firstSync();
+ } catch (e) {
+ setError(e.message);
+ setSuccess(false);
+ setSyncing(false);
+ return;
+ }
+ plugin.settings = settings;
+ await plugin.saveSettings();
+ setSyncing(false);
+ setSuccess(true);
+ })();
+ }, [stepData]);
+
+ const loadingBarStyle = () => {
+ if (error) {
+ return { width: 0 };
+ } else if (success) {
+ return { width: "100%" };
+ } else {
+ return {};
+ }
+ };
+
return (
- Now we can sync your vault with your repository. This might take a few
- minutes depending on the size of your vault.
+ Now we can try and sync your vault with your repository. This might take
+ a few minutes depending on the number of files.
- Syncing vault...
+ {syncing ? "Syncing..." : null}
+ {error ? "Syncing failed" : null}
+ {success ? "Syncing complete" : null}
-
Show failure or success message here
+ {error ?
{error}
: null}
+ {success ?
Everything is set up and ready to go.
: null}
+ {success ? (
+
await onClose()}
+ >
+ Close
+
+ ) : null}
);
};
-const OnBoardingComponent = () => {
+const OnBoardingComponent = ({ onClose }: { onClose: () => Promise }) => {
// It starts as true because the first step is just a welcome message
// so the button is already enabled.
const [isValid, setIsValid] = useState(true);
const [step, setStep] = useState("welcome");
- const [stepData, setStepData] = useState({});
+ const [stepData, setStepData] = useState(DEFAULT_STEP_DATA);
const updateStepData = (step: Step, data: StepData[keyof StepData]) => {
setStepData((stepData) => {
@@ -419,9 +511,7 @@ const OnBoardingComponent = () => {
/>
);
case "first_sync":
- return ;
- // case "done":
- // return ;
+ return ;
}
};
return (
diff --git a/src/views/onboarding/view.tsx b/src/views/onboarding/view.tsx
index 20edde1..a84a8fc 100644
--- a/src/views/onboarding/view.tsx
+++ b/src/views/onboarding/view.tsx
@@ -16,20 +16,21 @@ export class OnboardingDialog extends Modal {
// Make the dialog look like the settings modal
this.modalEl.addClass("mod-settings");
this.modalEl.addClass("mod-sidebar-layout");
- // Make the dialog slightly smaller than Obsidian settings
- this.modalEl.setCssProps({
- width: "60vw",
- height: "50vh",
- });
this.root.render(
-
+ {
+ this.plugin.settings.firstStart = false;
+ await this.plugin.saveSettings();
+ this.close();
+ }}
+ />
,
);
}
- onClose() {
+ async onClose() {
const { contentEl } = this;
this.root?.unmount();
contentEl.empty();