mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: add max upload size setting to UI & UI improvements (#1646)
* Add preliminar Windows support for both development and production environments. Default profile.Data will be set to "C:\ProgramData\memos" on Windows. Folder will be created if it does not exist, as this behavior is expected for Windows applications. System service installation can be achieved with third-party tools, explained in docs/windows-service.md. Not sure if it's worth using https://github.com/kardianos/service to make service support built-in. This could be a nice addition alongside #1583 (add Windows artifacts) * feat: improve Windows support - Fix local file storage path handling on Windows - Improve Windows dev script * feat: add max upload size setting to UI & more - feat: add max upload size setting to UI - feat: max upload size setting is checked on UI during upload, but also enforced by the server - fix: overflowing mobile layout for Create SSO, Create Storage and other Settings dialogs - feat: add HelpButton component with some links to docs were appropriate - remove LearnMore component in favor of HelpButton - refactor: change some if/else to switch statements - refactor: inline some err == nil checks ! Existing databases without the new setting 'max-upload-size-mib' will show an upload error, but this can be user-fixed by simply setting the value on system settings UI. * improvements requested by @boojack
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, Divider, Input, Switch, Textarea, Typography } from "@mui/joy";
|
||||
import { Button, Divider, Input, Switch, Textarea } from "@mui/joy";
|
||||
import { formatBytes } from "@/helpers/utils";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
import Icon from "../Icon";
|
||||
import HelpButton from "../kit/HelpButton";
|
||||
import showUpdateCustomizedProfileDialog from "../UpdateCustomizedProfileDialog";
|
||||
import "@/less/settings/system-section.less";
|
||||
|
||||
@ -16,6 +16,7 @@ interface State {
|
||||
disablePublicMemos: boolean;
|
||||
additionalStyle: string;
|
||||
additionalScript: string;
|
||||
maxUploadSizeMiB: number;
|
||||
}
|
||||
|
||||
const SystemSection = () => {
|
||||
@ -29,6 +30,7 @@ const SystemSection = () => {
|
||||
additionalStyle: systemStatus.additionalStyle,
|
||||
additionalScript: systemStatus.additionalScript,
|
||||
disablePublicMemos: systemStatus.disablePublicMemos,
|
||||
maxUploadSizeMiB: systemStatus.maxUploadSizeMiB,
|
||||
});
|
||||
const [openAIConfig, setOpenAIConfig] = useState<OpenAIConfig>({
|
||||
key: "",
|
||||
@ -56,6 +58,7 @@ const SystemSection = () => {
|
||||
additionalStyle: systemStatus.additionalStyle,
|
||||
additionalScript: systemStatus.additionalScript,
|
||||
disablePublicMemos: systemStatus.disablePublicMemos,
|
||||
maxUploadSizeMiB: systemStatus.maxUploadSizeMiB,
|
||||
});
|
||||
}, [systemStatus]);
|
||||
|
||||
@ -175,6 +178,30 @@ const SystemSection = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const handleMaxUploadSizeChanged = async (event: React.FocusEvent<HTMLInputElement>) => {
|
||||
// fixes cursor skipping position on mobile
|
||||
event.target.selectionEnd = event.target.value.length;
|
||||
|
||||
let num = parseInt(event.target.value);
|
||||
if (Number.isNaN(num)) {
|
||||
num = 0;
|
||||
}
|
||||
setState({
|
||||
...state,
|
||||
maxUploadSizeMiB: num,
|
||||
});
|
||||
event.target.value = num.toString();
|
||||
globalStore.setSystemStatus({ maxUploadSizeMiB: num });
|
||||
await api.upsertSystemSetting({
|
||||
name: "max-upload-size-mib",
|
||||
value: JSON.stringify(num),
|
||||
});
|
||||
};
|
||||
|
||||
const handleMaxUploadSizeFocus = (event: React.FocusEvent<HTMLInputElement>) => {
|
||||
event.target.select();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="section-container system-section-container">
|
||||
<p className="title-text">{t("common.basic")}</p>
|
||||
@ -185,7 +212,7 @@ const SystemSection = () => {
|
||||
<Button onClick={handleUpdateCustomizedProfileButtonClick}>{t("common.edit")}</Button>
|
||||
</div>
|
||||
<div className="form-label">
|
||||
<span className="normal-text">
|
||||
<span className="text-sm">
|
||||
{t("setting.system-section.database-file-size")}: <span className="font-mono font-bold">{formatBytes(state.dbSize)}</span>
|
||||
</span>
|
||||
<Button onClick={handleVacuumBtnClick}>{t("common.vacuum")}</Button>
|
||||
@ -203,19 +230,27 @@ const SystemSection = () => {
|
||||
<span className="normal-text">{t("setting.system-section.disable-public-memos")}</span>
|
||||
<Switch checked={state.disablePublicMemos} onChange={(event) => handleDisablePublicMemosChanged(event.target.checked)} />
|
||||
</div>
|
||||
<div className="form-label">
|
||||
<div className="flex flex-row">
|
||||
<span className="normal-text">{t("setting.system-section.max-upload-size")}</span>
|
||||
<HelpButton icon="info" hint={t("setting.system-section.max-upload-size-hint")} hintPlacement="left" />
|
||||
</div>
|
||||
<Input
|
||||
className="w-16"
|
||||
sx={{
|
||||
fontFamily: "monospace",
|
||||
}}
|
||||
defaultValue={state.maxUploadSizeMiB}
|
||||
onFocus={handleMaxUploadSizeFocus}
|
||||
onChange={handleMaxUploadSizeChanged}
|
||||
/>
|
||||
</div>
|
||||
<Divider className="!mt-3 !my-4" />
|
||||
<div className="form-label">
|
||||
<span className="normal-text">{t("setting.system-section.openai-api-key")}</span>
|
||||
<Typography className="!mb-1" level="body2">
|
||||
<a
|
||||
className="ml-2 text-sm text-blue-600 hover:opacity-80 hover:underline"
|
||||
href="https://platform.openai.com/account/api-keys"
|
||||
target="_blank"
|
||||
>
|
||||
{t("setting.system-section.openai-api-key-description")}
|
||||
<Icon.ExternalLink className="inline -mt-1 ml-1 w-4 h-auto opacity-80" />
|
||||
</a>
|
||||
</Typography>
|
||||
<div className="flex flex-row">
|
||||
<span className="normal-text">{t("setting.system-section.openai-api-key")}</span>
|
||||
<HelpButton hint={t("setting.system-section.openai-api-key-description")} url="https://platform.openai.com/account/api-keys" />
|
||||
</div>
|
||||
<Button onClick={handleSaveOpenAIConfig}>{t("common.save")}</Button>
|
||||
</div>
|
||||
<Input
|
||||
|
Reference in New Issue
Block a user