Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94c7a4a874 | ||
|
|
b573b2859c | ||
|
|
e2c4d158b1 | ||
|
|
55890611e2 | ||
|
|
5acd1551c9 | ||
|
|
ef2c45a11d | ||
|
|
c1771bb117 | ||
|
|
ddb86745dd | ||
|
|
971719b710 |
@@ -0,0 +1,65 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File a bug report
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels: ["bug"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: What did you expect to happen?
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: What OS are you using?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- Windows
|
||||||
|
- Linux
|
||||||
|
- macOS
|
||||||
|
- iOS (iPhone, iPad)
|
||||||
|
- Android
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: service
|
||||||
|
attributes:
|
||||||
|
label: What remote cloud services are you using?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- S3
|
||||||
|
- OneDrive for personal
|
||||||
|
- Dropbox
|
||||||
|
- webdav
|
||||||
|
- others
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: version-plugin
|
||||||
|
attributes:
|
||||||
|
label: Version of the plugin
|
||||||
|
description: What version of the plugin are you running?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: input
|
||||||
|
id: version-obsidian
|
||||||
|
attributes:
|
||||||
|
label: Version of Obsidian
|
||||||
|
description: What version of Obsidian are you running?
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
id: ensure-no-sensitive-information
|
||||||
|
attributes:
|
||||||
|
label: Ensure no sensitive information
|
||||||
|
description: By submitting this issue, you ensure that no sensitive information is submitted in the issue.
|
||||||
|
options:
|
||||||
|
- label: I ensure that no sensitive information is submitted in the issue.
|
||||||
|
required: true
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: Some idea about new features
|
||||||
|
title: "[Feature Request]: "
|
||||||
|
labels: ["enhancement"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
- type: textarea
|
||||||
|
id: what-are-you-expecting
|
||||||
|
attributes:
|
||||||
|
label: What feature are you suggesting?
|
||||||
|
description: What feature are you suggesting?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: service
|
||||||
|
attributes:
|
||||||
|
label: What remote cloud services are you using, or suggesting adding the feature to?
|
||||||
|
multiple: true
|
||||||
|
options:
|
||||||
|
- S3
|
||||||
|
- OneDrive for personal
|
||||||
|
- Dropbox
|
||||||
|
- webdav
|
||||||
|
- others
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
id: ensure-no-sensitive-information
|
||||||
|
attributes:
|
||||||
|
label: Ensure no sensitive information
|
||||||
|
description: By submitting this issue, you ensure that no sensitive information is submitted in the issue.
|
||||||
|
options:
|
||||||
|
- label: I ensure that no sensitive information is submitted in the issue.
|
||||||
|
required: true
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "remotely-save",
|
"id": "remotely-save",
|
||||||
"name": "Remotely Save",
|
"name": "Remotely Save",
|
||||||
"version": "0.3.0",
|
"version": "0.3.2",
|
||||||
"minAppVersion": "0.12.15",
|
"minAppVersion": "0.12.15",
|
||||||
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
|
||||||
"author": "fyears",
|
"author": "fyears",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "remotely-save",
|
"name": "remotely-save",
|
||||||
"version": "0.3.0",
|
"version": "0.3.2",
|
||||||
"description": "This is yet another sync plugin for Obsidian app.",
|
"description": "This is yet another sync plugin for Obsidian app.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev2": "node esbuild.config.mjs",
|
"dev2": "node esbuild.config.mjs",
|
||||||
|
|||||||
+10
-3
@@ -156,13 +156,20 @@ const fixLastModifiedTimeInplace = (allFilesFolders: RemoteItem[]) => {
|
|||||||
// see https://dropbox.tech/developers/pkce--what-and-why-
|
// see https://dropbox.tech/developers/pkce--what-and-why-
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
export const getAuthUrlAndVerifier = async (appKey: string) => {
|
export const getAuthUrlAndVerifier = async (
|
||||||
|
appKey: string,
|
||||||
|
needManualPatse: boolean = false
|
||||||
|
) => {
|
||||||
const auth = new DropboxAuth({
|
const auth = new DropboxAuth({
|
||||||
clientId: appKey,
|
clientId: appKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const callback = needManualPatse
|
||||||
|
? undefined
|
||||||
|
: `obsidian://${COMMAND_CALLBACK_DROPBOX}`;
|
||||||
const authUrl = (
|
const authUrl = (
|
||||||
await auth.getAuthenticationUrl(
|
await auth.getAuthenticationUrl(
|
||||||
`obsidian://${COMMAND_CALLBACK_DROPBOX}`,
|
callback,
|
||||||
undefined,
|
undefined,
|
||||||
"code",
|
"code",
|
||||||
"offline",
|
"offline",
|
||||||
@@ -456,7 +463,7 @@ export const uploadToRemote = async (
|
|||||||
let localContent = undefined;
|
let localContent = undefined;
|
||||||
if (uploadRaw) {
|
if (uploadRaw) {
|
||||||
if (typeof rawContent === "string") {
|
if (typeof rawContent === "string") {
|
||||||
localContent = new TextEncoder().encode(rawContent);
|
localContent = new TextEncoder().encode(rawContent).buffer;
|
||||||
} else {
|
} else {
|
||||||
localContent = rawContent;
|
localContent = rawContent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -690,7 +690,7 @@ export const uploadToRemote = async (
|
|||||||
let localContent = undefined;
|
let localContent = undefined;
|
||||||
if (uploadRaw) {
|
if (uploadRaw) {
|
||||||
if (typeof rawContent === "string") {
|
if (typeof rawContent === "string") {
|
||||||
localContent = new TextEncoder().encode(rawContent);
|
localContent = new TextEncoder().encode(rawContent).buffer;
|
||||||
} else {
|
} else {
|
||||||
localContent = rawContent;
|
localContent = rawContent;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -141,7 +141,7 @@ export const uploadToRemote = async (
|
|||||||
let localContent = undefined;
|
let localContent = undefined;
|
||||||
if (uploadRaw) {
|
if (uploadRaw) {
|
||||||
if (typeof rawContent === "string") {
|
if (typeof rawContent === "string") {
|
||||||
localContent = new TextEncoder().encode(rawContent);
|
localContent = new TextEncoder().encode(rawContent).buffer;
|
||||||
} else {
|
} else {
|
||||||
localContent = rawContent;
|
localContent = rawContent;
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,6 @@ export const listFromRemote = async (
|
|||||||
const contents = [] as _Object[];
|
const contents = [] as _Object[];
|
||||||
|
|
||||||
let isTruncated = true;
|
let isTruncated = true;
|
||||||
let continuationToken = "";
|
|
||||||
do {
|
do {
|
||||||
const rsp = await s3Client.send(new ListObjectsV2Command(confCmd));
|
const rsp = await s3Client.send(new ListObjectsV2Command(confCmd));
|
||||||
|
|
||||||
@@ -206,7 +205,8 @@ export const listFromRemote = async (
|
|||||||
confCmd.ContinuationToken = rsp.NextContinuationToken;
|
confCmd.ContinuationToken = rsp.NextContinuationToken;
|
||||||
if (
|
if (
|
||||||
isTruncated &&
|
isTruncated &&
|
||||||
(continuationToken === undefined || continuationToken === "")
|
(confCmd.ContinuationToken === undefined ||
|
||||||
|
confCmd.ContinuationToken === "")
|
||||||
) {
|
) {
|
||||||
throw Error("isTruncated is true but no continuationToken provided");
|
throw Error("isTruncated is true but no continuationToken provided");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ export const uploadToRemote = async (
|
|||||||
let localContent = undefined;
|
let localContent = undefined;
|
||||||
if (uploadRaw) {
|
if (uploadRaw) {
|
||||||
if (typeof rawContent === "string") {
|
if (typeof rawContent === "string") {
|
||||||
localContent = new TextEncoder().encode(rawContent);
|
localContent = new TextEncoder().encode(rawContent).buffer;
|
||||||
} else {
|
} else {
|
||||||
localContent = rawContent;
|
localContent = rawContent;
|
||||||
}
|
}
|
||||||
|
|||||||
+110
-11
@@ -1,4 +1,11 @@
|
|||||||
import { App, Modal, Notice, PluginSettingTab, Setting } from "obsidian";
|
import {
|
||||||
|
App,
|
||||||
|
Modal,
|
||||||
|
Notice,
|
||||||
|
PluginSettingTab,
|
||||||
|
Setting,
|
||||||
|
Platform,
|
||||||
|
} from "obsidian";
|
||||||
import type { SUPPORTED_SERVICES_TYPE, WebdavAuthType } from "./baseTypes";
|
import type { SUPPORTED_SERVICES_TYPE, WebdavAuthType } from "./baseTypes";
|
||||||
import { exportVaultSyncPlansToFiles } from "./debugMode";
|
import { exportVaultSyncPlansToFiles } from "./debugMode";
|
||||||
import { exportQrCodeUri } from "./importExport";
|
import { exportQrCodeUri } from "./importExport";
|
||||||
@@ -110,17 +117,45 @@ class DropboxAuthModal extends Modal {
|
|||||||
async onOpen() {
|
async onOpen() {
|
||||||
let { contentEl } = this;
|
let { contentEl } = this;
|
||||||
|
|
||||||
const { authUrl, verifier } = await getAuthUrlAndVerifierDropbox(
|
let needManualPatse = false;
|
||||||
this.plugin.settings.dropbox.clientID
|
const userAgent = window.navigator.userAgent.toLocaleLowerCase() || "";
|
||||||
);
|
// some users report that,
|
||||||
this.plugin.oauth2Info.verifier = verifier;
|
// the Linux would open another instance Obsidian if jumping back,
|
||||||
|
// so fallback to manual paste on Linux
|
||||||
|
if (
|
||||||
|
Platform.isDesktopApp &&
|
||||||
|
!Platform.isMacOS &&
|
||||||
|
(/linux/.test(userAgent) ||
|
||||||
|
/ubuntu/.test(userAgent) ||
|
||||||
|
/debian/.test(userAgent) ||
|
||||||
|
/fedora/.test(userAgent) ||
|
||||||
|
/centos/.test(userAgent))
|
||||||
|
) {
|
||||||
|
needManualPatse = true;
|
||||||
|
}
|
||||||
|
|
||||||
contentEl.createEl("p", {
|
const { authUrl, verifier } = await getAuthUrlAndVerifierDropbox(
|
||||||
text: "Visit the address in a browser, and follow the steps.",
|
this.plugin.settings.dropbox.clientID,
|
||||||
});
|
needManualPatse
|
||||||
contentEl.createEl("p", {
|
);
|
||||||
text: "Finally you should be redirected to Obsidian.",
|
|
||||||
});
|
if (needManualPatse) {
|
||||||
|
contentEl.createEl("p", {
|
||||||
|
text: "Step 1: Visit the address in a browser, and follow the steps.",
|
||||||
|
});
|
||||||
|
contentEl.createEl("p", {
|
||||||
|
text: 'Step 2: In the end of the web flow, you obtain a long code. Paste it here then click "Submit".',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.plugin.oauth2Info.verifier = verifier;
|
||||||
|
|
||||||
|
contentEl.createEl("p", {
|
||||||
|
text: "Visit the address in a browser, and follow the steps.",
|
||||||
|
});
|
||||||
|
contentEl.createEl("p", {
|
||||||
|
text: "Finally you should be redirected to Obsidian.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const div2 = contentEl.createDiv();
|
const div2 = contentEl.createDiv();
|
||||||
div2.createEl(
|
div2.createEl(
|
||||||
@@ -140,6 +175,70 @@ class DropboxAuthModal extends Modal {
|
|||||||
href: authUrl,
|
href: authUrl,
|
||||||
text: authUrl,
|
text: authUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (needManualPatse) {
|
||||||
|
let authCode = "";
|
||||||
|
new Setting(contentEl)
|
||||||
|
.setName("Auth Code from web page")
|
||||||
|
.setDesc('You need to click "Confirm".')
|
||||||
|
.addText((text) =>
|
||||||
|
text
|
||||||
|
.setPlaceholder("")
|
||||||
|
.setValue("")
|
||||||
|
.onChange((val) => {
|
||||||
|
authCode = val.trim();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.addButton(async (button) => {
|
||||||
|
button.setButtonText("Confirm");
|
||||||
|
button.onClick(async () => {
|
||||||
|
new Notice("Trying to connect to Dropbox");
|
||||||
|
try {
|
||||||
|
const authRes = await sendAuthReqDropbox(
|
||||||
|
this.plugin.settings.dropbox.clientID,
|
||||||
|
verifier,
|
||||||
|
authCode
|
||||||
|
);
|
||||||
|
const self = this;
|
||||||
|
setConfigBySuccessfullAuthInplace(
|
||||||
|
this.plugin.settings.dropbox,
|
||||||
|
authRes,
|
||||||
|
() => self.plugin.saveSettings()
|
||||||
|
);
|
||||||
|
const client = new RemoteClient(
|
||||||
|
"dropbox",
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
this.plugin.settings.dropbox,
|
||||||
|
undefined,
|
||||||
|
this.app.vault.getName(),
|
||||||
|
() => self.plugin.saveSettings()
|
||||||
|
);
|
||||||
|
const username = await client.getUser();
|
||||||
|
this.plugin.settings.dropbox.username = username;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
new Notice(
|
||||||
|
`Good! We've connected to Dropbox as user ${username}!`
|
||||||
|
);
|
||||||
|
this.authDiv.toggleClass(
|
||||||
|
"dropbox-auth-button-hide",
|
||||||
|
this.plugin.settings.dropbox.username !== ""
|
||||||
|
);
|
||||||
|
this.revokeAuthDiv.toggleClass(
|
||||||
|
"dropbox-revoke-auth-button-hide",
|
||||||
|
this.plugin.settings.dropbox.username === ""
|
||||||
|
);
|
||||||
|
this.revokeAuthSetting.setDesc(
|
||||||
|
`You've connected as user ${this.plugin.settings.dropbox.username}. If you want to disconnect, click this button.`
|
||||||
|
);
|
||||||
|
this.close();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
new Notice("Something goes wrong while connecting to Dropbox.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose() {
|
onClose() {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class SyncAlgoV2Modal extends Modal {
|
|||||||
const texts = [
|
const texts = [
|
||||||
"Welcome to use Remotely Save!",
|
"Welcome to use Remotely Save!",
|
||||||
|
|
||||||
"From this version 0.3.0, a new algorithm has been developed, but it needs uploading extra meta data files _remotely-save-metadata-on-remote.{json,bin} to YOUR configured cloud destinations, besides your notes.",
|
"From version 0.3.0, a new algorithm has been developed, but it needs uploading extra meta data files _remotely-save-metadata-on-remote.{json,bin} to YOUR configured cloud destinations, besides your notes.",
|
||||||
|
|
||||||
"So that, for example, the second device can know that what files/folders have been deleted on the first device by reading those files.",
|
"So that, for example, the second device can know that what files/folders have been deleted on the first device by reading those files.",
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"0.3.0": "0.12.15"
|
"0.3.2": "0.12.15"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user