refactor webApi

This commit is contained in:
an-lee
2024-01-11 17:36:23 +08:00
parent 94d4a0a338
commit 66cf3dd828
11 changed files with 62 additions and 52 deletions

View File

@@ -6,9 +6,11 @@ const ONE_MINUTE = 1000 * 60; // 1 minute
export class Client {
public api: AxiosInstance;
public baseUrl: string;
constructor(options: { baseUrl: string; accessToken?: string }) {
const { baseUrl, accessToken } = options;
this.baseUrl = baseUrl;
this.api = axios.create({
baseURL: baseUrl,
@@ -20,7 +22,7 @@ export class Client {
this.api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${accessToken}`;
console.info(
console.debug(
config.method.toUpperCase(),
config.baseURL + config.url,
config.data,
@@ -30,7 +32,7 @@ export class Client {
});
this.api.interceptors.response.use(
(response) => {
console.info(
console.debug(
response.status,
response.config.method.toUpperCase(),
response.config.baseURL + response.config.url
@@ -63,7 +65,7 @@ export class Client {
return this.api.post("/api/sessions", decamelizeKeys(params));
}
me() {
me(): Promise<UserType> {
return this.api.get("/api/me");
}
@@ -151,7 +153,7 @@ export class Client {
sourceId?: string;
sourceType?: string;
}[]
): Promise<{ successCount: number; total: number }> {
): Promise<{ successCount: number; errors: string[], total: number }> {
return this.api.post("/api/lookups/batch", {
lookups: decamelizeKeys(lookups, { deep: true }),
});
@@ -171,6 +173,7 @@ export class Client {
): Promise<
{
meanings: MeaningType[];
pendingLookups?: LookupType[];
} & PagyResponseType
> {
return this.api.get(`/api/stories/${storyId}/meanings`, {
@@ -220,11 +223,11 @@ export class Client {
});
}
starStory(storyId: string) {
starStory(storyId: string): Promise<{ starred: boolean }> {
return this.api.post(`/api/mine/stories`, decamelizeKeys({ storyId }));
}
unstarStory(storyId: string) {
unstarStory(storyId: string): Promise<{ starred: boolean }> {
return this.api.delete(`/api/mine/stories/${storyId}`);
}
}

View File

@@ -5,10 +5,10 @@ import { t } from "i18next";
export const LoginForm = () => {
const { toast } = useToast();
const { EnjoyApp, login, apiUrl } = useContext(AppSettingsProviderContext);
const { EnjoyApp, login, webApi } = useContext(AppSettingsProviderContext);
const handleMixinLogin = () => {
const url = `${apiUrl}/sessions/new?provider=mixin`;
const url = `${webApi.baseUrl}/sessions/new?provider=mixin`;
EnjoyApp.view.load(url, { x: 0, y: 0 });
};
@@ -34,7 +34,7 @@ export const LoginForm = () => {
const provider = new URL(url).pathname.split("/")[2];
const code = new URL(url).searchParams.get("code");
if (!url.startsWith(apiUrl)) {
if (!url.startsWith(webApi.baseUrl)) {
toast({
title: t("error"),
description: t("invalidRedirectUrl"),
@@ -44,7 +44,7 @@ export const LoginForm = () => {
}
if (provider && code) {
EnjoyApp.webApi
webApi
.auth({ provider, code })
.then((user) => {
login(user);
@@ -70,7 +70,7 @@ export const LoginForm = () => {
EnjoyApp.view.removeViewStateListeners();
EnjoyApp.view.remove();
};
}, [apiUrl]);
}, [webApi]);
return (
<div className="w-full max-w-sm px-6 flex flex-col space-y-4">

View File

@@ -18,7 +18,7 @@ export const LookupResult = (props: {
const [loading, setLoading] = useState<boolean>(true);
if (!word) return null;
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const lookup = (retries = 0) => {
if (!word) return;
@@ -28,7 +28,7 @@ export const LookupResult = (props: {
}
retries += 1;
EnjoyApp.webApi
webApi
.lookup({
word,
context,

View File

@@ -1,19 +1,13 @@
import { useContext, useEffect, useState } from "react";
import { Client } from "@/api";
import { AppSettingsProviderContext } from "@renderer/context";
import { t } from "i18next";
export const Posts = () => {
const { apiUrl, user } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const [posts, setPosts] = useState<PostType[]>([]);
const client = new Client({
baseUrl: apiUrl,
accessToken: user.accessToken,
});
const fetchPosts = async () => {
client.posts().then(
webApi.posts().then(
(res) => {
setPosts(res.posts);
},

View File

@@ -7,10 +7,10 @@ import { AppSettingsProviderContext } from "@renderer/context";
export const StoriesSegment = () => {
const [stories, setStorys] = useState<StoryType[]>([]);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const fetchStorys = async () => {
EnjoyApp.webApi.mineStories().then((response) => {
webApi.mineStories().then((response) => {
if (response?.stories) {
setStorys(response.stories);
}

View File

@@ -8,7 +8,6 @@ import {
CardHeader,
CardContent,
} from "@renderer/components/ui";
import { Client } from "@/api";
import { AppSettingsProviderContext } from "@renderer/context";
import { t } from "i18next";
import { formatDuration } from "@renderer/lib/utils";
@@ -28,16 +27,11 @@ const RankingsCard = (props: {
range: "day" | "week" | "month" | "year" | "all";
}) => {
const { range } = props;
const { apiUrl, user } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const [rankings, setRankings] = useState<UserType[]>([]);
const client = new Client({
baseUrl: apiUrl,
accessToken: user.accessToken,
});
const fetchRankings = async () => {
client.rankings(range).then(
webApi.rankings(range).then(
(res) => {
setRankings(res.rankings);
},

View File

@@ -1,8 +1,9 @@
import { createContext, useEffect, useState } from "react";
import { WEB_API_URL } from "@/constants";
import { Client } from "@/api";
type AppSettingsProviderState = {
apiUrl: string;
webApi: Client;
user: UserType | null;
initialized: boolean;
version?: string;
@@ -19,7 +20,7 @@ type AppSettingsProviderState = {
};
const initialState: AppSettingsProviderState = {
apiUrl: WEB_API_URL,
webApi: null,
user: null,
initialized: false,
};
@@ -35,6 +36,7 @@ export const AppSettingsProvider = ({
const [initialized, setInitialized] = useState<boolean>(false);
const [version, setVersion] = useState<string>("");
const [apiUrl, setApiUrl] = useState<string>(WEB_API_URL);
const [webApi, setWebApi] = useState<Client>(null);
const [user, setUser] = useState<UserType | null>(null);
const [libraryPath, setLibraryPath] = useState("");
const [whisperModelsPath, setWhisperModelsPath] = useState<string>("");
@@ -48,7 +50,6 @@ export const AppSettingsProvider = ({
fetchLibraryPath();
fetchModel();
fetchFfmpegConfig();
fetchApiUrl();
}, []);
useEffect(() => {
@@ -59,6 +60,17 @@ export const AppSettingsProvider = ({
validate();
}, [user, libraryPath, whisperModel, ffmpegConfig]);
useEffect(() => {
if (!apiUrl) return;
setWebApi(
new Client({
baseUrl: apiUrl,
accessToken: user?.accessToken,
})
);
}, [user, apiUrl]);
const fetchFfmpegConfig = async () => {
const config = await EnjoyApp.settings.getFfmpegConfig();
setFfmegConfig(config);
@@ -70,10 +82,18 @@ export const AppSettingsProvider = ({
};
const fetchUser = async () => {
const apiUrl = await EnjoyApp.app.apiUrl();
setApiUrl(apiUrl);
const currentUser = await EnjoyApp.settings.getUser();
if (!currentUser) return;
EnjoyApp.webApi.me().then((user) => {
const client = new Client({
baseUrl: apiUrl,
accessToken: currentUser.accessToken,
});
client.me().then((user) => {
if (user?.id) {
login(currentUser);
} else {
@@ -113,9 +133,8 @@ export const AppSettingsProvider = ({
};
const fetchApiUrl = async () => {
const apiUrl = await EnjoyApp.app.apiUrl();
setApiUrl(apiUrl);
}
return apiUrl;
};
const setModelHandler = async (name: string) => {
await EnjoyApp.settings.setWhisperModel(name);
@@ -133,7 +152,7 @@ export const AppSettingsProvider = ({
value={{
EnjoyApp,
version,
apiUrl,
webApi,
user,
login,
logout,

View File

@@ -5,10 +5,10 @@ import { AppSettingsProviderContext } from "@renderer/context";
export default () => {
const [stories, setStorys] = useState<StoryType[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const fetchStorys = async () => {
EnjoyApp.webApi
webApi
.mineStories()
.then((response) => {
if (response?.stories) {

View File

@@ -26,7 +26,7 @@ export default () => {
});
const [loading, setLoading] = useState(true);
const [readable, setReadable] = useState(true);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { EnjoyApp, webApi } = useContext(AppSettingsProviderContext);
const { toast } = useToast();
const [meanings, setMeanings] = useState<MeaningType[]>([]);
const [marked, setMarked] = useState<boolean>(false);
@@ -52,7 +52,7 @@ export default () => {
const createStory = async () => {
if (!story) return;
EnjoyApp.webApi
webApi
.createStory({
url: story.metadata?.url || story.url,
...story,

View File

@@ -16,7 +16,7 @@ nlp.plugin(paragraphs);
let timeout: NodeJS.Timeout = null;
export default () => {
const { id } = useParams<{ id: string }>();
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const [loading, setLoading] = useState<boolean>(true);
const [story, setStory] = useState<StoryType>();
const [meanings, setMeanings] = useState<MeaningType[]>([]);
@@ -26,7 +26,7 @@ export default () => {
const [doc, setDoc] = useState<any>(null);
const fetchStory = async () => {
EnjoyApp.webApi
webApi
.story(id)
.then((story) => {
setStory(story);
@@ -41,7 +41,7 @@ export default () => {
const fetchMeanings = async () => {
setScanning(true);
EnjoyApp.webApi
webApi
.storyMeanings(id, { items: 500 })
.then((response) => {
if (!response) return;
@@ -88,14 +88,14 @@ export default () => {
});
});
EnjoyApp.webApi.lookupInBatch(vocabulary).then((response) => {
webApi.lookupInBatch(vocabulary).then((response) => {
const { errors } = response;
if (errors.length > 0) {
console.warn(errors);
return;
}
EnjoyApp.webApi.extractVocabularyFromStory(id).then(() => {
webApi.extractVocabularyFromStory(id).then(() => {
fetchStory();
if (pendingLookups.length > 0) return;
@@ -108,11 +108,11 @@ export default () => {
if (!story) return;
if (story.starred) {
EnjoyApp.webApi.unstarStory(id).then((result) => {
webApi.unstarStory(id).then((result) => {
setStory({ ...story, starred: result.starred });
});
} else {
EnjoyApp.webApi.starStory(id).then((result) => {
webApi.starStory(id).then((result) => {
setStory({ ...story, starred: result.starred });
});
}

View File

@@ -11,14 +11,14 @@ export default () => {
const [loading, setLoading] = useState<boolean>(false);
const [meanings, setMeanings] = useState<MeaningType[]>([]);
const { EnjoyApp } = useContext(AppSettingsProviderContext);
const { webApi } = useContext(AppSettingsProviderContext);
const [currentIndex, setCurrentIndex] = useState<number>(0);
const [nextPage, setNextPage] = useState(1);
const fetchMeanings = async (page: number = nextPage) => {
if (!page) return;
EnjoyApp.webApi
webApi
.mineMeanings({ page, items: 10 })
.then((response) => {
setMeanings([...meanings, ...response.meanings]);