added private app name and logo

This commit is contained in:
PhilReact 2025-02-06 00:40:41 +02:00
parent 16b7ed2dbc
commit 76eb315b9d
4 changed files with 69 additions and 13 deletions

View File

@ -9,7 +9,7 @@ import {
PublishQAppChoseFile, PublishQAppChoseFile,
PublishQAppInfo, PublishQAppInfo,
} from "./Apps-styles"; } from "./Apps-styles";
import { Avatar, Box, Button, ButtonBase, Dialog, DialogActions, DialogContent, DialogTitle, Input, MenuItem, Select, Tab, Tabs } from "@mui/material"; import { Avatar, Box, Button, ButtonBase, Dialog, DialogActions, DialogContent, DialogTitle, Input, MenuItem, Select, Tab, Tabs, Typography } from "@mui/material";
import { Add } from "@mui/icons-material"; import { Add } from "@mui/icons-material";
import { getBaseApiReact, isMobile, MyContext } from "../../App"; import { getBaseApiReact, isMobile, MyContext } from "../../App";
import LogoSelected from "../../assets/svgs/LogoSelected.svg"; import LogoSelected from "../../assets/svgs/LogoSelected.svg";
@ -25,6 +25,9 @@ import { saveToLocalStorage } from "./AppsNavBarDesktop";
import { Label } from "../Group/AddGroup"; import { Label } from "../Group/AddGroup";
import { useHandlePrivateApps } from "./useHandlePrivateApps"; import { useHandlePrivateApps } from "./useHandlePrivateApps";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import ImageUploader from "../../common/ImageUploader";
import { base64ToBlobUrl, fileToBase64 } from "../../utils/fileReading";
import { objectToBase64 } from "../../qdn/encryption/group-encryption";
const maxFileSize = 50 * 1024 * 1024 ; // 50MB or 400MB const maxFileSize = 50 * 1024 * 1024 ; // 50MB or 400MB
@ -37,6 +40,7 @@ export const AppsHomeDesktop = ({
}) => { }) => {
const {openApp} = useHandlePrivateApps() const {openApp} = useHandlePrivateApps()
const [file, setFile] = useState(null) const [file, setFile] = useState(null)
const [logo, setLogo] = useState(null)
const { getRootProps, getInputProps } = useDropzone({ const { getRootProps, getInputProps } = useDropzone({
accept: { accept: {
"application/zip": [".zip"], // Only accept zip files "application/zip": [".zip"], // Only accept zip files
@ -91,7 +95,8 @@ const [myGroupsWhereIAmAdmin, setMyGroupsWhereIAmAdmin] = useRecoilState(
const [newPrivateAppValues, setNewPrivateAppValues] = useState({ const [newPrivateAppValues, setNewPrivateAppValues] = useState({
service: 'DOCUMENT', service: 'DOCUMENT',
identifier: '' identifier: '',
name: '',
}) })
const addPrivateApp = async ()=> { const addPrivateApp = async ()=> {
@ -114,23 +119,35 @@ const [myGroupsWhereIAmAdmin, setMyGroupsWhereIAmAdmin] = useRecoilState(
}) })
setNewPrivateAppValues({ setNewPrivateAppValues({
service: 'DOCUMENT', service: 'DOCUMENT',
identifier: '' identifier: '',
name: ''
}) })
setFile(null) setFile(null)
setValueTabPrivateApp(0) setValueTabPrivateApp(0)
setSelectedGroup(null) setSelectedGroup(0)
setLogo(null)
} }
const publishPrivateApp = async ()=> { const publishPrivateApp = async ()=> {
try { try {
if(selectedGroup === 0) return if(selectedGroup === 0) return
if(!logo) throw new Error('Please select an image for a logo')
if(!myName) throw new Error('You need a Qortal name to publish') if(!myName) throw new Error('You need a Qortal name to publish')
if(!newPrivateAppValues?.name) throw new Error('Your app needs a name')
const base64Logo = await fileToBase64(logo)
const base64App = await fileToBase64(file)
const objectToSave = {
app: base64App,
logo: base64Logo,
name: newPrivateAppValues.name
}
const object64 = await objectToBase64(objectToSave);
const decryptedData = await window.sendMessage( const decryptedData = await window.sendMessage(
"ENCRYPT_QORTAL_GROUP_DATA", "ENCRYPT_QORTAL_GROUP_DATA",
{ {
file: file, base64: object64,
groupId: selectedGroup, groupId: selectedGroup,
} }
); );
@ -598,6 +615,35 @@ service: 'DOCUMENT',
})} })}
/> />
</Box> </Box>
<Spacer height="10px"/>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: "5px",
marginTop: "15px",
}}
>
<Label>App name</Label>
<Input
placeholder="App name"
value={newPrivateAppValues?.name}
onChange={(e) => setNewPrivateAppValues((prev)=> {
return {
...prev,
name: e.target.value
}
})}
/>
</Box>
<Spacer height="10px" />
<ImageUploader onPick={(file) => setLogo(file)}>
<Button variant="contained">Choose logo</Button>
</ImageUploader>
{logo?.name}
<Spacer height="25px" />
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button variant="contained" onClick={()=> { <Button variant="contained" onClick={()=> {

View File

@ -58,7 +58,7 @@ const SortableItem = ({ id, name, app, isDesktop }) => {
border: "none", border: "none",
}} }}
> >
{app?.isPrivate ? ( {app?.isPrivate && !app?.privateAppProperties?.logo ? (
<LockIcon <LockIcon
sx={{ sx={{
height: "42px", height: "42px",
@ -75,7 +75,7 @@ const SortableItem = ({ id, name, app, isDesktop }) => {
} }
}} }}
alt={app?.metadata?.title || app?.name} alt={app?.metadata?.title || app?.name}
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${ src={ app?.privateAppProperties?.logo ? app?.privateAppProperties?.logo :`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
app?.name app?.name
}/qortal_avatar?async=true`} }/qortal_avatar?async=true`}
> >
@ -93,7 +93,7 @@ const SortableItem = ({ id, name, app, isDesktop }) => {
</AppCircle> </AppCircle>
{app?.isPrivate ? ( {app?.isPrivate ? (
<AppCircleLabel> <AppCircleLabel>
Private {`${app?.privateAppProperties?.appName || "Private"}`}
</AppCircleLabel> </AppCircleLabel>
) : ( ) : (
<AppCircleLabel> <AppCircleLabel>

View File

@ -37,7 +37,7 @@ const TabComponent = ({ isSelected, app }) => {
src={NavCloseTab} src={NavCloseTab}
/> />
)} )}
{app?.isPrivate ? ( {app?.isPrivate && !app?.privateAppProperties?.logo ? (
<LockIcon <LockIcon
sx={{ sx={{
height: "28px", height: "28px",
@ -51,7 +51,7 @@ const TabComponent = ({ isSelected, app }) => {
width: "28px", width: "28px",
}} }}
alt={app?.name} alt={app?.name}
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${ src={app?.privateAppProperties?.logo ? app?.privateAppProperties?.logo :`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
app?.name app?.name
}/qortal_avatar?async=true`} }/qortal_avatar?async=true`}
> >

View File

@ -8,6 +8,9 @@ import {
sortablePinnedAppsAtom, sortablePinnedAppsAtom,
} from "../../atoms/global"; } from "../../atoms/global";
import { saveToLocalStorage } from "./AppsNavBarDesktop"; import { saveToLocalStorage } from "./AppsNavBarDesktop";
import { base64ToBlobUrl } from "../../utils/fileReading";
import { base64ToUint8Array } from "../../qdn/encryption/group-encryption";
import { uint8ArrayToObject } from "../../backgroundFunctions/encryption";
export const useHandlePrivateApps = () => { export const useHandlePrivateApps = () => {
const [status, setStatus] = useState(""); const [status, setStatus] = useState("");
@ -58,6 +61,10 @@ export const useHandlePrivateApps = () => {
} }
); );
if(decryptedData?.error) throw new Error(decryptedData?.error) if(decryptedData?.error) throw new Error(decryptedData?.error)
const convertToUint = base64ToUint8Array(decryptedData)
const UintToObject = uint8ArrayToObject(convertToUint)
if (decryptedData) { if (decryptedData) {
setInfoSnackCustom({ setInfoSnackCustom({
type: "info", type: "info",
@ -71,7 +78,7 @@ export const useHandlePrivateApps = () => {
headers: { headers: {
"Content-Type": "text/plain", "Content-Type": "text/plain",
}, },
body: decryptedData, body: UintToObject?.app,
}); });
const previewPath = await response.text(); const previewPath = await response.text();
setOpenSnackGlobal(false); setOpenSnackGlobal(false);
@ -81,12 +88,15 @@ export const useHandlePrivateApps = () => {
}); });
}; };
const appName = UintToObject?.name
const logo = UintToObject?.logo ? `data:image/png;base64,${UintToObject?.logo}` : null
executeEvent("addTab", { executeEvent("addTab", {
data: { data: {
url: await createEndpoint(previewPath), url: await createEndpoint(previewPath),
isPreview: true, isPreview: true,
isPrivate: true, isPrivate: true,
privateAppProperties: { ...privateAppProperties }, privateAppProperties: { ...privateAppProperties, logo, appName },
filePath: "", filePath: "",
refreshFunc: (tabId) => { refreshFunc: (tabId) => {
refreshfunc(tabId); refreshfunc(tabId);
@ -101,7 +111,7 @@ export const useHandlePrivateApps = () => {
{ {
isPrivate: true, isPrivate: true,
isPreview: true, isPreview: true,
privateAppProperties: { ...privateAppProperties }, privateAppProperties: { ...privateAppProperties, logo, appName },
}, },
]; ];