mirror of
https://github.com/coaidev/coai.git
synced 2025-05-31 10:50:21 +09:00
feat: app offline detection
This commit is contained in:
parent
af91738524
commit
e6f605098a
14
app/src/api/quota.ts
Normal file
14
app/src/api/quota.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export async function getQuota(): Promise<number> {
|
||||||
|
try {
|
||||||
|
const response = await axios.get("/quota");
|
||||||
|
if (response.data.status) {
|
||||||
|
return response.data.quota as number;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.debug(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NaN;
|
||||||
|
}
|
@ -15,6 +15,7 @@ import {
|
|||||||
Boxes,
|
Boxes,
|
||||||
CalendarPlus,
|
CalendarPlus,
|
||||||
Cloud,
|
Cloud,
|
||||||
|
CloudOff,
|
||||||
Cloudy,
|
Cloudy,
|
||||||
Gift,
|
Gift,
|
||||||
ListStart,
|
ListStart,
|
||||||
@ -28,6 +29,7 @@ import { openDialog as openSharingDialog } from "@/store/sharing.ts";
|
|||||||
import { openDialog as openApiDialog } from "@/store/api.ts";
|
import { openDialog as openApiDialog } from "@/store/api.ts";
|
||||||
import router from "@/router.tsx";
|
import router from "@/router.tsx";
|
||||||
import { useDeeptrain } from "@/utils/env.ts";
|
import { useDeeptrain } from "@/utils/env.ts";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
type MenuBarProps = {
|
type MenuBarProps = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@ -48,12 +50,17 @@ function MenuBar({ children, className }: MenuBarProps) {
|
|||||||
<DropdownMenuLabel className={`username`}>{username}</DropdownMenuLabel>
|
<DropdownMenuLabel className={`username`}>{username}</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem onClick={() => dispatch(openQuotaDialog())}>
|
<DropdownMenuItem onClick={() => dispatch(openQuotaDialog())}>
|
||||||
<Cloud className={`h-4 w-4 mr-1`} />
|
{!isNaN(quota) ? (
|
||||||
{quota}
|
<>
|
||||||
</DropdownMenuItem>
|
<Cloud className={`h-4 w-4 mr-1`} />
|
||||||
<DropdownMenuItem onClick={() => dispatch(openQuotaDialog())}>
|
{quota.toFixed(2)}
|
||||||
<Cloudy className={`h-4 w-4 mr-1`} />
|
</>
|
||||||
{t("quota")}
|
) : (
|
||||||
|
<>
|
||||||
|
<CloudOff className={`h-4 w-4 mr-1 text-red-500`} />
|
||||||
|
<p className={`text-red-500`}>{t("offline")}</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => dispatch(openSub())}>
|
<DropdownMenuItem onClick={() => dispatch(openSub())}>
|
||||||
<CalendarPlus className={`h-4 w-4 mr-1`} />
|
<CalendarPlus className={`h-4 w-4 mr-1`} />
|
||||||
|
@ -23,6 +23,7 @@ const resources = {
|
|||||||
logout: "登出",
|
logout: "登出",
|
||||||
quota: "点数",
|
quota: "点数",
|
||||||
download: "下载",
|
download: "下载",
|
||||||
|
offline: "应用离线",
|
||||||
"try-again": "重试",
|
"try-again": "重试",
|
||||||
"invalid-token": "无效的令牌",
|
"invalid-token": "无效的令牌",
|
||||||
"invalid-token-prompt": "请重试。",
|
"invalid-token-prompt": "请重试。",
|
||||||
@ -465,6 +466,7 @@ const resources = {
|
|||||||
logout: "Logout",
|
logout: "Logout",
|
||||||
quota: "Quota",
|
quota: "Quota",
|
||||||
download: "Download",
|
download: "Download",
|
||||||
|
offline: "App offline",
|
||||||
"try-again": "Try again",
|
"try-again": "Try again",
|
||||||
"invalid-token": "Invalid token",
|
"invalid-token": "Invalid token",
|
||||||
"invalid-token-prompt": "Please try again.",
|
"invalid-token-prompt": "Please try again.",
|
||||||
@ -930,6 +932,7 @@ const resources = {
|
|||||||
logout: "Выйти",
|
logout: "Выйти",
|
||||||
quota: "Квота",
|
quota: "Квота",
|
||||||
download: "Скачать",
|
download: "Скачать",
|
||||||
|
offline: "Приложение оффлайн",
|
||||||
"try-again": "Попробуйте еще раз",
|
"try-again": "Попробуйте еще раз",
|
||||||
"invalid-token": "Неверный токен",
|
"invalid-token": "Неверный токен",
|
||||||
"invalid-token-prompt": "Пожалуйста, попробуйте еще раз.",
|
"invalid-token-prompt": "Пожалуйста, попробуйте еще раз.",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createSlice } from "@reduxjs/toolkit";
|
import { createSlice } from "@reduxjs/toolkit";
|
||||||
import { AppDispatch, RootState } from "./index.ts";
|
import { AppDispatch, RootState } from "./index.ts";
|
||||||
import axios from "axios";
|
import { getQuota } from "@/api/quota.ts";
|
||||||
|
|
||||||
export const quotaSlice = createSlice({
|
export const quotaSlice = createSlice({
|
||||||
name: "quota",
|
name: "quota",
|
||||||
@ -47,14 +47,9 @@ export default quotaSlice.reducer;
|
|||||||
export const dialogSelector = (state: RootState): boolean => state.quota.dialog;
|
export const dialogSelector = (state: RootState): boolean => state.quota.dialog;
|
||||||
export const quotaValueSelector = (state: RootState): number =>
|
export const quotaValueSelector = (state: RootState): number =>
|
||||||
state.quota.quota;
|
state.quota.quota;
|
||||||
export const quotaSelector = (state: RootState): string =>
|
export const quotaSelector = (state: RootState): number => state.quota.quota;
|
||||||
state.quota.quota.toFixed(2);
|
|
||||||
|
|
||||||
export const refreshQuota = async (dispatch: AppDispatch) => {
|
export const refreshQuota = async (dispatch: AppDispatch) => {
|
||||||
try {
|
const quota = await getQuota();
|
||||||
const response = await axios.get("/quota");
|
dispatch(setQuota(quota));
|
||||||
if (response.data.status) dispatch(setQuota(response.data.quota));
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user