mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-02-11 17:55:49 +00:00
batch of updates 7
This commit is contained in:
parent
a4c1fd564b
commit
f6cac4b91f
45
package-lock.json
generated
45
package-lock.json
generated
@ -40,6 +40,7 @@
|
||||
"file-saver": "^2.0.5",
|
||||
"html-to-text": "^9.0.5",
|
||||
"jssha": "3.3.1",
|
||||
"lit": "^3.2.1",
|
||||
"lodash": "^4.17.21",
|
||||
"mime": "^4.0.4",
|
||||
"moment": "^2.30.1",
|
||||
@ -1360,6 +1361,19 @@
|
||||
"resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
|
||||
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
|
||||
},
|
||||
"node_modules/@lit-labs/ssr-dom-shim": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz",
|
||||
"integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ=="
|
||||
},
|
||||
"node_modules/@lit/reactive-element": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
|
||||
"integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
|
||||
"dependencies": {
|
||||
"@lit-labs/ssr-dom-shim": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/base": {
|
||||
"version": "5.0.0-beta.40",
|
||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz",
|
||||
@ -2876,8 +2890,7 @@
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
|
||||
},
|
||||
"node_modules/@types/use-sync-external-store": {
|
||||
"version": "0.0.6",
|
||||
@ -6029,6 +6042,34 @@
|
||||
"uc.micro": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz",
|
||||
"integrity": "sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
"lit-element": "^4.1.0",
|
||||
"lit-html": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit-element": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.1.tgz",
|
||||
"integrity": "sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==",
|
||||
"dependencies": {
|
||||
"@lit-labs/ssr-dom-shim": "^1.2.0",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
"lit-html": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lit-html": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.1.tgz",
|
||||
"integrity": "sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==",
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/local-pkg": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
|
||||
|
@ -65,6 +65,7 @@
|
||||
"react-virtuoso": "^4.10.4",
|
||||
"recoil": "^0.7.7",
|
||||
"short-unique-id": "^5.2.0",
|
||||
"lit": "^3.2.1",
|
||||
"slate": "^0.103.0",
|
||||
"slate-react": "^0.109.0",
|
||||
"tiptap-extension-resize-image": "^1.1.8",
|
||||
|
@ -77,7 +77,7 @@ display: flex;
|
||||
border: 1px solid var(--50-white, rgba(255, 255, 255, 0.5));
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 140px;
|
||||
width: auto;
|
||||
height: 25px;
|
||||
padding: 5px 15px 5px 15px;
|
||||
gap: 5px;
|
||||
|
163
src/App.tsx
163
src/App.tsx
@ -51,6 +51,7 @@ import {
|
||||
createAccount,
|
||||
generateRandomSentence,
|
||||
saveFileToDisk,
|
||||
saveSeedPhraseToDisk
|
||||
} from "./utils/generateWallet/generateWallet";
|
||||
import { kdf } from "./deps/kdf";
|
||||
import { generateSaveWalletData } from "./utils/generateWallet/storeWallet";
|
||||
@ -116,6 +117,8 @@ import { useHandleTutorials } from "./components/Tutorials/useHandleTutorials";
|
||||
import { CoreSyncStatus } from "./components/CoreSyncStatus";
|
||||
import BoundedNumericTextField from "./common/BoundedNumericTextField";
|
||||
import { Wallets } from "./Wallets";
|
||||
import './utils/seedPhrase/RandomSentenceGenerator';
|
||||
import { test } from "vitest";
|
||||
|
||||
type extStates =
|
||||
| "not-authenticated"
|
||||
@ -323,7 +326,8 @@ function App() {
|
||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||
const { isShow: isShowUnsavedChanges, onCancel: onCancelUnsavedChanges, onOk: onOkUnsavedChanges, show: showUnsavedChanges, message: messageUnsavedChanges } = useModal();
|
||||
const {downloadResource} = useFetchResources()
|
||||
|
||||
const [showSeed, setShowSeed] = useState(false)
|
||||
const [creationStep, setCreationStep] = useState(1)
|
||||
const {
|
||||
isShow: isShowInfo,
|
||||
onCancel: onCancelInfo,
|
||||
@ -366,6 +370,11 @@ function App() {
|
||||
const [fullScreen, setFullScreen] = useRecoilState(fullScreenAtom);
|
||||
const resetAtomIsUsingImportExportSettingsAtom = useResetRecoilState(isUsingImportExportSettingsAtom)
|
||||
const { toggleFullScreen } = useAppFullScreen(setFullScreen);
|
||||
const generatorRef = useRef(null)
|
||||
const exportSeedphrase = ()=> {
|
||||
const seedPhrase = generatorRef.current.parsedString
|
||||
saveSeedPhraseToDisk(seedPhrase)
|
||||
}
|
||||
const {showTutorial, openTutorialModal, shownTutorialsInitiated, setOpenTutorialModal} = useHandleTutorials()
|
||||
|
||||
const passwordRef = useRef<HTMLInputElement>(null);
|
||||
@ -1028,7 +1037,8 @@ function App() {
|
||||
res();
|
||||
}, 250);
|
||||
});
|
||||
const res = await createAccount();
|
||||
const res = await createAccount(generatorRef.current.parsedString);
|
||||
|
||||
const wallet = await res.generateSaveWalletData(
|
||||
walletToBeDownloadedPassword,
|
||||
crypto.kdfThreads,
|
||||
@ -1102,6 +1112,8 @@ function App() {
|
||||
setExtstate("authenticated");
|
||||
setIsOpenSendQort(false);
|
||||
setIsOpenSendQortSuccess(false);
|
||||
setShowSeed(false)
|
||||
setCreationStep(1)
|
||||
};
|
||||
|
||||
const resetAllStates = () => {
|
||||
@ -1131,6 +1143,8 @@ function App() {
|
||||
setTxList([]);
|
||||
setMemberGroups([]);
|
||||
resetAllRecoil()
|
||||
setShowSeed(false)
|
||||
setCreationStep(1)
|
||||
};
|
||||
|
||||
function roundUpToDecimals(number, decimals = 8) {
|
||||
@ -1353,9 +1367,10 @@ function App() {
|
||||
return (
|
||||
<AuthenticatedContainer
|
||||
sx={{
|
||||
width: isMobile ? "100vw" : "350px",
|
||||
width: isMobile ? "100vw" : "auto",
|
||||
display: "flex",
|
||||
backgroundColor: "var(--bg-2)",
|
||||
justifyContent: 'flex-end'
|
||||
}}
|
||||
>
|
||||
{isMobile && (
|
||||
@ -1378,9 +1393,11 @@ function App() {
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{desktopViewMode !== "apps" && desktopViewMode !== "dev" && desktopViewMode !== "chat" && (
|
||||
<AuthenticatedContainerInnerLeft
|
||||
sx={{
|
||||
overflowY: isMobile && "auto",
|
||||
padding: '0px 20px'
|
||||
}}
|
||||
>
|
||||
<Spacer height="48px" />
|
||||
@ -1534,6 +1551,7 @@ function App() {
|
||||
Get QORT at Q-Trade
|
||||
</TextP>
|
||||
</AuthenticatedContainerInnerLeft>
|
||||
)}
|
||||
<AuthenticatedContainerInnerRight sx={{
|
||||
height: "100%",
|
||||
justifyContent: "space-between",
|
||||
@ -1620,7 +1638,7 @@ function App() {
|
||||
showTutorial('qapps', true)
|
||||
|
||||
} else {
|
||||
showTutorial('create-account', true)
|
||||
showTutorial('getting-started', true)
|
||||
|
||||
}
|
||||
}} >
|
||||
@ -1652,10 +1670,10 @@ function App() {
|
||||
<AppContainer
|
||||
sx={{
|
||||
height: isMobile ? "100%" : "100vh",
|
||||
backgroundImage: desktopViewMode === 'apps' && 'url("appsBg.svg")',
|
||||
backgroundSize: desktopViewMode === 'apps' && 'cover',
|
||||
backgroundPosition: desktopViewMode === 'apps' && 'center',
|
||||
backgroundRepeat: desktopViewMode === 'apps' && 'no-repeat',
|
||||
// backgroundImage: desktopViewMode === 'apps' && 'url("appsBg.svg")',
|
||||
// backgroundSize: desktopViewMode === 'apps' && 'cover',
|
||||
// backgroundPosition: desktopViewMode === 'apps' && 'center',
|
||||
// backgroundRepeat: desktopViewMode === 'apps' && 'no-repeat',
|
||||
}}
|
||||
>
|
||||
<GlobalContext.Provider value={{
|
||||
@ -1714,7 +1732,7 @@ function App() {
|
||||
desktopViewMode={desktopViewMode}
|
||||
setDesktopViewMode={setDesktopViewMode}
|
||||
/>
|
||||
{(!isMobile && desktopViewMode !== 'apps') && renderProfile()}
|
||||
{!isMobile && renderProfile()}
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
@ -2538,7 +2556,15 @@ function App() {
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => {
|
||||
if(creationStep === 2){
|
||||
setCreationStep(1)
|
||||
return
|
||||
}
|
||||
setExtstate("not-authenticated");
|
||||
setShowSeed(false)
|
||||
setCreationStep(1)
|
||||
setWalletToBeDownloadedPasswordConfirm('')
|
||||
setWalletToBeDownloadedPassword('')
|
||||
}}
|
||||
src={Return}
|
||||
/>
|
||||
@ -2564,6 +2590,117 @@ function App() {
|
||||
Set up your Qortal account
|
||||
</TextP>
|
||||
<Spacer height="14px" />
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
maxWidth: '100%',
|
||||
justifyContent: 'center',
|
||||
padding: '10px'
|
||||
}}>
|
||||
<Box sx={{
|
||||
display: creationStep === 1 ? 'flex' : 'none',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
width: '350px',
|
||||
maxWidth: '95%'
|
||||
}}>
|
||||
<Typography sx={{
|
||||
fontSize: '14px'
|
||||
}}>
|
||||
A ‘ <span onClick={()=> {
|
||||
setShowSeed(true)
|
||||
}} style={{
|
||||
fontSize: '14px',
|
||||
color: 'steelblue',
|
||||
cursor: 'pointer'
|
||||
}}>SEEDPHRASE</span> ’ has been randomly generated in the background.
|
||||
|
||||
|
||||
</Typography>
|
||||
<Typography sx={{
|
||||
fontSize: '14px',
|
||||
marginTop: '5px'
|
||||
}}>
|
||||
If you wish to VIEW THE SEEDPHRASE, click the word 'SEEDPHRASE' in this text. Seedphrases are used to generate the private key for your Qortal account. For security by default, seedphrases are NOT displayed unless specifically chosen.
|
||||
</Typography>
|
||||
<Typography sx={{
|
||||
fontSize: '16px',
|
||||
marginTop: '15px',
|
||||
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
Create your Qortal account by clicking <span style={{
|
||||
fontWeight: 'bold'
|
||||
}}>NEXT</span> below.
|
||||
|
||||
</Typography>
|
||||
<Spacer height="17px" />
|
||||
<CustomButton onClick={()=> {
|
||||
setCreationStep(2)
|
||||
}}>
|
||||
Next
|
||||
</CustomButton>
|
||||
</Box>
|
||||
<div style={{
|
||||
display: 'none'
|
||||
}}>
|
||||
<random-sentence-generator
|
||||
ref={generatorRef}
|
||||
template="adverb verb noun adjective noun adverb verb noun adjective noun adjective verbed adjective noun"
|
||||
|
||||
></random-sentence-generator>
|
||||
</div>
|
||||
<Dialog
|
||||
open={showSeed}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogContent>
|
||||
<Box sx={{
|
||||
flexDirection: 'column',
|
||||
maxWidth: '400px',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
display: showSeed ? 'flex' : 'none'
|
||||
}}>
|
||||
<Typography sx={{
|
||||
fontSize: '14px'
|
||||
}}>Your seedphrase</Typography>
|
||||
|
||||
<Box sx={{
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
backgroundColor: '#1f2023',
|
||||
borderRadius: '5px',
|
||||
padding: '10px',
|
||||
}}>
|
||||
{generatorRef.current?.parsedString}
|
||||
</Box>
|
||||
|
||||
<CustomButton sx={{
|
||||
padding: '7px',
|
||||
fontSize: '12px'
|
||||
}} onClick={exportSeedphrase}>
|
||||
Export Seedphrase
|
||||
</CustomButton>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
|
||||
<Button variant="contained" onClick={()=> setShowSeed(false)}>
|
||||
close
|
||||
</Button>
|
||||
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
</Box>
|
||||
<Box sx={{
|
||||
display: creationStep === 2 ? 'flex' : 'none',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
|
||||
}}>
|
||||
<Spacer height="14px" />
|
||||
<CustomLabel htmlFor="standard-adornment-password">
|
||||
Wallet Password
|
||||
</CustomLabel>
|
||||
@ -2592,6 +2729,7 @@ function App() {
|
||||
<CustomButton onClick={createAccountFunc}>
|
||||
Create Account
|
||||
</CustomButton>
|
||||
</Box>
|
||||
<ErrorText>{walletToBeDownloadedError}</ErrorText>
|
||||
</>
|
||||
)}
|
||||
@ -2611,9 +2749,12 @@ function App() {
|
||||
</TextP>
|
||||
<Spacer height="100px" />
|
||||
<CustomButton
|
||||
onClick={() => {
|
||||
saveFileToDiskFunc();
|
||||
onClick={async () => {
|
||||
await saveFileToDiskFunc();
|
||||
returnToMain();
|
||||
await showInfo({
|
||||
message: `Keep your wallet file secure.`,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Backup Account
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||
import { Spacer } from "../common/Spacer";
|
||||
import { CustomButton, TextItalic, TextP, TextSpan } from "../App-styles";
|
||||
import {
|
||||
@ -14,6 +14,7 @@ import {
|
||||
Switch,
|
||||
Tooltip,
|
||||
Typography,
|
||||
ButtonBase
|
||||
} from "@mui/material";
|
||||
import Logo1 from "../assets/svgs/Logo1.svg";
|
||||
import Logo1Dark from "../assets/svgs/Logo1Dark.svg";
|
||||
@ -21,6 +22,8 @@ import Info from "../assets/svgs/Info.svg";
|
||||
import { CustomizedSnackbars } from "../components/Snackbar/Snackbar";
|
||||
import { set } from "lodash";
|
||||
import { cleanUrl, isUsingLocal } from "../background";
|
||||
import HelpIcon from '@mui/icons-material/Help';
|
||||
import { GlobalContext } from "../App";
|
||||
|
||||
const manifestData = chrome?.runtime?.getManifest();
|
||||
|
||||
@ -55,6 +58,8 @@ export const NotAuthenticated = ({
|
||||
const importedApiKeyRef = useRef(null)
|
||||
const currentNodeRef = useRef(null)
|
||||
const hasLocalNodeRef = useRef(null)
|
||||
const { showTutorial } = useContext(GlobalContext);
|
||||
|
||||
const isLocal = cleanUrl(currentNode?.url) === "127.0.0.1:12391";
|
||||
const handleFileChangeApiKey = (event) => {
|
||||
const file = event.target.files[0]; // Get the selected file
|
||||
@ -627,6 +632,17 @@ export const NotAuthenticated = ({
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)}
|
||||
<ButtonBase onClick={()=> {
|
||||
showTutorial('create-account', true)
|
||||
}} sx={{
|
||||
position: 'fixed',
|
||||
bottom: '25px',
|
||||
right: '25px'
|
||||
}}>
|
||||
<HelpIcon sx={{
|
||||
color: 'var(--unread)'
|
||||
}} />
|
||||
</ButtonBase>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -34,46 +34,8 @@ import { RESOURCE_TYPE_NUMBER_GROUP_CHAT_REACTIONS } from "./constants/resourceT
|
||||
import TradeBotRespondRequest from './transactions/TradeBotRespondRequest';
|
||||
|
||||
|
||||
let inMemoryKey: CryptoKey | null = null;
|
||||
let inMemoryIV: Uint8Array | null = null;
|
||||
|
||||
|
||||
async function initializeKeyAndIV() {
|
||||
if (!inMemoryKey) {
|
||||
inMemoryKey = await generateKey(); // Generates the key in memory
|
||||
}
|
||||
}
|
||||
|
||||
async function generateKey(): Promise<CryptoKey> {
|
||||
return await crypto.subtle.generateKey(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
length: 256
|
||||
},
|
||||
true,
|
||||
["encrypt", "decrypt"]
|
||||
);
|
||||
}
|
||||
|
||||
async function encryptData(data: string, key: CryptoKey): Promise<{ iv: Uint8Array; encryptedData: ArrayBuffer }> {
|
||||
const encoder = new TextEncoder();
|
||||
const encodedData = encoder.encode(data);
|
||||
|
||||
// Generate a random IV each time you encrypt
|
||||
const iv = crypto.getRandomValues(new Uint8Array(12));
|
||||
|
||||
const encryptedData = await crypto.subtle.encrypt(
|
||||
{
|
||||
name: "AES-GCM",
|
||||
iv: iv
|
||||
},
|
||||
key,
|
||||
encodedData
|
||||
);
|
||||
|
||||
return { iv, encryptedData };
|
||||
}
|
||||
|
||||
export function cleanUrl(url) {
|
||||
return url?.replace(/^(https?:\/\/)?(www\.)?/, '');
|
||||
}
|
||||
@ -1064,15 +1026,7 @@ function base64ToJson(base64) {
|
||||
export async function getKeyPair() {
|
||||
const res = await chrome.storage.local.get(["keyPair"]);
|
||||
if (res?.keyPair) {
|
||||
const combinedData = atob(res?.keyPair)
|
||||
.split("")
|
||||
.map((c) => c.charCodeAt(0));
|
||||
|
||||
const iv = new Uint8Array(combinedData.slice(0, 12)); // First 12 bytes are the IV
|
||||
const encryptedData = new Uint8Array(combinedData.slice(12)).buffer;
|
||||
|
||||
const decryptedBase64Data = await decryptData(encryptedData, inMemoryKey, iv);
|
||||
return decryptedBase64Data
|
||||
return res.keyPair;
|
||||
} else {
|
||||
throw new Error("Wallet not authenticated");
|
||||
}
|
||||
@ -1573,14 +1527,8 @@ async function decryptWallet({ password, wallet, walletVersion }) {
|
||||
rvnPrivateKey: wallet2._addresses[0].rvnWallet.derivedMasterPrivateKey
|
||||
};
|
||||
const dataString = JSON.stringify(toSave);
|
||||
await initializeKeyAndIV();
|
||||
const { iv, encryptedData } = await encryptData(dataString, inMemoryKey);
|
||||
|
||||
// Combine IV and encrypted data into a single Uint8Array
|
||||
const combinedData = new Uint8Array([...iv, ...new Uint8Array(encryptedData)]);
|
||||
const encryptedBase64Data = btoa(String.fromCharCode(...combinedData));
|
||||
await new Promise((resolve, reject) => {
|
||||
chrome.storage.local.set({ keyPair: encryptedBase64Data }, () => {
|
||||
chrome.storage.local.set({ keyPair: dataString }, () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
reject(new Error(chrome.runtime.lastError.message));
|
||||
} else {
|
||||
|
@ -20,10 +20,12 @@ import { HomeIcon } from "../../assets/Icons/HomeIcon";
|
||||
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
||||
import { Save } from "../Save/Save";
|
||||
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
||||
import { IconWrapper } from "../Desktop/DesktopFooter";
|
||||
import { AppsIcon } from "../../assets/Icons/AppsIcon";
|
||||
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
export const AppsDesktop = ({ mode, setMode, show , myName, goToHome, setDesktopSideView, hasUnreadDirects, isDirects, isGroups, hasUnreadGroups, toggleSideViewGroups, toggleSideViewDirects}) => {
|
||||
export const AppsDesktop = ({ mode, setMode, show , myName, goToHome, setDesktopSideView, hasUnreadDirects, isDirects, isGroups, hasUnreadGroups, toggleSideViewGroups, toggleSideViewDirects, setDesktopViewMode, isApps, desktopViewMode}) => {
|
||||
const [availableQapps, setAvailableQapps] = useState([]);
|
||||
const [selectedAppInfo, setSelectedAppInfo] = useState(null);
|
||||
const [selectedCategory, setSelectedCategory] = useState(null)
|
||||
@ -334,46 +336,44 @@ export const AppsDesktop = ({ mode, setMode, show , myName, goToHome, setDesktop
|
||||
|
||||
<HomeIcon
|
||||
height={34}
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
color={desktopViewMode === 'home' ? 'white': "rgba(250, 250, 250, 0.5)"}
|
||||
/>
|
||||
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("directs");
|
||||
toggleSideViewDirects()
|
||||
setDesktopViewMode('apps')
|
||||
}}
|
||||
>
|
||||
|
||||
<IconWrapper
|
||||
color={isApps ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Apps"
|
||||
disableWidth
|
||||
>
|
||||
<AppsIcon height={30} color={isApps ? 'white' :"rgba(250, 250, 250, 0.5)"} />
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopViewMode('chat')
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color={(hasUnreadDirects || hasUnreadGroups) ? "var(--unread)" : desktopViewMode === 'chat' ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Chat"
|
||||
disableWidth
|
||||
>
|
||||
<MessagingIcon
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadDirects
|
||||
(hasUnreadDirects || hasUnreadGroups)
|
||||
? "var(--unread)"
|
||||
: isDirects
|
||||
: desktopViewMode === 'chat'
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("groups");
|
||||
toggleSideViewGroups()
|
||||
}}
|
||||
>
|
||||
<HubsIcon
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadGroups
|
||||
? "var(--unread)"
|
||||
: isGroups
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<Save isDesktop myName={myName} />
|
||||
{mode !== 'home' && (
|
||||
|
@ -18,7 +18,7 @@ import AppIcon from "../../assets/svgs/AppIcon.svg";
|
||||
import { HomeIcon } from "../../assets/Icons/HomeIcon";
|
||||
import { Save } from "../Save/Save";
|
||||
|
||||
export const IconWrapper = ({ children, label, color, selected }) => {
|
||||
export const IconWrapper = ({ children, label, color, selected, disableWidth, customWidth }) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@ -27,8 +27,8 @@ export const IconWrapper = ({ children, label, color, selected }) => {
|
||||
alignItems: "center",
|
||||
gap: "5px",
|
||||
flexDirection: "column",
|
||||
height: "89px",
|
||||
width: "89px",
|
||||
height: customWidth ? customWidth : disableWidth ? 'auto' : "89px",
|
||||
width: customWidth? customWidth : disableWidth ? 'auto' : "89px",
|
||||
borderRadius: "50%",
|
||||
backgroundColor: selected ? "rgba(28, 29, 32, 1)" : "transparent",
|
||||
}}
|
||||
|
@ -128,74 +128,7 @@ export const DesktopHeader = ({
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
goToHome();
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
label="Home"
|
||||
selected={isHome}
|
||||
>
|
||||
<HomeIcon
|
||||
height={25}
|
||||
color={isHome ? "white" : "rgba(250, 250, 250, 0.5)"}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("groups");
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
label="Groups"
|
||||
selected={isGroups}
|
||||
>
|
||||
<HubsIcon
|
||||
height={25}
|
||||
color={
|
||||
hasUnreadGroups
|
||||
? "var(--unread)"
|
||||
: isGroups
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("directs");
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
label="Messaging"
|
||||
selected={isDirects}
|
||||
>
|
||||
<MessagingIcon
|
||||
height={25}
|
||||
color={
|
||||
hasUnreadDirects
|
||||
? "var(--unread)"
|
||||
: isDirects
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<Box
|
||||
sx={{
|
||||
width: "1px",
|
||||
height: "50px",
|
||||
background: "white",
|
||||
borderRadius: "50px",
|
||||
}}
|
||||
/>
|
||||
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
goToAnnouncements()
|
||||
@ -231,6 +164,7 @@ export const DesktopHeader = ({
|
||||
label="Chat"
|
||||
selected={isChat}
|
||||
selectColor="#09b6e8"
|
||||
customHeight="55px"
|
||||
>
|
||||
<ChatIcon
|
||||
height={25}
|
||||
@ -257,6 +191,7 @@ export const DesktopHeader = ({
|
||||
label="Threads"
|
||||
selected={isForum}
|
||||
selectColor="#09b6e8"
|
||||
customHeight="55px"
|
||||
>
|
||||
<ThreadsIcon
|
||||
height={25}
|
||||
@ -279,6 +214,7 @@ export const DesktopHeader = ({
|
||||
color="rgba(250, 250, 250, 0.5)"
|
||||
label="Members"
|
||||
selected={false}
|
||||
customHeight="55px"
|
||||
>
|
||||
<MembersIcon
|
||||
height={25}
|
||||
|
104
src/components/DesktopSideBar.tsx
Normal file
104
src/components/DesktopSideBar.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
import { Box, ButtonBase } from '@mui/material';
|
||||
import React from 'react'
|
||||
import { HomeIcon } from "../assets/Icons/HomeIcon";
|
||||
import { MessagingIcon } from "../assets/Icons/MessagingIcon";
|
||||
import { Save } from "./Save/Save";
|
||||
import { HubsIcon } from "../assets/Icons/HubsIcon";
|
||||
import { CoreSyncStatus } from "./CoreSyncStatus";
|
||||
import { IconWrapper } from './Desktop/DesktopFooter';
|
||||
import AppIcon from "./../assets/svgs/AppIcon.svg";
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { AppsIcon } from '../assets/Icons/AppsIcon';
|
||||
|
||||
export const DesktopSideBar = ({goToHome, setDesktopSideView, toggleSideViewDirects, hasUnreadDirects, isDirects, toggleSideViewGroups,hasUnreadGroups, isGroups, isApps, setDesktopViewMode, desktopViewMode, myName }) => {
|
||||
|
||||
return (
|
||||
<Box sx={{
|
||||
width: '60px',
|
||||
flexDirection: 'column',
|
||||
height: '100vh',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
gap: '25px'
|
||||
}}>
|
||||
<ButtonBase
|
||||
sx={{
|
||||
width: '60px',
|
||||
height: '60px',
|
||||
paddingTop: '23px'
|
||||
}}
|
||||
onClick={() => {
|
||||
goToHome();
|
||||
|
||||
}}
|
||||
>
|
||||
|
||||
<HomeIcon
|
||||
height={34}
|
||||
color={desktopViewMode === 'home' ? 'white': "rgba(250, 250, 250, 0.5)"}
|
||||
|
||||
/>
|
||||
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopViewMode('apps')
|
||||
// setIsOpenSideViewDirects(false)
|
||||
// setIsOpenSideViewGroups(false)
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color={isApps ? 'white' : "rgba(250, 250, 250, 0.5)"}
|
||||
label="Apps"
|
||||
selected={isApps}
|
||||
disableWidth
|
||||
>
|
||||
<AppsIcon color={isApps ? 'white' : "rgba(250, 250, 250, 0.5)"} height={30} />
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopViewMode('chat')
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color={(hasUnreadDirects || hasUnreadGroups) ? "var(--unread)" : desktopViewMode === 'chat' ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Chat"
|
||||
disableWidth
|
||||
>
|
||||
<MessagingIcon
|
||||
height={30}
|
||||
color={
|
||||
(hasUnreadDirects || hasUnreadGroups)
|
||||
? "var(--unread)"
|
||||
: desktopViewMode === 'chat'
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
{/* <ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("groups");
|
||||
toggleSideViewGroups()
|
||||
}}
|
||||
>
|
||||
<HubsIcon
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadGroups
|
||||
? "var(--danger)"
|
||||
: isGroups
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
|
||||
</ButtonBase> */}
|
||||
<Save isDesktop disableWidth myName={myName} />
|
||||
{/* <CoreSyncStatus imageSize="30px" position="left" /> */}
|
||||
|
||||
</Box>
|
||||
)
|
||||
}
|
@ -86,7 +86,7 @@ import { getRootHeight } from "../../utils/mobile/mobileUtils";
|
||||
import { ReturnIcon } from "../../assets/Icons/ReturnIcon";
|
||||
import { ExitIcon } from "../../assets/Icons/ExitIcon";
|
||||
import { HomeDesktop } from "./HomeDesktop";
|
||||
import { DesktopFooter } from "../Desktop/DesktopFooter";
|
||||
import { DesktopFooter, IconWrapper } from "../Desktop/DesktopFooter";
|
||||
import { DesktopHeader } from "../Desktop/DesktopHeader";
|
||||
import { Apps } from "../Apps/Apps";
|
||||
import { AppsNavBar } from "../Apps/AppsNavBar";
|
||||
@ -98,6 +98,9 @@ import { useSetRecoilState } from "recoil";
|
||||
import { selectedGroupIdAtom } from "../../atoms/global";
|
||||
import { sortArrayByTimestampAndGroupName } from "../../utils/time";
|
||||
import { AdminSpace } from "../Chat/AdminSpace";
|
||||
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
||||
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
||||
import { DesktopSideBar } from "../DesktopSideBar";
|
||||
|
||||
// let touchStartY = 0;
|
||||
// let disablePullToRefresh = false;
|
||||
@ -1359,6 +1362,10 @@ export const Group = ({
|
||||
setupGroupWebsocketInterval.current = null;
|
||||
settimeoutForRefetchSecretKey.current = null;
|
||||
initiatedGetMembers.current = false;
|
||||
|
||||
if(!isMobile){
|
||||
setDesktopViewMode('home')
|
||||
}
|
||||
};
|
||||
|
||||
const openDevModeFunc = () => {
|
||||
@ -1445,7 +1452,9 @@ export const Group = ({
|
||||
setTriedToFetchSecretKey(false);
|
||||
setFirstSecretKeyInCreation(false);
|
||||
setGroupSection("chat");
|
||||
|
||||
if(!isMobile){
|
||||
setDesktopViewMode('chat')
|
||||
}
|
||||
chrome?.runtime?.sendMessage({
|
||||
action: "addTimestampEnterChat",
|
||||
payload: {
|
||||
@ -1458,7 +1467,6 @@ export const Group = ({
|
||||
setSelectedGroup(findGroup);
|
||||
setMobileViewMode("group");
|
||||
setDesktopSideView('groups')
|
||||
setDesktopViewMode('home')
|
||||
getTimestampEnterChat();
|
||||
isLoadingOpenSectionFromNotification.current = false;
|
||||
}, 200);
|
||||
@ -1497,6 +1505,9 @@ export const Group = ({
|
||||
setTriedToFetchSecretKey(false);
|
||||
setFirstSecretKeyInCreation(false);
|
||||
setGroupSection("announcement");
|
||||
if(!isMobile){
|
||||
setDesktopViewMode('chat')
|
||||
}
|
||||
chrome?.runtime?.sendMessage({
|
||||
action: "addGroupNotificationTimestamp",
|
||||
payload: {
|
||||
@ -1508,7 +1519,6 @@ export const Group = ({
|
||||
setSelectedGroup(findGroup);
|
||||
setMobileViewMode("group");
|
||||
setDesktopSideView('groups')
|
||||
setDesktopViewMode('home')
|
||||
getGroupAnnouncements();
|
||||
}, 200);
|
||||
}
|
||||
@ -1560,12 +1570,13 @@ export const Group = ({
|
||||
setFirstSecretKeyInCreation(false);
|
||||
setGroupSection("forum");
|
||||
setDefaultThread(data);
|
||||
|
||||
if(!isMobile){
|
||||
setDesktopViewMode('chat')
|
||||
}
|
||||
setTimeout(() => {
|
||||
setSelectedGroup(findGroup);
|
||||
setMobileViewMode("group");
|
||||
setDesktopSideView('groups')
|
||||
setDesktopViewMode('home')
|
||||
getGroupAnnouncements();
|
||||
}, 200);
|
||||
}
|
||||
@ -1591,32 +1602,13 @@ export const Group = ({
|
||||
}
|
||||
setDesktopViewMode('home')
|
||||
|
||||
setGroupSection("default");
|
||||
clearAllQueues();
|
||||
|
||||
await new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
res(null);
|
||||
}, 200);
|
||||
});
|
||||
setGroupSection("home");
|
||||
setSelectedGroup(null);
|
||||
setNewChat(false);
|
||||
setSelectedDirect(null);
|
||||
setSecretKey(null);
|
||||
setGroupOwner(null)
|
||||
lastFetchedSecretKey.current = null;
|
||||
initiatedGetMembers.current = false;
|
||||
setSecretKeyPublishDate(null);
|
||||
setAdmins([]);
|
||||
setSecretKeyDetails(null);
|
||||
setAdminsWithNames([]);
|
||||
setMembers([]);
|
||||
setMemberCountFromSecretKeyData(null);
|
||||
setIsForceShowCreationKeyPopup(false)
|
||||
setTriedToFetchSecretKey(false);
|
||||
setFirstSecretKeyInCreation(false);
|
||||
setIsOpenSideViewDirects(false)
|
||||
setIsOpenSideViewGroups(false)
|
||||
|
||||
};
|
||||
|
||||
const goToAnnouncements = async () => {
|
||||
@ -1690,6 +1682,66 @@ export const Group = ({
|
||||
borderRadius: !isMobile && '0px 15px 15px 0px'
|
||||
}}
|
||||
>
|
||||
{!isMobile && (
|
||||
<Box sx={{
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
display: 'flex',
|
||||
gap: '10px'
|
||||
}}>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("groups");
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color={(groupChatHasUnread ||
|
||||
groupsAnnHasUnread)
|
||||
? "var(--unread)"
|
||||
: desktopSideView === 'groups' ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Groups"
|
||||
selected={desktopSideView === 'groups'}
|
||||
customWidth="75px"
|
||||
>
|
||||
<HubsIcon
|
||||
height={24}
|
||||
color={
|
||||
(groupChatHasUnread ||
|
||||
groupsAnnHasUnread)
|
||||
? "var(--unread)"
|
||||
: desktopSideView === 'groups'
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("directs");
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
customWidth="75px"
|
||||
color={directChatHasUnread ? "var(--unread)" : desktopSideView === 'directs' ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Messaging"
|
||||
selected={desktopSideView === 'directs'}
|
||||
>
|
||||
<MessagingIcon
|
||||
height={24}
|
||||
color={
|
||||
directChatHasUnread
|
||||
? "var(--unread)"
|
||||
: desktopSideView === 'directs'
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
</Box>
|
||||
)}
|
||||
{isMobile && (
|
||||
<Box
|
||||
sx={{
|
||||
@ -1899,172 +1951,66 @@ export const Group = ({
|
||||
borderRadius: !isMobile && '0px 15px 15px 0px'
|
||||
}}
|
||||
>
|
||||
{/* <div
|
||||
style={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
justifyContent: "center",
|
||||
gap: "20px",
|
||||
padding: "10px",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{isMobile && (
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<CloseIcon
|
||||
{!isMobile && (
|
||||
<Box sx={{
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
display: 'flex',
|
||||
gap: '10px'
|
||||
}}>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setIsOpenDrawer(false);
|
||||
}}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
color: "white",
|
||||
setDesktopSideView("groups");
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
color={(groupChatHasUnread ||
|
||||
groupsAnnHasUnread)
|
||||
? "var(--unread)"
|
||||
: desktopSideView === 'groups' ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Groups"
|
||||
selected={desktopSideView === 'groups'}
|
||||
customWidth="75px"
|
||||
>
|
||||
<HubsIcon
|
||||
height={24}
|
||||
color={
|
||||
(groupChatHasUnread ||
|
||||
groupsAnnHasUnread)
|
||||
? "var(--unread)"
|
||||
: desktopSideView === 'groups'
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopSideView("directs");
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
customWidth="75px"
|
||||
color={directChatHasUnread ? "var(--unread)" : desktopSideView === 'directs' ? 'white' :"rgba(250, 250, 250, 0.5)"}
|
||||
label="Messaging"
|
||||
selected={desktopSideView === 'directs' }
|
||||
>
|
||||
<MessagingIcon
|
||||
height={24}
|
||||
color={
|
||||
directChatHasUnread
|
||||
? "var(--unread)"
|
||||
: desktopSideView === 'directs'
|
||||
? "white"
|
||||
: "rgba(250, 250, 250, 0.5)"
|
||||
}
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
</Box>
|
||||
)}
|
||||
<CustomButton
|
||||
onClick={() => {
|
||||
setChatMode((prev) =>
|
||||
prev === "directs" ? "groups" : "directs"
|
||||
);
|
||||
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: chatMode === 'directs' && ( groupChatHasUnread || groupsAnnHasUnread) ? 'red' : 'revert'
|
||||
}}
|
||||
>
|
||||
{chatMode === "groups" && (
|
||||
<>
|
||||
<MarkUnreadChatAltIcon
|
||||
sx={{
|
||||
color: directChatHasUnread ? "red" : "white",
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{chatMode === "directs" ? "Switch to groups" : "Direct msgs"}
|
||||
</CustomButton>
|
||||
</div> */}
|
||||
{/* <div
|
||||
style={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
flexDirection: "column",
|
||||
alignItems: "flex-start",
|
||||
flexGrow: 1,
|
||||
overflowY: "auto",
|
||||
visibility: chatMode === "groups" && "hidden",
|
||||
position: chatMode === "groups" && "fixed",
|
||||
left: chatMode === "groups" && "-1000px",
|
||||
}}
|
||||
>
|
||||
{directs.map((direct: any) => (
|
||||
<List sx={{
|
||||
width: '100%'
|
||||
}} className="group-list" dense={true}>
|
||||
<ListItem
|
||||
// secondaryAction={
|
||||
// <IconButton edge="end" aria-label="delete">
|
||||
// <SettingsIcon />
|
||||
// </IconButton>
|
||||
// }
|
||||
onClick={() => {
|
||||
setSelectedDirect(null);
|
||||
setNewChat(false);
|
||||
// setSelectedGroup(null);
|
||||
setIsOpenDrawer(false);
|
||||
chrome?.runtime?.sendMessage({
|
||||
action: "addTimestampEnterChat",
|
||||
payload: {
|
||||
timestamp: Date.now(),
|
||||
groupId: direct.address,
|
||||
},
|
||||
});
|
||||
setTimeout(() => {
|
||||
setSelectedDirect(direct);
|
||||
|
||||
getTimestampEnterChat();
|
||||
}, 200);
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
flexDirection: "column",
|
||||
cursor: "pointer",
|
||||
border: "1px #232428 solid",
|
||||
padding: "2px",
|
||||
borderRadius: "2px",
|
||||
background:
|
||||
direct?.address === selectedDirect?.address && "white",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
sx={{
|
||||
background: "#232428",
|
||||
color: "white",
|
||||
}}
|
||||
alt={direct?.name || direct?.address}
|
||||
// src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${groupOwner?.name}/qortal_group_avatar_${group.groupId}?async=true`}
|
||||
>
|
||||
{(direct?.name || direct?.address)?.charAt(0)}
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={direct?.name || direct?.address}
|
||||
primaryTypographyProps={{
|
||||
style: {
|
||||
color:
|
||||
direct?.address === selectedDirect?.address &&
|
||||
"black",
|
||||
textWrap: "wrap",
|
||||
overflow: "hidden",
|
||||
},
|
||||
}} // Change the color of the primary text
|
||||
secondaryTypographyProps={{
|
||||
style: {
|
||||
color:
|
||||
direct?.address === selectedDirect?.address &&
|
||||
"black",
|
||||
},
|
||||
}}
|
||||
sx={{
|
||||
width: "150px",
|
||||
fontFamily: "Inter",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
/>
|
||||
{direct?.sender !== myAddress &&
|
||||
direct?.timestamp &&
|
||||
((!timestampEnterData[direct?.address] &&
|
||||
Date.now() - direct?.timestamp <
|
||||
timeDifferenceForNotificationChats) ||
|
||||
timestampEnterData[direct?.address] <
|
||||
direct?.timestamp) && (
|
||||
<MarkChatUnreadIcon
|
||||
sx={{
|
||||
color: "red",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</ListItem>
|
||||
</List>
|
||||
))}
|
||||
</div> */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@ -2095,7 +2041,6 @@ export const Group = ({
|
||||
onClick={() => {
|
||||
setMobileViewMode("group");
|
||||
setDesktopSideView('groups')
|
||||
setDesktopViewMode('home')
|
||||
initiatedGetMembers.current = false;
|
||||
clearAllQueues();
|
||||
setSelectedDirect(null);
|
||||
@ -2347,8 +2292,14 @@ export const Group = ({
|
||||
alignItems: "flex-start",
|
||||
}}
|
||||
>
|
||||
{!isMobile && ((desktopSideView === 'groups' && desktopViewMode !== 'apps') || isOpenSideViewGroups) && renderGroups()}
|
||||
{!isMobile && ((desktopSideView === 'directs' && desktopViewMode !== 'apps') || isOpenSideViewDirects) && renderDirects()}
|
||||
{!isMobile && ((desktopViewMode !== 'apps' && desktopViewMode !== 'dev') || isOpenSideViewGroups) && (
|
||||
<DesktopSideBar desktopViewMode={desktopViewMode} toggleSideViewGroups={toggleSideViewGroups} toggleSideViewDirects={toggleSideViewDirects} goToHome={goToHome} mode={appsMode} setMode={setAppsMode} setDesktopSideView={setDesktopSideView} hasUnreadDirects={directChatHasUnread} isApps={desktopViewMode === 'apps'} myName={userInfo?.name} isGroups={isOpenSideViewGroups}
|
||||
isDirects={isOpenSideViewDirects} hasUnreadGroups={groupChatHasUnread ||
|
||||
groupsAnnHasUnread} setDesktopViewMode={setDesktopViewMode} />
|
||||
)}
|
||||
|
||||
{!isMobile && desktopViewMode === 'chat' && desktopSideView !== 'directs' && renderGroups()}
|
||||
{!isMobile && desktopViewMode === 'chat' && desktopSideView === 'directs' && renderDirects()}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
@ -2454,9 +2405,37 @@ export const Group = ({
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
{selectedGroup && mobileViewMode !== 'groups' && (
|
||||
<>
|
||||
{!isMobile && selectedGroup && (
|
||||
{desktopViewMode === 'chat' && !selectedGroup && (
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
color: 'rgba(255, 255, 255, 0.2)'
|
||||
}}
|
||||
>
|
||||
No group selected
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{mobileViewMode !== 'groups' && (
|
||||
<div style={{
|
||||
width: '100%',
|
||||
display: selectedGroup? 'block' : 'none',
|
||||
opacity: !(desktopViewMode === 'chat' && selectedGroup) ? 0 : 1,
|
||||
position: !(desktopViewMode === 'chat' && selectedGroup) ? 'absolute' : 'relative',
|
||||
left: !(desktopViewMode === 'chat' && selectedGroup) ? '-100000px' : '0px',
|
||||
}}>
|
||||
{!isMobile && (
|
||||
|
||||
<DesktopHeader
|
||||
isPrivate={isPrivate}
|
||||
@ -2753,7 +2732,7 @@ export const Group = ({
|
||||
isOwner={groupOwner?.owner === myAddress}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedDirect && !newChat && (
|
||||
@ -2797,43 +2776,7 @@ export const Group = ({
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
{!isMobile && groupSection === "home" && (
|
||||
<DesktopFooter
|
||||
isPrivate={isPrivate}
|
||||
selectedGroup={selectedGroup}
|
||||
groupSection={groupSection}
|
||||
isUnread={isUnread}
|
||||
goToAnnouncements={goToAnnouncements}
|
||||
isUnreadChat={isUnreadChat}
|
||||
goToChat={goToChat}
|
||||
goToThreads={goToThreads}
|
||||
setOpenManageMembers={setOpenManageMembers}
|
||||
groupChatHasUnread={groupChatHasUnread}
|
||||
groupsAnnHasUnread={groupsAnnHasUnread}
|
||||
directChatHasUnread={directChatHasUnread}
|
||||
chatMode={chatMode}
|
||||
openDrawerGroups={openDrawerGroups}
|
||||
goToHome={goToHome}
|
||||
setIsOpenDrawerProfile={setIsOpenDrawerProfile}
|
||||
mobileViewMode={mobileViewMode}
|
||||
setMobileViewMode={setMobileViewMode}
|
||||
setMobileViewModeKeepOpen={setMobileViewModeKeepOpen}
|
||||
hasUnreadGroups={groupChatHasUnread ||
|
||||
groupsAnnHasUnread}
|
||||
hasUnreadDirects={directChatHasUnread}
|
||||
myName={userInfo?.name || null}
|
||||
isHome={groupSection === "home" && desktopViewMode === 'home'}
|
||||
isGroups={desktopSideView === 'groups' && desktopViewMode !== 'apps'}
|
||||
isDirects={desktopSideView === 'directs' && desktopViewMode !== 'apps'}
|
||||
setDesktopViewMode={setDesktopViewMode}
|
||||
isApps={desktopViewMode === 'apps'}
|
||||
setDesktopSideView={setDesktopSideView}
|
||||
desktopViewMode={desktopViewMode}
|
||||
hide={desktopViewMode === 'apps'}
|
||||
setIsOpenSideViewDirects={setIsOpenSideViewDirects}
|
||||
setIsOpenSideViewGroups={setIsOpenSideViewGroups}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isMobile && mobileViewMode === "home" && (
|
||||
<Home
|
||||
refreshHomeDataFunc={refreshHomeDataFunc}
|
||||
@ -2848,6 +2791,7 @@ export const Group = ({
|
||||
setOpenManageMembers={setOpenManageMembers}
|
||||
setOpenAddGroup={setOpenAddGroup}
|
||||
setMobileViewMode={setMobileViewMode}
|
||||
setDesktopViewMode={setDesktopViewMode}
|
||||
/>
|
||||
)}
|
||||
{isMobile && (
|
||||
@ -2856,12 +2800,11 @@ export const Group = ({
|
||||
{!isMobile && (
|
||||
<AppsDesktop toggleSideViewGroups={toggleSideViewGroups} toggleSideViewDirects={toggleSideViewDirects} goToHome={goToHome} mode={appsMode} setMode={setAppsMode} setDesktopSideView={setDesktopSideView} hasUnreadDirects={directChatHasUnread} show={desktopViewMode === "apps"} myName={userInfo?.name} isGroups={isOpenSideViewGroups}
|
||||
isDirects={isOpenSideViewDirects} hasUnreadGroups={groupChatHasUnread ||
|
||||
groupsAnnHasUnread} />
|
||||
groupsAnnHasUnread} setDesktopViewMode={setDesktopViewMode} isApps={desktopViewMode === 'apps'} desktopViewMode={desktopViewMode} />
|
||||
)}
|
||||
|
||||
|
||||
{!isMobile && !selectedGroup &&
|
||||
groupSection === "home" && desktopViewMode !== "apps" && (
|
||||
{!isMobile && desktopViewMode === 'home' && (
|
||||
<HomeDesktop
|
||||
refreshHomeDataFunc={refreshHomeDataFunc}
|
||||
myAddress={myAddress}
|
||||
@ -2875,6 +2818,8 @@ export const Group = ({
|
||||
setOpenManageMembers={setOpenManageMembers}
|
||||
setOpenAddGroup={setOpenAddGroup}
|
||||
setMobileViewMode={setMobileViewMode}
|
||||
setDesktopViewMode={setDesktopViewMode}
|
||||
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -2886,7 +2831,7 @@ export const Group = ({
|
||||
width: "31px",
|
||||
// minWidth: "135px",
|
||||
padding: "5px",
|
||||
display: (isMobile || desktopViewMode === 'apps') ? "none" : "flex",
|
||||
display: (isMobile || desktopViewMode === 'apps' || desktopViewMode === 'dev' || desktopViewMode === 'chat') ? "none" : "flex",
|
||||
}}
|
||||
>
|
||||
|
||||
|
@ -20,7 +20,7 @@ import { myGroupsWhereIAmAdminAtom } from "../../atoms/global";
|
||||
import { useSetRecoilState } from "recoil";
|
||||
export const requestQueueGroupJoinRequests = new RequestQueueWithPromise(2)
|
||||
|
||||
export const GroupJoinRequests = ({ myAddress, groups, setOpenManageMembers, getTimestampEnterChat, setSelectedGroup, setGroupSection, setMobileViewMode }) => {
|
||||
export const GroupJoinRequests = ({ myAddress, groups, setOpenManageMembers, getTimestampEnterChat, setSelectedGroup, setGroupSection, setMobileViewMode, setDesktopViewMode }) => {
|
||||
const [groupsWithJoinRequests, setGroupsWithJoinRequests] = React.useState([])
|
||||
const [loading, setLoading] = React.useState(true)
|
||||
const {txList, setTxList} = React.useContext(MyContext)
|
||||
@ -185,6 +185,9 @@ export const GroupJoinRequests = ({ myAddress, groups, setOpenManageMembers, get
|
||||
getTimestampEnterChat()
|
||||
setGroupSection("announcement")
|
||||
setOpenManageMembers(true)
|
||||
if(!isMobile){
|
||||
setDesktopViewMode('chat')
|
||||
}
|
||||
setTimeout(() => {
|
||||
executeEvent("openGroupJoinRequest", {});
|
||||
|
||||
|
@ -21,6 +21,7 @@ export const Home = ({
|
||||
setOpenManageMembers,
|
||||
setOpenAddGroup,
|
||||
setMobileViewMode,
|
||||
setDesktopViewMode
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
@ -97,6 +98,7 @@ export const Home = ({
|
||||
myAddress={myAddress}
|
||||
groups={groups}
|
||||
setMobileViewMode={setMobileViewMode}
|
||||
setDesktopViewMode={setDesktopViewMode}
|
||||
/>
|
||||
<GroupInvites
|
||||
setOpenAddGroup={setOpenAddGroup}
|
||||
|
@ -21,6 +21,7 @@ export const HomeDesktop = ({
|
||||
setOpenManageMembers,
|
||||
setOpenAddGroup,
|
||||
setMobileViewMode,
|
||||
setDesktopViewMode
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
@ -67,7 +68,7 @@ export const HomeDesktop = ({
|
||||
display: "flex",
|
||||
gap: "15px",
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "flex-start",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Box sx={{
|
||||
@ -106,6 +107,7 @@ export const HomeDesktop = ({
|
||||
myAddress={myAddress}
|
||||
groups={groups}
|
||||
setMobileViewMode={setMobileViewMode}
|
||||
setDesktopViewMode={setDesktopViewMode}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{
|
||||
|
@ -57,6 +57,8 @@ useEffect(()=> {
|
||||
}, [])
|
||||
const showTutorial = useCallback(async (type, isForce) => {
|
||||
try {
|
||||
console.log('type, isForce', type, isForce)
|
||||
|
||||
const isOnline = await checkIfGatewayIsOnline()
|
||||
if(!isOnline) return
|
||||
switch (type) {
|
||||
|
@ -79,8 +79,8 @@ const hasExtension = (filename) => {
|
||||
return filename.includes(".") && filename.split(".").pop().length > 0;
|
||||
};
|
||||
|
||||
export const createAccount = async()=> {
|
||||
const generatedSeedPhrase = generateRandomSentence()
|
||||
export const createAccount = async(generatedSeedPhrase)=> {
|
||||
if(!generatedSeedPhrase) throw new Error('No generated seed-phrase')
|
||||
const threads = doInitWorkers(crypto.kdfThreads)
|
||||
|
||||
const seed = await kdf(generatedSeedPhrase, void 0, threads)
|
||||
@ -118,3 +118,12 @@ fileName = hasExtension(fileName) ? fileName : fileName + "." + fileExtension;
|
||||
await saveAs(blob, fileName);
|
||||
|
||||
}
|
||||
|
||||
export const saveSeedPhraseToDisk = async (data) => {
|
||||
|
||||
const blob = new Blob([data], { type: 'text/plain;charset=utf-8' })
|
||||
const fileName = "qortal_seedphrase.txt"
|
||||
|
||||
await saveAs(blob, fileName);
|
||||
|
||||
}
|
173
src/utils/seedPhrase/RandomSentenceGenerator.ts
Normal file
173
src/utils/seedPhrase/RandomSentenceGenerator.ts
Normal file
@ -0,0 +1,173 @@
|
||||
// Author: irontiga <irontiga@gmail.com>
|
||||
|
||||
import { html, LitElement, css } from 'lit'
|
||||
import * as WORDLISTS from './wordList'
|
||||
|
||||
class RandomSentenceGenerator extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
template: { type: String, attribute: 'template' },
|
||||
parsedString: { type: String },
|
||||
fetchedWordlistCount: { type: Number, value: 0 },
|
||||
capitalize: { type: Boolean },
|
||||
partsOfSpeechMap: { type: Object },
|
||||
templateEntropy: { type: Number, reflect: true, attribute: 'template-entropy' },
|
||||
maxWordLength: { type: Number, attribute: 'max-word-length' }
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.template = 'adjective noun verb adverb.'
|
||||
this.maxWordLength = 0
|
||||
this.parsedString = ''
|
||||
this.fetchedWordlistCount = 0
|
||||
this.capitalize = true
|
||||
this.partsOfSpeechMap = {
|
||||
'noun': 'nouns',
|
||||
'adverb': 'adverbs',
|
||||
'adv': 'adverbs',
|
||||
'verb': 'verbs',
|
||||
'interjection': 'interjections',
|
||||
'adjective': 'adjectives',
|
||||
'adj': 'adjectives',
|
||||
'verbed': 'verbed'
|
||||
}
|
||||
this.partsOfSpeech = Object.keys(this.partsOfSpeechMap)
|
||||
this._wordlists = WORDLISTS
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
div {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
background-color: #1f2023;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
}
|
||||
`;
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div>${this.parsedString}</div>
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
|
||||
firstUpdated() {
|
||||
// ...
|
||||
}
|
||||
|
||||
updated(changedProperties) {
|
||||
let regen = false
|
||||
|
||||
if (changedProperties.has('template')) {
|
||||
regen = true
|
||||
}
|
||||
|
||||
if (changedProperties.has('maxWordLength')) {
|
||||
console.dir(this.maxWordLength)
|
||||
|
||||
if (this.maxWordLength) {
|
||||
const wl = { ...this._wordlists }
|
||||
|
||||
for (const partOfSpeech in this._wordlists) {
|
||||
if (Array.isArray(this._wordlists[partOfSpeech])) {
|
||||
wl[partOfSpeech] = this._wordlists[partOfSpeech].filter(word => word.length <= this.maxWordLength)
|
||||
}
|
||||
}
|
||||
|
||||
this._wordlists = wl
|
||||
}
|
||||
|
||||
regen = true
|
||||
}
|
||||
|
||||
if (regen) this.generate()
|
||||
}
|
||||
|
||||
_RNG(entropy) {
|
||||
if (entropy > 1074) {
|
||||
throw new Error('Javascript can not handle that much entropy!')
|
||||
}
|
||||
|
||||
let randNum = 0
|
||||
|
||||
const crypto = window.crypto || window.msCrypto
|
||||
|
||||
if (crypto) {
|
||||
const entropy256 = Math.ceil(entropy / 8)
|
||||
|
||||
let buffer = new Uint8Array(entropy256)
|
||||
|
||||
crypto.getRandomValues(buffer)
|
||||
|
||||
randNum = buffer.reduce((num, value) => {
|
||||
return num * value
|
||||
}, 1) / Math.pow(256, entropy256)
|
||||
} else {
|
||||
console.warn('Secure RNG not found. Using Math.random')
|
||||
|
||||
randNum = Math.random()
|
||||
}
|
||||
|
||||
return randNum
|
||||
}
|
||||
|
||||
setRNG(fn) {
|
||||
this._RNG = fn
|
||||
}
|
||||
|
||||
_captitalize(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||
}
|
||||
|
||||
getWord(partOfSpeech) {
|
||||
const words = this._wordlists[this.partsOfSpeechMap[partOfSpeech]]
|
||||
const requiredEntropy = Math.log(words.length) / Math.log(2)
|
||||
const index = this._RNG(requiredEntropy) * words.length
|
||||
|
||||
return {
|
||||
word: words[Math.round(index)],
|
||||
entropy: words.length
|
||||
}
|
||||
}
|
||||
|
||||
generate() {
|
||||
this.parsedString = this.parse(this.template)
|
||||
}
|
||||
|
||||
parse(template) {
|
||||
const split = template.split(/[\s]/g)
|
||||
|
||||
let entropy = 1
|
||||
|
||||
const final = split.map(word => {
|
||||
const lower = word.toLowerCase()
|
||||
|
||||
this.partsOfSpeech.some(partOfSpeech => {
|
||||
const partOfSpeechIndex = lower.indexOf(partOfSpeech) // Check it exists
|
||||
const nextChar = word.charAt(partOfSpeech.length)
|
||||
|
||||
if (partOfSpeechIndex === 0 && !(nextChar && (nextChar.match(/[a-zA-Z]/g) != null))) {
|
||||
const replacement = this.getWord(partOfSpeech)
|
||||
word = replacement.word + word.slice(partOfSpeech.length) // Append the rest of the "word" (punctuation)
|
||||
entropy = entropy * replacement.entropy
|
||||
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
return word
|
||||
})
|
||||
|
||||
this.templateEntropy = Math.floor(Math.log(entropy) / Math.log(8))
|
||||
|
||||
return final.join(' ')
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('random-sentence-generator', RandomSentenceGenerator)
|
||||
|
||||
export default RandomSentenceGenerator
|
40
src/utils/seedPhrase/verb-past-tense.ts
Normal file
40
src/utils/seedPhrase/verb-past-tense.ts
Normal file
@ -0,0 +1,40 @@
|
||||
export const EXCEPTIONS = {
|
||||
'are': 'were',
|
||||
'eat': 'ate',
|
||||
'go': 'went',
|
||||
'have': 'had',
|
||||
'inherit': 'inherited',
|
||||
'is': 'was',
|
||||
'run': 'ran',
|
||||
'sit': 'sat',
|
||||
'visit': 'visited'
|
||||
}
|
||||
|
||||
export const getPastTense = (verb, exceptions = EXCEPTIONS) => {
|
||||
if (exceptions[verb]) {
|
||||
return exceptions[verb]
|
||||
}
|
||||
|
||||
if ((/e$/i).test(verb)) {
|
||||
return verb + 'd'
|
||||
}
|
||||
|
||||
if ((/[aeiou]c$/i).test(verb)) {
|
||||
return verb + 'ked'
|
||||
}
|
||||
|
||||
// for american english only
|
||||
if ((/el$/i).test(verb)) {
|
||||
return verb + 'ed'
|
||||
}
|
||||
|
||||
if ((/[aeio][aeiou][dlmnprst]$/).test(verb)) {
|
||||
return verb + 'ed'
|
||||
}
|
||||
|
||||
if ((/[aeiou][bdglmnprst]$/i).test(verb)) {
|
||||
return verb.replace(/(.+[aeiou])([bdglmnprst])/, '$1$2$2ed')
|
||||
}
|
||||
|
||||
return verb + 'ed'
|
||||
}
|
32
src/utils/seedPhrase/wordList.ts
Normal file
32
src/utils/seedPhrase/wordList.ts
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user