Skip to content

Commit a0094c0

Browse files
authored
Merge pull request #14 from frontend-engineering/pending-view
Pending view
2 parents 583f8e1 + bebe4bc commit a0094c0

18 files changed

+1969
-42
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"@typescript-eslint/parser": "5.29.0",
8484
"acorn": "^8.7.1",
8585
"aggregate-error": "^4.0.0",
86+
"antd": "^5.11.4",
8687
"assert": "^2.0.0",
8788
"aws-crt": "^1.12.1",
8889
"buffer": "^6.0.3",

pnpm-lock.yaml

Lines changed: 994 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/baseTypes.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ export interface InvioPluginSettings {
100100
currLogLevel?: string;
101101
autoRunEveryMilliseconds?: number;
102102
initRunAfterMilliseconds?: number;
103+
104+
autoCheckEveryMilliseconds?: number;
105+
initCheckAfterMilliseconds?: number;
103106
agreeToUploadExtraMetadata?: boolean;
104107
concurrency?: number;
105108
syncConfigDir?: boolean;
@@ -217,4 +220,5 @@ export const DEFAULT_SYNC_PLANS_HISTORY_FILE_PREFIX =
217220
"sync_plans_hist_exported_on_";
218221
export const DEFAULT_LOG_HISTORY_FILE_PREFIX = "log_hist_exported_on_";
219222

220-
export type SyncTriggerSourceType = "manual" | "auto" | "dry" | "autoOnceInit" | "force";
223+
// pre - only check pending files but no more actions
224+
export type SyncTriggerSourceType = "manual" | "auto" | "dry" | "autoOnceInit" | "force" | "pre";

src/components/CheckSettingsModal.ts

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
import { App, Modal, Setting, setIcon, Notice } from "obsidian";
2+
import type { TextComponent } from "obsidian";
3+
import type InvioPlugin from "../main"; // unavoidable
4+
import type { TransItemType } from "../i18n";
5+
import svg from '../utils/svg';
6+
import { InvioSettingTab } from '../settings'
7+
import { RemoteClient } from "../remote";
8+
9+
const wrapTextWithPasswordHide = (text: TextComponent) => {
10+
const hider = text.inputEl.insertAdjacentElement("afterend", createSpan()) as HTMLSpanElement;
11+
setIcon(hider, "eye-off");
12+
hider.addEventListener("click", (e) => {
13+
const isText = text.inputEl.getAttribute("type") === "text";
14+
if(isText) {
15+
setIcon(hider, "eye-off");
16+
text.inputEl.setAttribute("type", "password");
17+
} else {
18+
setIcon(hider, "eye");
19+
text.inputEl.setAttribute("type", "text");
20+
}
21+
});
22+
// the init type of text el is password
23+
text.inputEl.setAttribute("type", "password");
24+
return text;
25+
};
26+
export class CheckSettingsModal extends Modal {
27+
readonly plugin: InvioPlugin;
28+
detailed: boolean;
29+
constructor(app: App, plugin: InvioPlugin) {
30+
super(app);
31+
this.plugin = plugin;
32+
this.detailed = false;
33+
}
34+
35+
info(msg: string) {
36+
let { contentEl } = this;
37+
let container = contentEl.querySelector('.loading-logs');
38+
if (!container) {
39+
container = contentEl.createDiv('loading-logs');
40+
}
41+
const logItem = container.createDiv('loading-log-item');
42+
logItem.innerText = msg;
43+
}
44+
45+
onOpen() {
46+
let { contentEl } = this;
47+
const t = (x: TransItemType, vars?: any) => {
48+
return this.plugin.i18n.t(x, vars);
49+
};
50+
51+
contentEl.createEl("h2", {
52+
text: t('settings_check_modal_title')
53+
});
54+
55+
new Setting(contentEl)
56+
.setDesc(t('settings_check_modal_desc'))
57+
58+
new Setting(contentEl)
59+
.setName(t("settings_autocheck"))
60+
.setDesc(t("settings_autocheck_desc"))
61+
.addDropdown((dropdown) => {
62+
dropdown.addOption("-1", t("settings_autocheck_notset"));
63+
dropdown.addOption(`${1000 * 60 * 1}`, t("settings_autocheck_1min"));
64+
dropdown.addOption(`${1000 * 60 * 5}`, t("settings_autocheck_5min"));
65+
dropdown.addOption(`${1000 * 60 * 10}`, t("settings_autocheck_10min"));
66+
dropdown.addOption(`${1000 * 60 * 30}`, t("settings_autocheck_30min"));
67+
68+
69+
dropdown
70+
.setValue(`${this.plugin.settings.autoCheckEveryMilliseconds}`)
71+
.onChange(async (val: string) => {
72+
const realVal = parseInt(val);
73+
this.plugin.settings.autoCheckEveryMilliseconds = realVal;
74+
await this.plugin.saveSettings();
75+
if (
76+
(realVal === undefined || realVal === null || realVal <= 0) &&
77+
this.plugin.autoCheckIntervalID !== undefined
78+
) {
79+
// clear
80+
window.clearInterval(this.plugin.autoCheckIntervalID);
81+
this.plugin.autoCheckIntervalID = undefined;
82+
} else if (
83+
realVal !== undefined &&
84+
realVal !== null &&
85+
realVal > 0
86+
) {
87+
const intervalID = window.setInterval(() => {
88+
this.plugin.pendingView();
89+
}, realVal);
90+
this.plugin.autoCheckIntervalID = intervalID;
91+
this.plugin.registerInterval(intervalID);
92+
}
93+
});
94+
});
95+
96+
new Setting(contentEl)
97+
.setName(t("settings_checkoncestartup"))
98+
.setDesc(t("settings_checkoncestartup_desc"))
99+
.addDropdown((dropdown) => {
100+
dropdown.addOption("-1", t("settings_checkoncestartup_notset"));
101+
dropdown.addOption(
102+
`${1000 * 1 * 1}`,
103+
t("settings_checkoncestartup_1sec")
104+
);
105+
dropdown.addOption(
106+
`${1000 * 10 * 1}`,
107+
t("settings_checkoncestartup_10sec")
108+
);
109+
dropdown.addOption(
110+
`${1000 * 30 * 1}`,
111+
t("settings_checkoncestartup_30sec")
112+
);
113+
dropdown
114+
.setValue(`${this.plugin.settings.initCheckAfterMilliseconds}`)
115+
.onChange(async (val: string) => {
116+
const realVal = parseInt(val);
117+
this.plugin.settings.initCheckAfterMilliseconds = realVal;
118+
await this.plugin.saveSettings();
119+
});
120+
});
121+
122+
if (!this.detailed) {
123+
new Setting(contentEl)
124+
.setName(t('settings_check_modal_more'))
125+
.setDesc(t('settings_check_modal_more_desc'))
126+
.addButton(async (button) => {
127+
button.setButtonText(t('settings_check_modal_more_btn'));
128+
button.onClick(async () => {
129+
this.close();
130+
// (this.plugin.app as any).setting.open()
131+
// const settingTab = new InvioSettingTab(this.plugin.app, this.plugin);
132+
// settingTab.display();
133+
this.close()
134+
this.detailed = true;
135+
setTimeout(() => {
136+
this.open()
137+
}, 50)
138+
});
139+
})
140+
}
141+
142+
if (this.detailed) {
143+
const s3Div = contentEl.createEl("div", { cls: 'settings-config-section' });
144+
s3Div.createEl('h2', { text: t('settings_host_self_settings'), cls: 'settings-pub-header' });
145+
146+
new Setting(s3Div)
147+
.setName(t("settings_s3_endpoint"))
148+
.setDesc(t("settings_s3_endpoint"))
149+
.addText((text) =>
150+
text
151+
.setPlaceholder("")
152+
.setValue(this.plugin.settings.s3.s3Endpoint)
153+
.onChange(async (value) => {
154+
this.plugin.settings.s3.s3Endpoint = value.trim();
155+
await this.plugin.saveSettings();
156+
})
157+
);
158+
159+
new Setting(s3Div)
160+
.setName(t("settings_s3_region"))
161+
.setDesc(t("settings_s3_region_desc"))
162+
.addText((text) =>
163+
text
164+
.setPlaceholder("")
165+
.setValue(`${this.plugin.settings.s3.s3Region}`)
166+
.onChange(async (value) => {
167+
this.plugin.settings.s3.s3Region = value.trim();
168+
await this.plugin.saveSettings();
169+
})
170+
);
171+
172+
new Setting(s3Div)
173+
.setName(t("settings_s3_accesskeyid"))
174+
.setDesc(t("settings_s3_accesskeyid_desc"))
175+
.addText((text) => {
176+
wrapTextWithPasswordHide(text);
177+
text
178+
.setPlaceholder("")
179+
.setValue(`${this.plugin.settings.s3.s3AccessKeyID}`)
180+
.onChange(async (value) => {
181+
this.plugin.settings.s3.s3AccessKeyID = value.trim();
182+
await this.plugin.saveSettings();
183+
});
184+
});
185+
186+
new Setting(s3Div)
187+
.setName(t("settings_s3_secretaccesskey"))
188+
.setDesc(t("settings_s3_secretaccesskey_desc"))
189+
.addText((text) => {
190+
wrapTextWithPasswordHide(text);
191+
text
192+
.setPlaceholder("")
193+
.setValue(`${this.plugin.settings.s3.s3SecretAccessKey}`)
194+
.onChange(async (value) => {
195+
this.plugin.settings.s3.s3SecretAccessKey = value.trim();
196+
await this.plugin.saveSettings();
197+
});
198+
});
199+
200+
new Setting(s3Div)
201+
.setName(t("settings_s3_bucketname"))
202+
.setDesc(t("settings_s3_bucketname"))
203+
.addText((text) =>
204+
text
205+
.setPlaceholder("")
206+
.setValue(`${this.plugin.settings.s3.s3BucketName}`)
207+
.onChange(async (value) => {
208+
this.plugin.settings.s3.s3BucketName = value.trim();
209+
await this.plugin.saveSettings();
210+
})
211+
);
212+
213+
let remoteDomain = `${this.plugin.settings.remoteDomain}`;
214+
new Setting(s3Div)
215+
.setName(t("settings_domain"))
216+
.setDesc(t("settings_domain_desc"))
217+
.addText((text) => {
218+
text
219+
.setPlaceholder("https://docs.google.com")
220+
.setValue(`${this.plugin.settings.remoteDomain || ''}`)
221+
.onChange(async (value) => {
222+
remoteDomain = value.trim();
223+
});
224+
})
225+
.addButton(async (button) => {
226+
button.setButtonText(t("confirm"));
227+
button.onClick(async () => {
228+
this.plugin.settings.remoteDomain = remoteDomain
229+
await this.plugin.saveSettings();
230+
console.log('new domain: ', t("settings_domain_saved") + " " + remoteDomain)
231+
new Notice(t("settings_domain_saved") + " " + remoteDomain)
232+
});
233+
});
234+
235+
new Setting(s3Div)
236+
.setName(t("settings_checkonnectivity"))
237+
.setDesc(t("settings_checkonnectivity_desc"))
238+
.addButton(async (button) => {
239+
button.setButtonText(t("settings_checkonnectivity_button"));
240+
button.onClick(async () => {
241+
new Notice(t("settings_checkonnectivity_checking"));
242+
const client = new RemoteClient("s3", this.plugin.settings.s3);
243+
const errors = { msg: "" };
244+
const res = await client.checkConnectivity((err: any) => {
245+
errors.msg = err;
246+
});
247+
if (res) {
248+
new Notice(t("settings_s3_connect_succ"));
249+
} else {
250+
new Notice(t("settings_s3_connect_fail"));
251+
new Notice(errors.msg);
252+
}
253+
});
254+
});
255+
}
256+
257+
new Setting(contentEl)
258+
.addButton((button) => {
259+
button.setButtonText('OK');
260+
button.onClick(async () => {
261+
this.close();
262+
});
263+
})
264+
}
265+
266+
onClose() {
267+
let { contentEl } = this;
268+
contentEl.empty();
269+
}
270+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
.header {
2+
text-align: center;
3+
width: 100%;
4+
display: flex;
5+
justify-content: center;
6+
align-items: center;
7+
}
8+
9+
.sub-header {
10+
margin: 8px;
11+
font-weight: bold;
12+
}
13+
14+
.header > .icon {
15+
margin-right: 6px;
16+
}
17+
18+
.header > .settings {
19+
position: absolute;
20+
right: 14px;
21+
width: 18px;
22+
height: 18px;
23+
cursor: pointer;
24+
margin-top: 4px;
25+
transition: all;
26+
transition-duration: 0.3s;
27+
}
28+
.header > .settings:hover {
29+
transform: rotateZ(45deg);
30+
31+
}
32+
.empty-report {
33+
display: flex;
34+
flex-direction: column;
35+
margin-top: 12px;
36+
justify-content: center;
37+
align-items: center;
38+
margin-bottom: 18px;
39+
opacity: 0.75;
40+
}
41+
42+
.empty-report > .icon {
43+
width: 32px;
44+
height: 32px;
45+
opacity: 0.1;
46+
}
47+
48+
.empty-report > span {
49+
margin-top: 22px;
50+
}
51+
52+
53+
.icon {
54+
width: 16px;
55+
height: 16px;
56+
}
57+
58+
.actions {
59+
display: flex;
60+
justify-content: center;
61+
margin-top: 22px;
62+
}
63+
64+
.actions > button {
65+
/* color: white; */
66+
color: var(--text-normal);
67+
}

0 commit comments

Comments
 (0)