aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/app/services
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/app/services')
-rw-r--r--FrontEnd/src/app/services/DataHub2.ts60
-rw-r--r--FrontEnd/src/app/services/timeline.ts80
-rw-r--r--FrontEnd/src/app/services/user.ts14
3 files changed, 89 insertions, 65 deletions
diff --git a/FrontEnd/src/app/services/DataHub2.ts b/FrontEnd/src/app/services/DataHub2.ts
index 50ae919b..f0fb724b 100644
--- a/FrontEnd/src/app/services/DataHub2.ts
+++ b/FrontEnd/src/app/services/DataHub2.ts
@@ -32,6 +32,8 @@ export class DataLine2<TData> {
private _current: DataAndStatus<TData> | null = null;
private _observers: Subscriber<DataAndStatus<TData>>[] = [];
+ private _syncPromise: Promise<void> | null = null;
+
get currentData(): DataAndStatus<TData> | null {
return this._current;
}
@@ -50,7 +52,7 @@ export class DataLine2<TData> {
}
subscribe(subsriber: Subscriber<DataAndStatus<TData>>): void {
- this.sync(); // TODO: Should I sync at this point or let the user sync explicitly.
+ void this.sync(); // TODO: Should I sync at this point or let the user sync explicitly.
this._observers.push(subsriber);
const { currentData } = this;
if (currentData != null) {
@@ -76,36 +78,44 @@ export class DataLine2<TData> {
});
}
- sync(): void {
- const { currentData } = this;
- if (currentData != null && currentData.status === "syncing") return;
- this.next({ data: currentData?.data ?? null, status: "syncing" });
- void this.config.getSavedData().then((savedData) => {
- if (currentData == null && savedData != null) {
- this.next({ data: savedData, status: "syncing" });
- }
- return this.config.fetchData(savedData).then((data) => {
- if (data == null) {
- this.next({
- data: savedData,
- status: "offline",
- });
- } else {
- return this.config.saveData(data).then(() => {
- this.next({ data: data, status: "synced" });
- });
- }
- });
+ private syncWithAction(action: () => Promise<void>): Promise<void> {
+ if (this._syncPromise != null) return this._syncPromise;
+ this._syncPromise = action().then(() => {
+ this._syncPromise = null;
});
+ return this._syncPromise;
+ }
+
+ sync(): Promise<void> {
+ return this.syncWithAction(this.doSync.bind(this));
}
- save(data: TData): void {
+ private async doSync(): Promise<void> {
const { currentData } = this;
- if (currentData != null && currentData.status === "syncing") return;
this.next({ data: currentData?.data ?? null, status: "syncing" });
- void this.config.saveData(data).then(() => {
+ const savedData = await this.config.getSavedData();
+ if (currentData == null && savedData != null) {
+ this.next({ data: savedData, status: "syncing" });
+ }
+ const data = await this.config.fetchData(savedData);
+ if (data == null) {
+ this.next({
+ data: savedData,
+ status: "offline",
+ });
+ } else {
+ await this.config.saveData(data);
this.next({ data: data, status: "synced" });
- });
+ }
+ }
+
+ save(data: TData): Promise<void> {
+ return this.syncWithAction(this.doSave.bind(this, data));
+ }
+
+ private async doSave(data: TData): Promise<void> {
+ await this.config.saveData(data);
+ this.next({ data: data, status: "synced" });
}
getSavedData(): Promise<TData | null> {
diff --git a/FrontEnd/src/app/services/timeline.ts b/FrontEnd/src/app/services/timeline.ts
index 8bc1d40b..46671ea1 100644
--- a/FrontEnd/src/app/services/timeline.ts
+++ b/FrontEnd/src/app/services/timeline.ts
@@ -26,6 +26,8 @@ export type { TimelineVisibility } from "@/http/timeline";
import { dataStorage } from "./common";
import { userInfoService, AuthUser } from "./user";
import { DataAndStatus, DataHub2 } from "./DataHub2";
+import { getHttpBookmarkClient } from "@/http/bookmark";
+import { getHttpHighlightClient } from "@/http/highlight";
export type TimelineInfo = HttpTimelineInfo;
export type TimelineChangePropertyRequest = HttpTimelinePatchRequest;
@@ -104,8 +106,9 @@ export class TimelineService {
saveData: async (timelineName, data) => {
if (data === "notexist") return;
- userInfoService.saveUser(data.owner);
- userInfoService.saveUsers(data.members);
+ // TODO: Avoid save same user.
+ void userInfoService.saveUser(data.owner);
+ void userInfoService.saveUsers(data.members);
await dataStorage.setItem<TimelineData>(
this.generateTimelineDataStorageKey(timelineName),
@@ -157,8 +160,8 @@ export class TimelineService {
},
});
- syncTimeline(timelineName: string): void {
- this.timelineHub.getLine(timelineName).sync();
+ syncTimeline(timelineName: string): Promise<void> {
+ return this.timelineHub.getLine(timelineName).sync();
}
createTimeline(timelineName: string): Observable<TimelineInfo> {
@@ -174,15 +177,12 @@ export class TimelineService {
changeTimelineProperty(
timelineName: string,
req: TimelineChangePropertyRequest
- ): Observable<TimelineInfo> {
- return from(
- getHttpTimelineClient()
- .patchTimeline(timelineName, req)
- .then((timeline) => {
- void this.syncTimeline(timelineName);
- return timeline;
- })
- );
+ ): Promise<void> {
+ return getHttpTimelineClient()
+ .patchTimeline(timelineName, req)
+ .then(() => {
+ void this.syncTimeline(timelineName);
+ });
}
deleteTimeline(timelineName: string): Observable<unknown> {
@@ -222,7 +222,7 @@ export class TimelineService {
};
data.posts.forEach((p) => {
- userInfoService.saveUser(p.author);
+ void userInfoService.saveUser(p.author);
});
await dataStorage.setItem<TimelinePostsData>(
@@ -342,31 +342,27 @@ export class TimelineService {
},
});
- syncPosts(timelineName: string): void {
- this.postsHub.getLine(timelineName).sync();
+ syncPosts(timelineName: string): Promise<void> {
+ return this.postsHub.getLine(timelineName).sync();
}
createPost(
timelineName: string,
request: TimelineCreatePostRequest
- ): Observable<unknown> {
- return from(
- getHttpTimelineClient()
- .postPost(timelineName, request)
- .then(() => {
- this.syncPosts(timelineName);
- })
- );
+ ): Promise<void> {
+ return getHttpTimelineClient()
+ .postPost(timelineName, request)
+ .then(() => {
+ void this.syncPosts(timelineName);
+ });
}
- deletePost(timelineName: string, postId: number): Observable<unknown> {
- return from(
- getHttpTimelineClient()
- .deletePost(timelineName, postId)
- .then(() => {
- this.syncPosts(timelineName);
- })
- );
+ deletePost(timelineName: string, postId: number): Promise<void> {
+ return getHttpTimelineClient()
+ .deletePost(timelineName, postId)
+ .then(() => {
+ void this.syncPosts(timelineName);
+ });
}
isMemberOf(username: string, timeline: TimelineInfo): boolean {
@@ -435,6 +431,26 @@ export class TimelineService {
user.username === post.author.username)
);
}
+
+ setHighlight(timelineName: string, highlight: boolean): Promise<void> {
+ const client = getHttpHighlightClient();
+ const promise = highlight
+ ? client.put(timelineName)
+ : client.delete(timelineName);
+ return promise.then(() => {
+ void timelineService.syncTimeline(timelineName);
+ });
+ }
+
+ setBookmark(timelineName: string, bookmark: boolean): Promise<void> {
+ const client = getHttpBookmarkClient();
+ const promise = bookmark
+ ? client.put(timelineName)
+ : client.delete(timelineName);
+ return promise.then(() => {
+ void timelineService.syncTimeline(timelineName);
+ });
+ }
}
export const timelineService = new TimelineService();
diff --git a/FrontEnd/src/app/services/user.ts b/FrontEnd/src/app/services/user.ts
index 5c4e3ae0..611a86ae 100644
--- a/FrontEnd/src/app/services/user.ts
+++ b/FrontEnd/src/app/services/user.ts
@@ -248,12 +248,12 @@ export function checkLogin(): AuthUser {
export class UserNotExistError extends Error {}
export class UserInfoService {
- saveUser(user: HttpUser): void {
- this.userHub.getLine(user.username).save(user);
+ saveUser(user: HttpUser): Promise<void> {
+ return this.userHub.getLine(user.username).save(user);
}
- saveUsers(users: HttpUser[]): void {
- return users.forEach((user) => this.saveUser(user));
+ saveUsers(users: HttpUser[]): Promise<void> {
+ return Promise.all(users.map((user) => this.saveUser(user))).then();
}
async getCachedUser(username: string): Promise<HttpUser | null> {
@@ -351,15 +351,13 @@ export class UserInfoService {
async setAvatar(username: string, blob: Blob): Promise<void> {
const etag = await getHttpUserClient().putAvatar(username, blob);
- this.avatarHub.getLine(username).save({ data: blob, etag });
+ await this.avatarHub.getLine(username).save({ data: blob, etag });
}
async setNickname(username: string, nickname: string): Promise<void> {
return getHttpUserClient()
.patch(username, { nickname })
- .then((user) => {
- this.saveUser(user);
- });
+ .then((user) => this.saveUser(user));
}
}