refactor webApi
This commit is contained in:
@@ -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}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
|
||||
Reference in New Issue
Block a user