Merge pull request #33 from Qortal/feature/background-colors
Feature/background colors
416
package-lock.json
generated
@ -41,6 +41,7 @@
|
||||
"@tiptap/starter-kit": "^2.5.9",
|
||||
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
||||
"@types/chrome": "^0.0.263",
|
||||
"@uiw/react-color": "^2.5.1",
|
||||
"adm-zip": "^0.5.16",
|
||||
"asmcrypto.js": "2.3.2",
|
||||
"axios": "^1.7.7",
|
||||
@ -5900,6 +5901,399 @@
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/color-convert": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.5.1.tgz",
|
||||
"integrity": "sha512-p+P8Ho0Z1AbUprES0hcLEDAaXbGH92TmjckkRQZ5S7HcyQ+9ZXlSsDFILjFbYu/okVjx5VG59T57Dx84lv9AWA==",
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color/-/react-color-2.5.1.tgz",
|
||||
"integrity": "sha512-u6Kj7rdhsMOls2KItpHLkG8WTghDS2jYBucLeOLLJXJDs25TuEBI9d1o939og8cUJtTwBrowWFFU63a1kGsciA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1",
|
||||
"@uiw/react-color-block": "2.5.1",
|
||||
"@uiw/react-color-chrome": "2.5.1",
|
||||
"@uiw/react-color-circle": "2.5.1",
|
||||
"@uiw/react-color-colorful": "2.5.1",
|
||||
"@uiw/react-color-compact": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1",
|
||||
"@uiw/react-color-editable-input-hsla": "2.5.1",
|
||||
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||
"@uiw/react-color-github": "2.5.1",
|
||||
"@uiw/react-color-hue": "2.5.1",
|
||||
"@uiw/react-color-material": "2.5.1",
|
||||
"@uiw/react-color-name": "2.5.1",
|
||||
"@uiw/react-color-saturation": "2.5.1",
|
||||
"@uiw/react-color-shade-slider": "2.5.1",
|
||||
"@uiw/react-color-sketch": "2.5.1",
|
||||
"@uiw/react-color-slider": "2.5.1",
|
||||
"@uiw/react-color-swatch": "2.5.1",
|
||||
"@uiw/react-color-wheel": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-alpha": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-alpha/-/react-color-alpha-2.5.1.tgz",
|
||||
"integrity": "sha512-hPsIgsnuOQrqinXt3Gt+87fHudbUvvPW+TpvRY0HS9v4ptFu5UsCc/7DPTVKTaL+p+0oaA6eTbziLzPLRLzgsQ==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-drag-event-interactive": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-block": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-block/-/react-color-block-2.5.1.tgz",
|
||||
"integrity": "sha512-qvubiV0z0P3OxpNt6o1UQ3CVsjVBY1/n/oz6Gzzxx9YPqSClI04AtFjwOQxF7M17SYqXv+88y77gfEfPIqk5+A==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1",
|
||||
"@uiw/react-color-swatch": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-chrome": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-chrome/-/react-color-chrome-2.5.1.tgz",
|
||||
"integrity": "sha512-m/CyRaWgmkW5aQTQ8AZwyvopYm+bhvX06uS+ezQjXDYDtjLvq7RbM0JLLNIOyMXke964R58fhoX4G06ZWd8ycA==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1",
|
||||
"@uiw/react-color-editable-input-hsla": "2.5.1",
|
||||
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||
"@uiw/react-color-github": "2.5.1",
|
||||
"@uiw/react-color-hue": "2.5.1",
|
||||
"@uiw/react-color-saturation": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-circle": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-circle/-/react-color-circle-2.5.1.tgz",
|
||||
"integrity": "sha512-+8zb/Ork1Q5f2bq0jN+GF7OyqY+2ZDYGrdZovN3EBZLMmERbg6TM2+1gTweeFsdiEM/gpteupJpwKpO1aBCocg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-swatch": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-colorful": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-colorful/-/react-color-colorful-2.5.1.tgz",
|
||||
"integrity": "sha512-Y/8Y2Kman6IZQpgs4tPTGPuTNr3fJIJxf4f13jll6xuaOsVZeDq9q+DlMErggL+5ICtaBr8gG+w68nCiY+QqKg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1",
|
||||
"@uiw/react-color-hue": "2.5.1",
|
||||
"@uiw/react-color-saturation": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-compact": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-compact/-/react-color-compact-2.5.1.tgz",
|
||||
"integrity": "sha512-5jHJcXEkjMwcghzCgSBU2rPMVjuuaJ7B6IxypNkafRQ4FkW/6bP9WpPkzcNXCZ/gPvSJ1OMQ+Y600mdO78qG5Q==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1",
|
||||
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||
"@uiw/react-color-swatch": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-editable-input": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-editable-input/-/react-color-editable-input-2.5.1.tgz",
|
||||
"integrity": "sha512-0kr5vQJGPln8LObXwfI2YLiHFz2DW3Atgi51JXlrZUyyaVujXRgMTAc1fz/1RQR6cU2A4bweFaCQljcTsv+Cdg==",
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-editable-input-hsla": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-editable-input-hsla/-/react-color-editable-input-hsla-2.5.1.tgz",
|
||||
"integrity": "sha512-gmnXB6JrYFAd8VN/EfNDJaTdkFHAnUxjzcsQjQyOEr046jDjWgEc/5o2uE1LwIvoJNg9Lo6LYsr37LnFWwsiLw==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-editable-input-rgba": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-editable-input-rgba": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-editable-input-rgba/-/react-color-editable-input-rgba-2.5.1.tgz",
|
||||
"integrity": "sha512-rk6OxL9lTdRI45aNe3GbUghvaELk4knkEf0gvF/mPHxoeE+nNphSrO5gHm3HhoDOgaplp81VP3q4gUwcdjBzvw==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-github": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-github/-/react-color-github-2.5.1.tgz",
|
||||
"integrity": "sha512-t05rIy2ifReiVnjv3x+IVlJH7wvwtZugMeouDa/1Y7jIGZswO0zw3zMxz7qfHrzf5NVYWjmEF8QCj85ngv9brg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-swatch": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-hue": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-hue/-/react-color-hue-2.5.1.tgz",
|
||||
"integrity": "sha512-o7mjZhm+U4gHxaBXFxjPINeE3jWfiZAl7RUFqwn4PDZC8wvhU5hEKgJUvcXzErYro0ZYrE1fC/wUHRpI+vcEBg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-material": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-material/-/react-color-material-2.5.1.tgz",
|
||||
"integrity": "sha512-iPB4YfKVTNO1lSIQ16DMdDurDKvGTjv6Qwi/nq47yE3nnhB0YbOFwb/IZbWBS1sCTPx1an7dM2IZ+hYoYcjrXg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1",
|
||||
"@uiw/react-color-editable-input-rgba": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-name": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-name/-/react-color-name-2.5.1.tgz",
|
||||
"integrity": "sha512-JFb6DFz9kF2jI42MS/vtXZu1XzIrzcSIOqCwVkYWCQnSxOM9h+vd4pv2Yi1oy7IPgaadXUDkrGQSAvEkXU593Q==",
|
||||
"dependencies": {
|
||||
"colors-named": "^1.0.1",
|
||||
"colors-named-hex": "^1.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-saturation": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-saturation/-/react-color-saturation-2.5.1.tgz",
|
||||
"integrity": "sha512-mQ6eGmn6dUXfScQrb5tP0TBGCpZWzrQuYOAiwK9u31IJaxFwD1NNAzkiienWe4MQkA5zmgz7Ol6FEdLN8K+vGw==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-drag-event-interactive": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-shade-slider": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-shade-slider/-/react-color-shade-slider-2.5.1.tgz",
|
||||
"integrity": "sha512-hrscAmqmy/Od/usUPETaEuvsNRhUGvNArl73d7HK6e6FjbRFPDBq40LkvjETe8BJMbxrBXTMo6dK7DO08lYq9g==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-sketch": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-sketch/-/react-color-sketch-2.5.1.tgz",
|
||||
"integrity": "sha512-eQgAnlSZvqoTt6frZa/j+tFdaIBEFneIdxEUfidD8hwvyu5OR/WLHnDy/4fYAxhehDp9Ej8eS3ZsCgPACBMOtA==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1",
|
||||
"@uiw/react-color-editable-input": "2.5.1",
|
||||
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||
"@uiw/react-color-hue": "2.5.1",
|
||||
"@uiw/react-color-saturation": "2.5.1",
|
||||
"@uiw/react-color-swatch": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-slider": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-slider/-/react-color-slider-2.5.1.tgz",
|
||||
"integrity": "sha512-2yluI0Akp6UMXTeAJ4CEjL8flhIFpn3xUPsFXbQmBSzMYJygleVFmwhMye8LSA2PCe3UdaqA2cWXxWsTL0FbIg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-color-alpha": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-swatch": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-swatch/-/react-color-swatch-2.5.1.tgz",
|
||||
"integrity": "sha512-EQ7UEzxdohfsdpXmcEWNmK/uiznZovEKo6+j3OLrSU5pZGO7pxjR9sQMlscikvd8Mu1Mm3U0E6bJseo2acD4Lg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-color-wheel": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-color-wheel/-/react-color-wheel-2.5.1.tgz",
|
||||
"integrity": "sha512-e3tDwDoC2T7zTapRRm/QxcOJ7IWJwNCoxZ/f97RL1Ib3gAN/k67H1bkR9TK7euRCUxGy031guxTgdKO9v19XFg==",
|
||||
"dependencies": {
|
||||
"@uiw/color-convert": "2.5.1",
|
||||
"@uiw/react-drag-event-interactive": "2.5.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uiw/react-drag-event-interactive": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-2.5.1.tgz",
|
||||
"integrity": "sha512-GNxhxk5L4O5Gpi20A/BG5sO0GNBNwtNWJidJsJu3pgHUBErN4rhqTDXXu3BQTz5C8yOG5D02Y6Zq/6yu6ckImw==",
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/runtime": ">=7.19.0",
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/structured-clone": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||
@ -7774,6 +8168,28 @@
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/colors-named": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/colors-named/-/colors-named-1.0.2.tgz",
|
||||
"integrity": "sha512-2ANq2r393PV9njYUD66UdfBcxR1slMqRA3QRTWgCx49JoCJ+kOhyfbQYxKJbPZQIhZUcNjVOs5AlyY1WwXec3w==",
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/colors-named-hex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/colors-named-hex/-/colors-named-hex-1.0.2.tgz",
|
||||
"integrity": "sha512-k6kq1e1pUCQvSVwIaGFq2l0LrkAPQZWyeuZn1Z8nOiYSEZiKoFj4qx690h2Kd34DFl9Me0gKS6MUwAMBJj8nuA==",
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
@ -46,6 +46,7 @@
|
||||
"@tiptap/starter-kit": "^2.5.9",
|
||||
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
||||
"@types/chrome": "^0.0.263",
|
||||
"@uiw/react-color": "^2.5.1",
|
||||
"adm-zip": "^0.5.16",
|
||||
"asmcrypto.js": "2.3.2",
|
||||
"axios": "^1.7.7",
|
||||
|
108
src/App.tsx
@ -30,14 +30,12 @@ import { CountdownCircleTimer } from 'react-countdown-circle-timer';
|
||||
import Logo1Dark from './assets/svgs/Logo1Dark.svg';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
import Copy from './assets/svgs/Copy.svg';
|
||||
import ltcLogo from './assets/ltc.png';
|
||||
import PersonSearchIcon from '@mui/icons-material/PersonSearch';
|
||||
import qortLogo from './assets/qort.png';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import { Return } from './assets/Icons/Return.tsx';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import Success from './assets/svgs/Success.svg';
|
||||
import './utils/seedPhrase/RandomSentenceGenerator';
|
||||
import EngineeringIcon from '@mui/icons-material/Engineering';
|
||||
import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
|
||||
@ -137,6 +135,8 @@ import ThemeSelector from './components/Theme/ThemeSelector.tsx';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import LanguageSelector from './components/Language/LanguageSelector.tsx';
|
||||
import { DownloadWallet } from './components/Auth/DownloadWallet.tsx';
|
||||
import { CopyIcon } from './assets/Icons/CopyIcon.tsx';
|
||||
import { SuccessIcon } from './assets/Icons/SuccessIcon.tsx';
|
||||
|
||||
type extStates =
|
||||
| 'not-authenticated'
|
||||
@ -1297,7 +1297,8 @@ function App() {
|
||||
<CopyToClipboard text={rawWallet?.ltcAddress}>
|
||||
<AddressBox>
|
||||
{rawWallet?.ltcAddress?.slice(0, 6)}...
|
||||
{rawWallet?.ltcAddress?.slice(-4)} <img src={Copy} />
|
||||
{rawWallet?.ltcAddress?.slice(-4)}{' '}
|
||||
<CopyIcon color={theme.palette.text.primary} />
|
||||
</AddressBox>
|
||||
</CopyToClipboard>
|
||||
|
||||
@ -1362,7 +1363,8 @@ function App() {
|
||||
<CopyToClipboard text={rawWallet?.address0}>
|
||||
<AddressBox>
|
||||
{rawWallet?.address0?.slice(0, 6)}...
|
||||
{rawWallet?.address0?.slice(-4)} <img src={Copy} />
|
||||
{rawWallet?.address0?.slice(-4)}{' '}
|
||||
<CopyIcon color={theme.palette.text.primary} />
|
||||
</AddressBox>
|
||||
</CopyToClipboard>
|
||||
<Spacer height="10px" />
|
||||
@ -1471,6 +1473,7 @@ function App() {
|
||||
sx={{
|
||||
height: '100%',
|
||||
justifyContent: 'space-between',
|
||||
borderLeft: `1px solid ${theme.palette.border.subtle}`,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@ -1508,7 +1511,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1518,7 +1521,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<LogoutIcon />
|
||||
<LogoutIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
|
||||
@ -1548,7 +1555,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1558,7 +1565,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SettingsIcon />
|
||||
<SettingsIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
|
||||
@ -1588,7 +1599,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1598,7 +1609,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<PersonSearchIcon />
|
||||
<PersonSearchIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
|
||||
@ -1628,7 +1643,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1638,7 +1653,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<AccountBalanceWalletIcon />
|
||||
<AccountBalanceWalletIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
|
||||
@ -1665,7 +1684,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1680,7 +1699,10 @@ function App() {
|
||||
setIsOpenDrawerProfile(true);
|
||||
}}
|
||||
>
|
||||
<WalletIcon width="25" />
|
||||
<WalletIcon
|
||||
color={theme.palette.text.secondary}
|
||||
width="25"
|
||||
/>
|
||||
</ButtonBase>
|
||||
</Tooltip>
|
||||
</>
|
||||
@ -1776,7 +1798,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1786,7 +1808,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<EngineeringIcon />
|
||||
<EngineeringIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
|
||||
@ -1821,7 +1847,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1831,7 +1857,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<HelpIcon />
|
||||
<HelpIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
)}
|
||||
@ -1863,7 +1893,7 @@ function App() {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -1873,7 +1903,11 @@ function App() {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DownloadIcon />
|
||||
<DownloadIcon
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
<Spacer height="40px" />
|
||||
@ -2164,10 +2198,10 @@ function App() {
|
||||
defaultChecked={messageQortalRequest?.checkbox1?.value}
|
||||
sx={{
|
||||
'&.Mui-checked': {
|
||||
color: 'white', // Customize the color when checked
|
||||
color: theme.palette.text.secondary, // Customize the color when checked
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@ -2897,7 +2931,7 @@ function App() {
|
||||
{walletToBeDownloaded && (
|
||||
<>
|
||||
<Spacer height="48px" />
|
||||
<img src={Success} />
|
||||
<SuccessIcon />
|
||||
<Spacer height="45px" />
|
||||
<TextP
|
||||
sx={{
|
||||
@ -2953,7 +2987,7 @@ function App() {
|
||||
}}
|
||||
>
|
||||
<Spacer height="48px" />
|
||||
<img src={Success} />
|
||||
<SuccessIcon />
|
||||
<Spacer height="45px" />
|
||||
<TextP
|
||||
sx={{
|
||||
@ -2978,7 +3012,7 @@ function App() {
|
||||
{extState === 'transfer-success-request' && (
|
||||
<>
|
||||
<Spacer height="48px" />
|
||||
<img src={Success} />
|
||||
<SuccessIcon />
|
||||
<Spacer height="45px" />
|
||||
<TextP
|
||||
sx={{
|
||||
@ -3003,7 +3037,7 @@ function App() {
|
||||
{extState === 'buy-order-submitted' && (
|
||||
<>
|
||||
<Spacer height="48px" />
|
||||
<img src={Success} />
|
||||
<SuccessIcon />
|
||||
<Spacer height="45px" />
|
||||
<TextP
|
||||
sx={{
|
||||
@ -3087,12 +3121,12 @@ function App() {
|
||||
<DialogActions>
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
@ -3107,12 +3141,12 @@ function App() {
|
||||
</Button>
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
@ -3406,10 +3440,10 @@ function App() {
|
||||
}
|
||||
sx={{
|
||||
'&.Mui-checked': {
|
||||
color: 'white', // Customize the color when checked
|
||||
color: theme.palette.text.secondary, // Customize the color when checked
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@ -3435,10 +3469,10 @@ function App() {
|
||||
disableRipple
|
||||
sx={{
|
||||
'&.Mui-checked': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
@ -3466,7 +3500,7 @@ function App() {
|
||||
>
|
||||
<CustomButtonAccept
|
||||
color="black"
|
||||
bgColor="var(--green)"
|
||||
bgColor={theme.palette.other.positive}
|
||||
sx={{
|
||||
minWidth: '102px',
|
||||
opacity:
|
||||
@ -3502,7 +3536,7 @@ function App() {
|
||||
</CustomButtonAccept>
|
||||
<CustomButtonAccept
|
||||
color="black"
|
||||
bgColor="var(--danger)"
|
||||
bgColor={theme.palette.other.danger}
|
||||
sx={{
|
||||
minWidth: '102px',
|
||||
}}
|
||||
@ -3559,7 +3593,7 @@ function App() {
|
||||
>
|
||||
<HelpIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
@ -562,11 +562,12 @@ export const NotAuthenticated = ({
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
hasSeenGettingStarted === false && 'var(--green)',
|
||||
hasSeenGettingStarted === false && theme.palette.other.positive,
|
||||
color: hasSeenGettingStarted === false && 'black',
|
||||
'&:hover': {
|
||||
backgroundColor:
|
||||
hasSeenGettingStarted === false && 'var(--green)',
|
||||
hasSeenGettingStarted === false &&
|
||||
theme.palette.other.positive,
|
||||
color: hasSeenGettingStarted === false && 'black',
|
||||
},
|
||||
}}
|
||||
@ -631,15 +632,6 @@ export const NotAuthenticated = ({
|
||||
}}
|
||||
control={
|
||||
<Switch
|
||||
sx={{
|
||||
'& .MuiSwitch-switchBase.Mui-checked': {
|
||||
color: '#5EB049',
|
||||
},
|
||||
'& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track':
|
||||
{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
}}
|
||||
checked={useLocalNode}
|
||||
onChange={(event) => {
|
||||
if (event.target.checked) {
|
||||
@ -1086,7 +1078,7 @@ export const NotAuthenticated = ({
|
||||
>
|
||||
<HelpIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
@ -48,7 +48,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
const [password, setPassword] = useState('');
|
||||
const [isOpenSeedModal, setIsOpenSeedModal] = useState(false);
|
||||
const [isLoadingEncryptSeed, setIsLoadingEncryptSeed] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const { isShow, onCancel, onOk, show } = useModal();
|
||||
|
||||
const { getRootProps, getInputProps } = useDropzone({
|
||||
@ -216,7 +216,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
maxHeight: '60vh',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden',
|
||||
backgroundColor: 'rgb(30 30 32 / 70%)',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
}}
|
||||
>
|
||||
{wallets?.map((wallet, idx) => {
|
||||
@ -429,7 +429,7 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => {
|
||||
bgcolor: theme.palette.background.default,
|
||||
flexGrow: 1,
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
transform: 'scale(1.01)',
|
||||
},
|
||||
transition: 'all 0.1s ease-in-out',
|
||||
@ -539,12 +539,12 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => {
|
||||
</Button>
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
},
|
||||
'&:focus': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
},
|
||||
}}
|
||||
size="small"
|
||||
|
@ -1,12 +1,18 @@
|
||||
import React from 'react';
|
||||
|
||||
export const ChatIcon= ({ color = 'white', height = 15, width = 15 }) => {
|
||||
return (
|
||||
<svg width={width} height={height} viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.5 0C3.35915 0 0 3.35915 0 7.5V13.8169C0 14.4718 0.528169 15 1.1831 15H7.5C11.6408 15 15 11.6408 15 7.5C15 3.35915 11.6408 0 7.5 0ZM11.0915 10.669H3.90845C3.67606 10.669 3.48592 10.4789 3.48592 10.2465C3.48592 10.0141 3.67606 9.82394 3.90845 9.82394H11.0915C11.3239 9.82394 11.5141 10.0141 11.5141 10.2465C11.5141 10.4789 11.3239 10.669 11.0915 10.669ZM11.0915 8.34507H3.90845C3.67606 8.34507 3.48592 8.15493 3.48592 7.92254C3.48592 7.69014 3.67606 7.5 3.90845 7.5H11.0915C11.3239 7.5 11.5141 7.69014 11.5141 7.92254C11.5141 8.15493 11.3239 8.34507 11.0915 8.34507ZM11.0915 6.02113H3.90845C3.67606 6.02113 3.48592 5.83099 3.48592 5.59859C3.48592 5.3662 3.67606 5.17606 3.90845 5.17606H11.0915C11.3239 5.17606 11.5141 5.3662 11.5141 5.59859C11.5141 5.83099 11.3239 6.02113 11.0915 6.02113Z" fill={color}/>
|
||||
</svg>
|
||||
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export const ChatIcon = ({ color = 'white', height = 15, width = 15 }) => {
|
||||
return (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.5 0C3.35915 0 0 3.35915 0 7.5V13.8169C0 14.4718 0.528169 15 1.1831 15H7.5C11.6408 15 15 11.6408 15 7.5C15 3.35915 11.6408 0 7.5 0ZM11.0915 10.669H3.90845C3.67606 10.669 3.48592 10.4789 3.48592 10.2465C3.48592 10.0141 3.67606 9.82394 3.90845 9.82394H11.0915C11.3239 9.82394 11.5141 10.0141 11.5141 10.2465C11.5141 10.4789 11.3239 10.669 11.0915 10.669ZM11.0915 8.34507H3.90845C3.67606 8.34507 3.48592 8.15493 3.48592 7.92254C3.48592 7.69014 3.67606 7.5 3.90845 7.5H11.0915C11.3239 7.5 11.5141 7.69014 11.5141 7.92254C11.5141 8.15493 11.3239 8.34507 11.0915 8.34507ZM11.0915 6.02113H3.90845C3.67606 6.02113 3.48592 5.83099 3.48592 5.59859C3.48592 5.3662 3.67606 5.17606 3.90845 5.17606H11.0915C11.3239 5.17606 11.5141 5.3662 11.5141 5.59859C11.5141 5.83099 11.3239 6.02113 11.0915 6.02113Z"
|
||||
fill={color}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
33
src/assets/Icons/ComposeIcon.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
import { SVGProps } from './interfaces';
|
||||
|
||||
export const ComposeIcon: React.FC<SVGProps> = ({
|
||||
color,
|
||||
height = 20,
|
||||
width = 20,
|
||||
opacity,
|
||||
...children
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = color ? color : theme.palette.text.primary;
|
||||
const setOpacity = opacity ? opacity : 1;
|
||||
|
||||
return (
|
||||
<svg
|
||||
{...children}
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 64 64"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M50.3 3c1.5 0 3.9 0.6 5.5 1.4 1.5 0.7 3.3 2.5 4 4 0.6 1.4 1.2 3.7 1.2 5.1 0 1.4-0.6 3.7-1.4 5.3-0.8 1.5-9.9 11.1-39.1 40l-6.7 1.6c-3.8 0.9-7.9 1.6-9.3 1.6-1.8 0-2.5-0.5-2.5-2 0-1.1 0.7-5.3 3.2-16.5l18.1-18.4c10-10 19.6-19.2 21.2-20.2 1.7-1 4.2-1.9 5.8-1.9zm-8.4 11.3c0 0.7 1.5 2.7 3.3 4.4 1.8 1.8 3.9 3.3 4.6 3.3 0.6 0 2.3-1.4 3.7-3 1.4-1.7 2.5-4 2.5-5.3 0.1-1.2-0.7-3-1.7-3.9-1-1-2.8-1.8-4-1.8-1.2 0-3.5 1.2-5.3 2.6-1.7 1.4-3.1 3.1-3.1 3.7z"
|
||||
fill={setColor}
|
||||
opacity={setOpacity}
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
25
src/assets/Icons/CopyIcon.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
export const CopyIcon = ({ color, height = 11, width = 10 }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = color ? color : theme.palette.text.primary;
|
||||
return (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 10 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M3.92857 0.5H8.57143C9.36071 0.5 10 1.13929 10 1.92857V6.57143C10 7.36071 9.36071 8 8.57143 8H8.21429V4.42857C8.21429 3.24643 7.25357 2.28571 6.07143 2.28571H2.5V1.92857C2.5 1.13929 3.13929 0.5 3.92857 0.5ZM1.42857 3H6.07143C6.86041 3 7.5 3.63959 7.5 4.42857V9.07143C7.5 9.86041 6.86041 10.5 6.07143 10.5H1.42857C0.639593 10.5 0 9.86041 0 9.07143V4.42857C0 3.63959 0.639593 3 1.42857 3Z"
|
||||
fill={setColor}
|
||||
fill-opacity="0.5"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -1,15 +1,18 @@
|
||||
import React from 'react';
|
||||
import { styled } from '@mui/system';
|
||||
import { SVGProps } from './interfaces';
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
// Create a styled container with hover effects
|
||||
const SvgContainer = styled('svg')({
|
||||
const SvgContainer = styled('svg')<{ color?: string }>(({ color }) => ({
|
||||
'& path': {
|
||||
fill: 'rgba(41, 41, 43, 1)', // Default to red if no color prop
|
||||
fill: color,
|
||||
},
|
||||
});
|
||||
}));
|
||||
export const CreateThreadIcon: React.FC<SVGProps> = ({ color }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
export const CreateThreadIcon: React.FC<SVGProps> = ({ color, opacity }) => {
|
||||
const setColor = color || theme.palette.text.primary;
|
||||
return (
|
||||
<SvgContainer
|
||||
width="20"
|
||||
@ -17,6 +20,7 @@ export const CreateThreadIcon: React.FC<SVGProps> = ({ color, opacity }) => {
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
color={setColor}
|
||||
>
|
||||
<path
|
||||
d="M0 9.80209V9.0205C0.0460138 8.67679 0.080024 8.31425 0.144043 7.98466C0.469856 6.30568 1.25577 4.79934 2.38071 3.6977C4.13924 1.88262 6.22987 0.985679 8.52256 0.674927C9.9086 0.485649 11.3116 0.565177 12.6758 0.910345C14.5124 1.34351 16.1889 2.2075 17.6053 3.67886C18.7276 4.84183 19.5319 6.24257 19.858 7.98466C19.918 8.31189 19.952 8.64383 20 8.97577V9.80209C19.9827 9.8676 19.9693 9.93447 19.96 10.0022C19.8708 11.2186 19.5113 12.3861 18.9177 13.3875C17.961 15.0025 16.6297 16.2594 15.0825 17.0082C12.4657 18.3525 9.75693 18.5667 6.98209 17.8346C6.8589 17.8074 6.73157 17.8264 6.61799 17.8887C5.15955 18.7339 3.70511 19.5908 2.24867 20.4501C2.18866 20.4854 2.12464 20.5183 2.0146 20.5748L3.78714 16.3703C3.37301 16.0148 2.96889 15.7017 2.60078 15.3415C1.42243 14.1879 0.556167 12.7895 0.182055 11.0192C0.0980294 10.6213 0.060018 10.2094 0 9.80209ZM14.0042 10.5931C14.1362 10.5968 14.2676 10.5698 14.3907 10.5135C14.5138 10.4572 14.6262 10.3728 14.7214 10.2651C14.8167 10.1574 14.8928 10.0286 14.9455 9.8861C14.9982 9.7436 15.0264 9.59023 15.0285 9.43484V9.4113C15.0285 9.25517 15.0024 9.10058 14.9516 8.95634C14.9008 8.8121 14.8264 8.68104 14.7326 8.57064C14.6388 8.46025 14.5274 8.37268 14.4048 8.31293C14.2823 8.25319 14.1509 8.22243 14.0182 8.22243C13.8855 8.22243 13.7542 8.25319 13.6316 8.31293C13.509 8.37268 13.3976 8.46025 13.3038 8.57064C13.21 8.68104 13.1356 8.8121 13.0848 8.95634C13.034 9.10058 13.0079 9.25517 13.0079 9.4113C13.0074 9.56588 13.0327 9.71906 13.0825 9.86211C13.1323 10.0052 13.2055 10.1353 13.2981 10.245C13.3906 10.3547 13.5005 10.442 13.6217 10.5017C13.7429 10.5614 13.8728 10.5925 14.0042 10.5931ZM10.003 10.5931C10.203 10.5926 10.3983 10.5225 10.5644 10.3915C10.7306 10.2606 10.86 10.0746 10.9364 9.85719C11.0129 9.63976 11.0329 9.40056 10.9939 9.16977C10.9549 8.93898 10.8588 8.72694 10.7175 8.5604C10.5763 8.39385 10.3962 8.28026 10.2002 8.23396C10.0041 8.18765 9.80084 8.21071 9.61591 8.30022C9.43099 8.38973 9.27273 8.54168 9.1611 8.7369C9.04948 8.93212 8.98949 9.16187 8.9887 9.39717C8.98975 9.71356 9.09688 10.0167 9.28682 10.2406C9.47675 10.4646 9.73413 10.5912 10.003 10.5931ZM4.98349 9.3854C4.9836 9.61979 5.04316 9.8488 5.15456 10.0431C5.26595 10.2374 5.42411 10.3882 5.60876 10.476C5.79341 10.5639 5.99616 10.5849 6.19102 10.5364C6.38588 10.4878 6.56399 10.3719 6.70252 10.2035C6.84105 10.0351 6.93371 9.82183 6.96861 9.59108C7.00352 9.36032 6.97909 9.12255 6.89845 8.90823C6.8178 8.69392 6.68463 8.51281 6.51597 8.38811C6.34732 8.26342 6.15087 8.20081 5.95179 8.20831C5.69208 8.21809 5.44579 8.34641 5.26507 8.56611C5.08434 8.78581 4.98336 9.07963 4.98349 9.3854Z"
|
||||
|
@ -1,14 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export const MessagingIcon2= ({ color = '#8F8F91', height = 24, width =24 }) => {
|
||||
return (
|
||||
<svg width={width} height={height} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M22.6636 0.00168233C22.6127 -0.000756257 22.5614 -0.000627677 22.5099 0.00261984C22.3724 0.0112798 22.2331 0.0405753 22.0969 0.093558L1.02096 8.28971C0.362343 8.54585 -0.00366118 9.18408 2.76147e-05 9.79253C0.00371641 10.401 0.377567 11.0341 1.03925 11.2822L9.02065 14.2752C9.34631 14.3974 9.60258 14.6536 9.72471 14.9793L12.7177 22.9607C12.9658 23.6224 13.5989 23.9963 14.2074 24C14.8158 24.0037 15.454 23.6376 15.7102 22.979L23.9063 1.90295C24.1182 1.35797 23.9526 0.768987 23.5917 0.408091C23.3549 0.171254 23.02 0.0187526 22.6636 0.00168233ZM18.4022 4.99812C18.5613 4.99815 18.7139 5.06138 18.8264 5.17391C18.9389 5.28643 19.0021 5.43902 19.0021 5.59813C19.0021 5.75724 18.9389 5.90983 18.8264 6.02235L13.2239 11.6244C13.1114 11.7369 12.9588 11.8001 12.7997 11.8001C12.6406 11.8001 12.488 11.7369 12.3755 11.6244C12.263 11.5119 12.1998 11.3593 12.1998 11.2002C12.1998 11.0411 12.263 10.8885 12.3755 10.776L17.9775 5.17391C18.0333 5.11813 18.0995 5.0739 18.1724 5.04374C18.2452 5.01357 18.3233 4.99807 18.4022 4.99812Z" fill={color}/>
|
||||
</svg>
|
||||
|
||||
|
||||
|
||||
|
||||
);
|
||||
};
|
||||
|
24
src/assets/Icons/MessagingIconFilled.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
export const MessagingIconFilled = ({ color, height = 31, width = 31 }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = color ? color : theme.palette.text.primary;
|
||||
return (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M22.6636 0.00168233C22.6127 -0.000756257 22.5614 -0.000627677 22.5099 0.00261984C22.3724 0.0112798 22.2331 0.0405753 22.0969 0.093558L1.02096 8.28971C0.362343 8.54585 -0.00366118 9.18408 2.76147e-05 9.79253C0.00371641 10.401 0.377567 11.0341 1.03925 11.2822L9.02065 14.2752C9.34631 14.3974 9.60258 14.6536 9.72471 14.9793L12.7177 22.9607C12.9658 23.6224 13.5989 23.9963 14.2074 24C14.8158 24.0037 15.454 23.6376 15.7102 22.979L23.9063 1.90295C24.1182 1.35797 23.9526 0.768987 23.5917 0.408091C23.3549 0.171254 23.02 0.0187526 22.6636 0.00168233ZM18.4022 4.99812C18.5613 4.99815 18.7139 5.06138 18.8264 5.17391C18.9389 5.28643 19.0021 5.43902 19.0021 5.59813C19.0021 5.75724 18.9389 5.90983 18.8264 6.02235L13.2239 11.6244C13.1114 11.7369 12.9588 11.8001 12.7997 11.8001C12.6406 11.8001 12.488 11.7369 12.3755 11.6244C12.263 11.5119 12.1998 11.3593 12.1998 11.2002C12.1998 11.0411 12.263 10.8885 12.3755 10.776L17.9775 5.17391C18.0333 5.11813 18.0995 5.0739 18.1724 5.04374C18.2452 5.01357 18.3233 4.99807 18.4022 4.99812Z"
|
||||
fill={setColor}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -14,8 +14,8 @@ export const QappDevelopText: React.FC<SVGProps> = ({
|
||||
return (
|
||||
<svg
|
||||
{...children}
|
||||
width="83"
|
||||
height="40"
|
||||
width="124"
|
||||
height="60"
|
||||
viewBox="0 0 83 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -1,17 +1,23 @@
|
||||
import React from 'react';
|
||||
import { styled } from '@mui/system';
|
||||
import { SVGProps } from './interfaces';
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
// Create a styled container with hover effects
|
||||
const SvgContainer = styled('svg')({
|
||||
// Make SvgContainer accept a prop
|
||||
const SvgContainer = styled('svg')<{ color?: string }>(({ color }) => ({
|
||||
'& path': {
|
||||
fill: 'rgba(41, 41, 43, 1)', // Default to red if no color prop
|
||||
fill: color,
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
export const SendNewMessage: React.FC<SVGProps> = ({ color, opacity }) => {
|
||||
export const SendNewMessage: React.FC<SVGProps> = ({ color, ...props }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = color || theme.palette.text.primary;
|
||||
return (
|
||||
<SvgContainer
|
||||
{...props}
|
||||
color={setColor}
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
|
37
src/assets/Icons/SortIcon.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
import { SVGProps } from './interfaces';
|
||||
|
||||
export const SortIcon: React.FC<SVGProps> = ({
|
||||
color,
|
||||
height = 16,
|
||||
width = 15,
|
||||
opacity,
|
||||
...children
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = color ? color : theme.palette.text.primary;
|
||||
const setOpacity = opacity ? opacity : 1;
|
||||
|
||||
return (
|
||||
<svg
|
||||
{...children}
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 15 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M14.3347 0.271977C14.0797 0.0885134 13.79 0 13.5034 0C13.0191 0 12.5424 0.251056 12.2542 0.711326L12.0008 1.11366L10.6942 3.20097L9.44204 5.19976C9.15388 5.66003 9 6.19916 9 6.75116V14.3987C9 15.2822 9.67136 16 10.4996 16C10.9145 16 11.2902 15.8214 11.5602 15.5301C11.8318 15.2404 11.9992 14.8397 11.9992 14.3987V7.57353C11.9992 7.11809 12.1275 6.6723 12.3628 6.29411L14.7465 2.48964C14.917 2.21605 15 1.90706 15 1.60129C15 1.08469 14.7646 0.577751 14.3332 0.270368L14.3347 0.271977Z"
|
||||
fill={setColor}
|
||||
opacity={setOpacity}
|
||||
/>
|
||||
<path
|
||||
d="M4.30727 3.20032L3.00075 1.11344L2.74881 0.711183C2.46065 0.251006 1.98391 0 1.49962 0C1.21297 0 0.923309 0.0884956 0.668343 0.271923C0.235353 0.579244 0 1.08608 0 1.60257C0 1.90829 0.0829771 2.21722 0.254966 2.49075L2.63716 6.29445C2.87403 6.67257 3.00075 7.11826 3.00075 7.57361V14.399C3.00075 15.2824 3.67211 16 4.50038 16C5.32864 16 6 15.2824 6 14.399V6.75141C6 6.19952 5.84762 5.6605 5.55947 5.20032L4.30576 3.20193L4.30727 3.20032Z"
|
||||
fill={setColor}
|
||||
opacity={setOpacity}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -1,4 +1,9 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
export const StarEmptyIcon = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = theme.palette.text.secondary;
|
||||
return (
|
||||
<svg
|
||||
width="12"
|
||||
@ -9,7 +14,7 @@ export const StarEmptyIcon = () => {
|
||||
>
|
||||
<path
|
||||
d="M6.2726 0.162533L7.89126 3.31595C7.9357 3.40243 8.02078 3.46234 8.11994 3.47588L11.7399 3.98173C11.8542 3.99736 11.9496 4.07446 11.9853 4.18022C12.0206 4.28598 11.9913 4.40215 11.9084 4.47977L9.28882 6.93449V6.93397C9.21729 7.00117 9.18478 7.09807 9.20157 7.19288L9.81988 10.6588C9.83939 10.7682 9.79278 10.8786 9.69903 10.9443C9.60529 11.0094 9.48119 11.0182 9.37931 10.9667L6.14144 9.32987C6.05311 9.28559 5.9469 9.28559 5.85856 9.32987L2.62069 10.9667C2.51881 11.0182 2.39472 11.0094 2.30096 10.9443C2.20722 10.8786 2.16062 10.7682 2.18012 10.6588L2.79842 7.19288C2.81522 7.09807 2.78271 7.00117 2.71118 6.93397L0.0916083 4.47978C0.0086971 4.40216 -0.0205644 4.28599 0.0146582 4.18023C0.0504232 4.07448 0.145798 3.99738 0.260135 3.98175L3.88006 3.47589C3.97923 3.46235 4.0643 3.40244 4.10874 3.31596L5.7274 0.162545C5.77888 0.0630431 5.88455 0 5.99997 0C6.11539 0 6.22113 0.0630238 6.2726 0.162533Z"
|
||||
fill="#727376"
|
||||
fill={setColor}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
export const StarFilledIcon = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = theme.palette.text.primary;
|
||||
return (
|
||||
<svg
|
||||
width="12"
|
||||
@ -9,7 +14,7 @@ export const StarFilledIcon = () => {
|
||||
>
|
||||
<path
|
||||
d="M6.2726 0.162533L7.89126 3.31595C7.9357 3.40243 8.02078 3.46234 8.11994 3.47588L11.7399 3.98173C11.8542 3.99736 11.9496 4.07446 11.9853 4.18022C12.0206 4.28598 11.9913 4.40215 11.9084 4.47977L9.28882 6.93449V6.93397C9.21729 7.00117 9.18478 7.09807 9.20157 7.19288L9.81988 10.6588C9.83939 10.7682 9.79278 10.8786 9.69903 10.9443C9.60529 11.0094 9.48119 11.0182 9.37931 10.9667L6.14144 9.32987C6.05311 9.28559 5.9469 9.28559 5.85856 9.32987L2.62069 10.9667C2.51881 11.0182 2.39472 11.0094 2.30096 10.9443C2.20722 10.8786 2.16062 10.7682 2.18012 10.6588L2.79842 7.19288C2.81522 7.09807 2.78271 7.00117 2.71118 6.93397L0.0916083 4.47978C0.0086971 4.40216 -0.0205644 4.28599 0.0146582 4.18023C0.0504232 4.07448 0.145798 3.99738 0.260135 3.98175L3.88006 3.47589C3.97923 3.46235 4.0643 3.40244 4.10874 3.31596L5.7274 0.162545C5.77888 0.0630431 5.88455 0 5.99997 0C6.11539 0 6.22113 0.0630238 6.2726 0.162533Z"
|
||||
fill="white"
|
||||
fill={setColor}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
32
src/assets/Icons/SuccessIcon.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { useTheme } from '@mui/material';
|
||||
import { SVGProps } from './interfaces';
|
||||
|
||||
export const SuccessIcon: React.FC<SVGProps> = ({
|
||||
color,
|
||||
height = 155,
|
||||
width = 156,
|
||||
opacity,
|
||||
...children
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const setColor = color ? color : theme.palette.text.primary;
|
||||
const setOpacity = opacity ? opacity : 1;
|
||||
|
||||
return (
|
||||
<svg
|
||||
{...children}
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 156 155"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M78 0C57.4456 0 37.7349 8.16507 23.1984 22.6984C8.66507 37.2332 0.5 56.9446 0.5 77.5C0.5 98.0554 8.66507 117.765 23.1984 132.302C37.7332 146.835 57.4445 155 78 155C98.5554 155 118.265 146.835 132.802 132.302C147.335 117.767 155.5 98.0554 155.5 77.5C155.48 56.9522 147.308 37.2523 132.779 22.7227C118.249 8.19318 98.5489 0.0215072 78.0014 0.00138561L78 0ZM66.5377 111.48L29.1001 77.2273L39.5907 65.765L66.0523 89.992L115.768 40.2557L126.764 51.2517L66.5377 111.48Z"
|
||||
fill={setColor}
|
||||
opacity={setOpacity}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="20" height="20" fill="url(#pattern0)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_127_477" transform="scale(0.015625)"/>
|
||||
</pattern>
|
||||
<image id="image0_127_477" width="64" height="64" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAACW0lEQVR4nO3bu2sUURSA8RsVMQRRfBArQ3yAb8RC0MZKsLBRtLHQQvEfEBEVS+2sjQHjo1TERhCLNHZWVsFGxShiFLTygSj+5OIKm2E3m12Tnbk789V7z+53zpl7z87uhFBRUZEiWIi9uIQx3MUozmMX+kIvgkU4iUkz8xxHeyoRWIlx7fEQy0LqYBivdMYzLA2Jy082EPuCERzDfpzCffxs8NoHSV4Omss/wmCTNTsw0WDNkdAj8jewoMXa5Q2SMJFMF2guP9ZKPtMJvzLrd4aE5W/OVr4uVtwT6jkXEpW/1a58LV7cGOsZCQnK34mTX4cxD2Ri3QuJyU9h4D/ixiOyntGQkHz9kbekw9jXTediSEy+4yRgDb6azu6QoHzbSYgbJh6bzstONtJ5AUMdzvZRqr9F7D5ca7D2eEi08rPuhFrl47CUZbzTk6Ro8k2TUJOPw1KW2GmrQsJt3/JyqMnHYSnLG6zvRfn6JAwUXX54jtq+GXFYyhLfb10vV34mClP5oUq+u7wtu/yGvN1DJa+qfDcpddu/x+a83UMlr6p8Nyl120+VXX5L3u6hkldVvptUbR/yRrXhyWO331qEyq/G6xyGnE2hCOBsDvL5Dzn/qP23rlt8KETbZ35X+1RK+UgcObsovy0UDZwurXwEt0srH8GLMssPllY+gsPzJP+x8PIRXJ0n+e0hBfC0zPL9+FFK+Qj2lVY+ggullZ+DL0Df8QSXsTakiL/ndDs3LuIzOGewB4tD6uBdE9nftUdN4kOJJ7Ax9CI4hM/4VmvnKziIFXl/toqKMG/8Ad4tdVYcSnGDAAAAAElFTkSuQmCC"/>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,3 +0,0 @@
|
||||
<svg width="10" height="11" viewBox="0 0 10 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.92857 0.5H8.57143C9.36071 0.5 10 1.13929 10 1.92857V6.57143C10 7.36071 9.36071 8 8.57143 8H8.21429V4.42857C8.21429 3.24643 7.25357 2.28571 6.07143 2.28571H2.5V1.92857C2.5 1.13929 3.13929 0.5 3.92857 0.5ZM1.42857 3H6.07143C6.86041 3 7.5 3.63959 7.5 4.42857V9.07143C7.5 9.86041 6.86041 10.5 6.07143 10.5H1.42857C0.639593 10.5 0 9.86041 0 9.07143V4.42857C0 3.63959 0.639593 3 1.42857 3Z" fill="white" fill-opacity="0.5"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 574 B |
@ -1,3 +0,0 @@
|
||||
<svg width="15" height="11" viewBox="0 0 15 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.76526 1.80943H6.51017C5.91236 1.80943 5.42723 2.37147 5.42723 3.06406V6.55419V6.82615H4L1.90297 9L2.00782 6.82615H0.8482C0.380282 6.82615 0 6.38558 0 5.84347V0.982675C0 0.440572 0.380282 0 0.8482 0H7.1518C7.62128 0 8 0.440572 8 0.982675V1.80943H7.76526ZM8.89437 2H14.0458C14.5722 2 15 2.44057 15 2.98268V7.84166C15 8.38558 14.5722 8.82434 14.0458 8.82434H12.7412L12.8592 11L10.5 8.82434H6.95423C6.42606 8.82434 6 8.38558 6 7.84166V7.01672V6.74476V6.47281V2.98268C6 2.44057 6.42606 2 6.95423 2H8.3662H8.63028H8.89437Z" fill="white"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 688 B |
@ -1,3 +0,0 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 0C4.06452 0 0 4.06452 0 9C0 13.9355 4.06452 18 9 18C13.9355 18 18 13.9355 18 9C18 4.06452 13.8629 0 9 0ZM9 16.8387C4.71774 16.8387 1.16129 13.2823 1.16129 9C1.16129 4.71774 4.71774 1.16129 9 1.16129C13.2823 1.16129 16.8387 4.71774 16.8387 9C16.8387 13.2823 13.2823 16.8387 9 16.8387ZM9.79861 13.2097C9.79861 13.5726 9.50829 13.9355 9.0728 13.9355H8.85506C8.49216 13.9355 8.12926 13.6451 8.12926 13.2097V7.18545C8.12926 6.82255 8.41958 6.45965 8.85506 6.45965H9.0728C9.43571 6.45965 9.79861 6.74997 9.79861 7.18545V13.2097ZM9.79823 4.86286C9.79823 5.30379 9.44078 5.66125 8.99984 5.66125C8.5589 5.66125 8.20145 5.30379 8.20145 4.86286C8.20145 4.42192 8.5589 4.06447 8.99984 4.06447C9.44078 4.06447 9.79823 4.42192 9.79823 4.86286Z" fill="white" fill-opacity="0.5"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 920 B |
@ -1,3 +0,0 @@
|
||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.14468 0L0.394043 2.66667L5.89531 8L0.394043 13.3333L3.14468 16L8.64594 10.6667L14.1472 16L16.8978 13.3333L11.3966 8L16.8978 2.66667L14.1472 0L8.64594 5.33333L3.14468 0Z" fill="white"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 300 B |
@ -1,3 +0,0 @@
|
||||
<svg width="20" height="16" viewBox="0 0 20 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.645 5.81803H15C15.9471 5.81803 16.8557 6.20131 17.5257 6.88278C18.195 7.56497 18.5714 8.49007 18.5714 9.45445V10.909C18.5714 11.8734 18.195 12.7985 17.5257 13.4807C16.8557 14.1622 15.9471 14.5454 15 14.5454C12.0164 14.5454 8.57143 14.5454 8.57143 14.5454C8.17714 14.5454 7.85714 14.8713 7.85714 15.2727C7.85714 15.6742 8.17714 16 8.57143 16H15C16.3264 16 17.5979 15.464 18.5357 14.5091C19.4736 13.5541 20 12.2596 20 10.909C20 10.4268 20 9.93664 20 9.45445C20 8.10461 19.4736 6.80932 18.5357 5.8544C17.5979 4.9002 16.3264 4.36347 15 4.36347H2.645L6.17929 1.27906C6.47857 1.01797 6.51286 0.55832 6.25643 0.253588C6 -0.0511433 5.54857 -0.0860541 5.24929 0.175041L0.249285 4.53874C0.0914279 4.67692 0 4.87838 0 5.09075C0 5.30312 0.0914279 5.50458 0.249285 5.64276L5.24929 10.0065C5.54857 10.2676 6 10.2326 6.25643 9.92791C6.51286 9.62318 6.47857 9.16353 6.17929 8.90244L2.645 5.81803Z" fill="white" fill-opacity="0.5"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1,3 +0,0 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.08728 0.00158245C2.72507 0.00158245 0 2.7262 0 6.08784C0 9.44948 2.72507 12.1741 6.08728 12.1741C7.62099 12.1741 9.02317 11.6043 10.0947 10.6668L13.3088 13.8803C13.3881 13.9596 13.4911 14 13.595 14C13.6988 14 13.8018 13.9596 13.8811 13.8803C14.0396 13.7218 14.0396 13.4643 13.8811 13.3066L10.667 10.093C11.6047 9.02162 12.1746 7.62202 12.1746 6.08626C12.1746 2.72461 9.44951 0 6.0873 0L6.08728 0.00158245ZM6.08728 11.3626C3.17756 11.3626 0.811637 8.99707 0.811637 6.08784C0.811637 3.17861 3.17756 0.813083 6.08728 0.813083C8.997 0.813083 11.3629 3.17861 11.3629 6.08784C11.3629 8.99707 8.997 11.3626 6.08728 11.3626Z" fill="white"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 748 B |
@ -1,4 +0,0 @@
|
||||
<svg width="15" height="16" viewBox="0 0 15 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.3347 0.271977C14.0797 0.0885134 13.79 0 13.5034 0C13.0191 0 12.5424 0.251056 12.2542 0.711326L12.0008 1.11366L10.6942 3.20097L9.44204 5.19976C9.15388 5.66003 9 6.19916 9 6.75116V14.3987C9 15.2822 9.67136 16 10.4996 16C10.9145 16 11.2902 15.8214 11.5602 15.5301C11.8318 15.2404 11.9992 14.8397 11.9992 14.3987V7.57353C11.9992 7.11809 12.1275 6.6723 12.3628 6.29411L14.7465 2.48964C14.917 2.21605 15 1.90706 15 1.60129C15 1.08469 14.7646 0.577751 14.3332 0.270368L14.3347 0.271977Z" fill="white"/>
|
||||
<path d="M4.30727 3.20032L3.00075 1.11344L2.74881 0.711183C2.46065 0.251006 1.98391 0 1.49962 0C1.21297 0 0.923309 0.0884956 0.668343 0.271923C0.235353 0.579244 0 1.08608 0 1.60257C0 1.90829 0.0829771 2.21722 0.254966 2.49075L2.63716 6.29445C2.87403 6.67257 3.00075 7.11826 3.00075 7.57361V14.399C3.00075 15.2824 3.67211 16 4.50038 16C5.32864 16 6 15.2824 6 14.399V6.75141C6 6.19952 5.84762 5.6605 5.55947 5.20032L4.30576 3.20193L4.30727 3.20032Z" fill="white"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1,3 +0,0 @@
|
||||
<svg width="156" height="155" viewBox="0 0 156 155" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M78 0C57.4456 0 37.7349 8.16507 23.1984 22.6984C8.66507 37.2332 0.5 56.9446 0.5 77.5C0.5 98.0554 8.66507 117.765 23.1984 132.302C37.7332 146.835 57.4445 155 78 155C98.5554 155 118.265 146.835 132.802 132.302C147.335 117.767 155.5 98.0554 155.5 77.5C155.48 56.9522 147.308 37.2523 132.779 22.7227C118.249 8.19318 98.5489 0.0215072 78.0014 0.00138561L78 0ZM66.5377 111.48L29.1001 77.2273L39.5907 65.765L66.0523 89.992L115.768 40.2557L126.764 51.2517L66.5377 111.48Z" fill="white" fill-opacity="0.5"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 615 B |
@ -1,4 +1,9 @@
|
||||
import { IconButton, InputAdornment, TextFieldProps } from '@mui/material';
|
||||
import {
|
||||
IconButton,
|
||||
InputAdornment,
|
||||
TextFieldProps,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
@ -39,7 +44,7 @@ export const BoundedNumericTextField = ({
|
||||
const stringIsEmpty = (value: string) => {
|
||||
return value === '';
|
||||
};
|
||||
|
||||
const theme = useTheme();
|
||||
const isAllZerosNum = /^0*\.?0*$/;
|
||||
const isFloatNum = /^-?[0-9]*\.?[0-9]*$/;
|
||||
const isIntegerNum = /^-?[0-9]+$/;
|
||||
@ -133,7 +138,7 @@ export const BoundedNumericTextField = ({
|
||||
>
|
||||
<AddIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>{' '}
|
||||
</IconButton>
|
||||
@ -143,7 +148,7 @@ export const BoundedNumericTextField = ({
|
||||
>
|
||||
<RemoveIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>{' '}
|
||||
</IconButton>
|
||||
|
@ -1,7 +1,19 @@
|
||||
import React from 'react'
|
||||
import './customloader.css'
|
||||
import React from 'react';
|
||||
import './customloader.css';
|
||||
import { Box, useTheme } from '@mui/material';
|
||||
export const CustomLoader = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<div className="lds-ellipsis"><div></div><div></div><div></div><div></div></div>
|
||||
)
|
||||
}
|
||||
<Box
|
||||
sx={{
|
||||
'--text-primary': theme.palette.text.primary,
|
||||
}}
|
||||
className="lds-ellipsis"
|
||||
>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -1,28 +1,29 @@
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { useInView } from 'react-intersection-observer'
|
||||
import CircularProgress from '@mui/material/CircularProgress'
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useInView } from 'react-intersection-observer';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
interface Props {
|
||||
onLoadMore: () => Promise<void>
|
||||
onLoadMore: () => Promise<void>;
|
||||
}
|
||||
|
||||
const LazyLoad: React.FC<Props> = ({ onLoadMore }) => {
|
||||
const [isFetching, setIsFetching] = useState<boolean>(false)
|
||||
|
||||
const firstLoad = useRef(false)
|
||||
const [isFetching, setIsFetching] = useState<boolean>(false);
|
||||
const theme = useTheme();
|
||||
const firstLoad = useRef(false);
|
||||
const [ref, inView] = useInView({
|
||||
threshold: 0.7
|
||||
})
|
||||
threshold: 0.7,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (inView) {
|
||||
setIsFetching(true)
|
||||
setIsFetching(true);
|
||||
onLoadMore().finally(() => {
|
||||
setIsFetching(false)
|
||||
firstLoad.current = true
|
||||
})
|
||||
setIsFetching(false);
|
||||
firstLoad.current = true;
|
||||
});
|
||||
}
|
||||
}, [inView])
|
||||
}, [inView]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -30,18 +31,22 @@ const LazyLoad: React.FC<Props> = ({ onLoadMore }) => {
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
minHeight: '25px'
|
||||
minHeight: '25px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
visibility: isFetching ? 'visible' : 'hidden'
|
||||
visibility: isFetching ? 'visible' : 'hidden',
|
||||
}}
|
||||
>
|
||||
<CircularProgress />
|
||||
<CircularProgress
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default LazyLoad
|
||||
export default LazyLoad;
|
||||
|
@ -1,5 +1,5 @@
|
||||
.lds-ellipsis {
|
||||
color: white;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.lds-ellipsis,
|
||||
.lds-ellipsis div {
|
||||
|
@ -186,7 +186,7 @@ export const AppInfo = ({ app, myName }) => {
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: isInstalled
|
||||
? '#0091E1'
|
||||
? theme.palette.primary.main
|
||||
: theme.palette.background.paper,
|
||||
height: '29px',
|
||||
maxWidth: '320px',
|
||||
|
@ -183,7 +183,7 @@ export const AppInfoSnippet = ({
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: isInstalled
|
||||
? '#0091E1'
|
||||
? theme.palette.primary.main
|
||||
: theme.palette.background.paper,
|
||||
}}
|
||||
>
|
||||
|
@ -20,7 +20,13 @@ import {
|
||||
PublishQAppChoseFile,
|
||||
PublishQAppInfo,
|
||||
} from './Apps-styles';
|
||||
import { InputBase, InputLabel, MenuItem, Select } from '@mui/material';
|
||||
import {
|
||||
InputBase,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { styled } from '@mui/system';
|
||||
import UnfoldMoreRoundedIcon from '@mui/icons-material/UnfoldMoreRounded';
|
||||
import { Add } from '@mui/icons-material';
|
||||
@ -59,11 +65,11 @@ const CustomSelect = styled(Select)({
|
||||
});
|
||||
|
||||
const CustomMenuItem = styled(MenuItem)({
|
||||
backgroundColor: '#1f1f1f', // Background for dropdown items
|
||||
color: '#ccc',
|
||||
'&:hover': {
|
||||
backgroundColor: '#333', // Darker background on hover
|
||||
},
|
||||
// backgroundColor: '#1f1f1f', // Background for dropdown items
|
||||
// color: '#ccc',
|
||||
// '&:hover': {
|
||||
// backgroundColor: '#333', // Darker background on hover
|
||||
// },
|
||||
});
|
||||
|
||||
export const AppPublish = ({ names, categories }) => {
|
||||
@ -74,7 +80,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
const [appType, setAppType] = useState('APP');
|
||||
const [file, setFile] = useState(null);
|
||||
const { show } = useContext(MyContext);
|
||||
|
||||
const theme = useTheme();
|
||||
const [tag1, setTag1] = useState('');
|
||||
const [tag2, setTag2] = useState('');
|
||||
const [tag3, setTag3] = useState('');
|
||||
@ -263,9 +269,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
|
||||
<Spacer height="18px" />
|
||||
|
||||
<InputLabel
|
||||
sx={{ color: '#888', fontSize: '14px', marginBottom: '2px' }}
|
||||
>
|
||||
<InputLabel sx={{ fontSize: '14px', marginBottom: '2px' }}>
|
||||
Name/App
|
||||
</InputLabel>
|
||||
|
||||
@ -278,11 +282,11 @@ export const AppPublish = ({ names, categories }) => {
|
||||
<CustomMenuItem value="">
|
||||
<em
|
||||
style={{
|
||||
color: 'var(--50-white, #FFFFFF80)',
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
>
|
||||
Select Name/App
|
||||
</em>{' '}
|
||||
</em>
|
||||
{/* This is the placeholder item */}
|
||||
</CustomMenuItem>
|
||||
{names.map((name) => {
|
||||
@ -292,9 +296,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
|
||||
<Spacer height="15px" />
|
||||
|
||||
<InputLabel
|
||||
sx={{ color: '#888', fontSize: '14px', marginBottom: '2px' }}
|
||||
>
|
||||
<InputLabel sx={{ fontSize: '14px', marginBottom: '2px' }}>
|
||||
App service type
|
||||
</InputLabel>
|
||||
|
||||
@ -307,12 +309,11 @@ export const AppPublish = ({ names, categories }) => {
|
||||
<CustomMenuItem value="">
|
||||
<em
|
||||
style={{
|
||||
color: 'var(--50-white, #FFFFFF80)',
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
>
|
||||
Select App Type
|
||||
</em>{' '}
|
||||
{/* This is the placeholder item */}
|
||||
</em>
|
||||
</CustomMenuItem>
|
||||
<CustomMenuItem value={'APP'}>App</CustomMenuItem>
|
||||
<CustomMenuItem value={'WEBSITE'}>Website</CustomMenuItem>
|
||||
@ -320,9 +321,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
|
||||
<Spacer height="15px" />
|
||||
|
||||
<InputLabel
|
||||
sx={{ color: '#888', fontSize: '14px', marginBottom: '2px' }}
|
||||
>
|
||||
<InputLabel sx={{ fontSize: '14px', marginBottom: '2px' }}>
|
||||
Title
|
||||
</InputLabel>
|
||||
|
||||
@ -330,7 +329,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
@ -347,9 +346,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
|
||||
<Spacer height="15px" />
|
||||
|
||||
<InputLabel
|
||||
sx={{ color: '#888', fontSize: '14px', marginBottom: '2px' }}
|
||||
>
|
||||
<InputLabel sx={{ fontSize: '14px', marginBottom: '2px' }}>
|
||||
Description
|
||||
</InputLabel>
|
||||
|
||||
@ -357,7 +354,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
@ -374,9 +371,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
|
||||
<Spacer height="15px" />
|
||||
|
||||
<InputLabel
|
||||
sx={{ color: '#888', fontSize: '14px', marginBottom: '2px' }}
|
||||
>
|
||||
<InputLabel sx={{ fontSize: '14px', marginBottom: '2px' }}>
|
||||
Category
|
||||
</InputLabel>
|
||||
|
||||
@ -389,12 +384,11 @@ export const AppPublish = ({ names, categories }) => {
|
||||
<CustomMenuItem value="">
|
||||
<em
|
||||
style={{
|
||||
color: 'var(--50-white, #FFFFFF80)',
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
>
|
||||
Select Category
|
||||
</em>{' '}
|
||||
{/* This is the placeholder item */}
|
||||
</em>
|
||||
</CustomMenuItem>
|
||||
{categories?.map((category) => {
|
||||
return (
|
||||
@ -407,9 +401,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
|
||||
<Spacer height="15px" />
|
||||
|
||||
<InputLabel
|
||||
sx={{ color: '#888', fontSize: '14px', marginBottom: '2px' }}
|
||||
>
|
||||
<InputLabel sx={{ fontSize: '14px', marginBottom: '2px' }}>
|
||||
Tags
|
||||
</InputLabel>
|
||||
|
||||
@ -418,7 +410,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={tag1}
|
||||
onChange={(e) => setTag1(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
@ -435,7 +427,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={tag2}
|
||||
onChange={(e) => setTag2(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
@ -452,7 +444,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={tag3}
|
||||
onChange={(e) => setTag3(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
@ -469,7 +461,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={tag4}
|
||||
onChange={(e) => setTag4(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
@ -486,7 +478,7 @@ export const AppPublish = ({ names, categories }) => {
|
||||
value={tag5}
|
||||
onChange={(e) => setTag5(e.target.value)}
|
||||
sx={{
|
||||
border: '0.5px solid var(--50-white, #FFFFFF80)',
|
||||
border: `0.5px solid ${theme.palette.action.disabled}`,
|
||||
padding: '0px 15px',
|
||||
borderRadius: '5px',
|
||||
height: '36px',
|
||||
|
@ -27,7 +27,7 @@ const AppViewerContainer = React.forwardRef(
|
||||
}
|
||||
.frame-content {
|
||||
overflow: hidden;
|
||||
height: '100vh';
|
||||
height: 100vh;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
@ -35,7 +35,7 @@ const AppViewerContainer = React.forwardRef(
|
||||
}
|
||||
style={{
|
||||
border: 'none',
|
||||
height: '100vh',
|
||||
height: customHeight || '100vh',
|
||||
left: (!isSelected || hide) && '-200vw',
|
||||
overflow: 'hidden',
|
||||
position: (!isSelected || hide) && 'fixed',
|
||||
|
@ -75,7 +75,7 @@ export const AppsWidthLimiter = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const AppsSearchContainer = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: '8px',
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
@ -87,7 +87,7 @@ export const AppsSearchContainer = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const AppsSearchLeft = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
@ -99,7 +99,7 @@ export const AppsSearchLeft = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const AppsSearchRight = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
flexShrink: 1,
|
||||
@ -141,7 +141,7 @@ export const AppLibrarySubTitle = styled(Typography)(({ theme }) => ({
|
||||
|
||||
export const AppCircle = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
borderColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? 'rgb(209, 209, 209)'
|
||||
@ -283,7 +283,7 @@ export const TabParent = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const PublishQAppCTAParent = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
@ -292,7 +292,7 @@ export const PublishQAppCTAParent = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const PublishQAppCTALeft = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-start',
|
||||
@ -300,7 +300,7 @@ export const PublishQAppCTALeft = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const PublishQAppCTARight = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
@ -308,8 +308,8 @@ export const PublishQAppCTARight = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const PublishQAppCTAButton = styled(ButtonBase)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
borderColor: theme.palette.text.primary,
|
||||
borderRadius: '25px',
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '1px',
|
||||
@ -322,10 +322,10 @@ export const PublishQAppCTAButton = styled(ButtonBase)(({ theme }) => ({
|
||||
|
||||
export const PublishQAppDotsBG = styled(Box)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
height: '60px',
|
||||
height: '80px',
|
||||
justifyContent: 'center',
|
||||
width: '60px',
|
||||
}));
|
||||
@ -333,7 +333,7 @@ export const PublishQAppDotsBG = styled(Box)(({ theme }) => ({
|
||||
export const PublishQAppInfo = styled(Typography)(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.default,
|
||||
color: theme.palette.text.primary,
|
||||
fontSize: '10px',
|
||||
fontSize: '16px',
|
||||
fontStyle: 'italic',
|
||||
fontWeight: 400,
|
||||
lineHeight: 1.2,
|
||||
@ -341,15 +341,18 @@ export const PublishQAppInfo = styled(Typography)(({ theme }) => ({
|
||||
|
||||
export const PublishQAppChoseFile = styled(ButtonBase)(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderRadius: '5px',
|
||||
color: theme.palette.text.primary,
|
||||
display: 'flex',
|
||||
fontSize: '10px',
|
||||
fontSize: '16px',
|
||||
fontWeight: 600,
|
||||
height: '30px',
|
||||
height: '40px',
|
||||
justifyContent: 'center',
|
||||
width: '101px',
|
||||
width: '120px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'action.hover', // background on hover
|
||||
},
|
||||
}));
|
||||
|
||||
export const AppsCategoryInfo = styled(Box)(({ theme }) => ({
|
||||
|
@ -24,6 +24,7 @@ import { useRecoilState } from 'recoil';
|
||||
import { enabledDevModeAtom } from '../../atoms/global';
|
||||
import { AppsIcon } from '../../assets/Icons/AppsIcon';
|
||||
import { CoreSyncStatus } from '../CoreSyncStatus';
|
||||
import { MessagingIconFilled } from '../../assets/Icons/MessagingIconFilled';
|
||||
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
@ -342,6 +343,8 @@ export const AppsDesktop = ({
|
||||
gap: '25px',
|
||||
height: '100vh',
|
||||
width: '60px',
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
borderRight: `1px solid ${theme.palette.border.subtle}`,
|
||||
}}
|
||||
>
|
||||
<ButtonBase
|
||||
@ -384,7 +387,7 @@ export const AppsDesktop = ({
|
||||
<IconWrapper
|
||||
color={
|
||||
hasUnreadDirects || hasUnreadGroups
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopViewMode === 'chat'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -392,11 +395,11 @@ export const AppsDesktop = ({
|
||||
label="Chat"
|
||||
disableWidth
|
||||
>
|
||||
<MessagingIcon
|
||||
<MessagingIconFilled
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadDirects || hasUnreadGroups
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopViewMode === 'chat'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
|
@ -1,15 +1,6 @@
|
||||
import React, {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { AppsDevModeHome } from './AppsDevModeHome';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { AppInfo } from './AppInfo';
|
||||
|
||||
import {
|
||||
executeEvent,
|
||||
@ -19,19 +10,15 @@ import {
|
||||
import { AppsParent } from './Apps-styles';
|
||||
import AppViewerContainer from './AppViewerContainer';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import { AppPublish } from './AppPublish';
|
||||
import { AppsLibraryDesktop } from './AppsLibraryDesktop';
|
||||
import { AppsCategoryDesktop } from './AppsCategoryDesktop';
|
||||
import { AppsNavBarDesktop } from './AppsNavBarDesktop';
|
||||
|
||||
import { Box, ButtonBase, useTheme } from '@mui/material';
|
||||
import { HomeIcon } from '../../assets/Icons/HomeIcon';
|
||||
import { MessagingIcon } from '../../assets/Icons/MessagingIcon';
|
||||
import { Save } from '../Save/Save';
|
||||
import { HubsIcon } from '../../assets/Icons/HubsIcon';
|
||||
import { AppsDevModeNavBar } from './AppsDevModeNavBar';
|
||||
import { AppsIcon } from '../../assets/Icons/AppsIcon';
|
||||
import { IconWrapper } from '../Desktop/DesktopFooter';
|
||||
import { CoreSyncStatus } from '../CoreSyncStatus';
|
||||
import { MessagingIconFilled } from '../../assets/Icons/MessagingIconFilled';
|
||||
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
@ -303,7 +290,7 @@ export const AppsDevMode = ({
|
||||
<IconWrapper
|
||||
color={
|
||||
hasUnreadDirects || hasUnreadGroups
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopViewMode === 'chat'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -311,11 +298,11 @@ export const AppsDevMode = ({
|
||||
label="Chat"
|
||||
disableWidth
|
||||
>
|
||||
<MessagingIcon
|
||||
<MessagingIconFilled
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadDirects || hasUnreadGroups
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopViewMode === 'chat'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
} from './Apps-styles';
|
||||
import { NavBack } from '../../assets/Icons/NavBack.tsx';
|
||||
import { NavAdd } from '../../assets/Icons/NavAdd.tsx';
|
||||
import { ButtonBase, Tab, Tabs } from '@mui/material';
|
||||
import { ButtonBase, Tab, Tabs, useTheme } from '@mui/material';
|
||||
import {
|
||||
executeEvent,
|
||||
subscribeToEvent,
|
||||
@ -23,7 +23,7 @@ export const AppsDevModeNavBar = () => {
|
||||
const [navigationController, setNavigationController] = useRecoilState(
|
||||
navigationControllerAtom
|
||||
);
|
||||
|
||||
const theme = useTheme();
|
||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
|
||||
const tabsRef = useRef(null);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
@ -81,7 +81,7 @@ export const AppsDevModeNavBar = () => {
|
||||
sx={{
|
||||
position: 'relative',
|
||||
flexDirection: 'column',
|
||||
width: '60px',
|
||||
width: '59px',
|
||||
height: 'unset',
|
||||
maxHeight: '70vh',
|
||||
borderRadius: '0px 30px 30px 0px',
|
||||
@ -114,9 +114,9 @@ export const AppsDevModeNavBar = () => {
|
||||
scrollButtons={true}
|
||||
sx={{
|
||||
'& .MuiTabs-indicator': {
|
||||
backgroundColor: 'white',
|
||||
backgroundColor: theme.palette.text.primary,
|
||||
},
|
||||
maxHeight: `320px`, // Ensure the tabs container fits within the available space
|
||||
maxHeight: `275px`, // Ensure the tabs container fits within the available space
|
||||
overflow: 'hidden', // Prevents overflow on small screens
|
||||
}}
|
||||
>
|
||||
@ -133,7 +133,7 @@ export const AppsDevModeNavBar = () => {
|
||||
} // Pass custom component
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
padding: '0px',
|
||||
margin: '0px',
|
||||
|
@ -69,10 +69,7 @@ export const AppsHomeDesktop = ({
|
||||
display: 'flex',
|
||||
gap: '20px',
|
||||
alignItems: 'center',
|
||||
backgroundColor:
|
||||
theme.palette.mode === 'dark'
|
||||
? 'rgba(41, 41, 43, 1)'
|
||||
: 'rgb(209, 209, 209)',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
padding: '7px',
|
||||
borderRadius: '20px',
|
||||
width: '100%',
|
||||
@ -91,9 +88,9 @@ export const AppsHomeDesktop = ({
|
||||
placeholder="qortal://"
|
||||
sx={{
|
||||
width: '100%',
|
||||
color: theme.palette.mode === 'dark' ? 'white' : 'black',
|
||||
color: theme.palette.text.primary,
|
||||
'& .MuiInput-input::placeholder': {
|
||||
color: 'rgba(84, 84, 84, 0.70) !important',
|
||||
color: theme.palette.text.secondary,
|
||||
fontSize: '20px',
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 400,
|
||||
@ -115,7 +112,9 @@ export const AppsHomeDesktop = ({
|
||||
<ButtonBase onClick={() => openQortalUrl()}>
|
||||
<ArrowOutwardIcon
|
||||
sx={{
|
||||
color: qortalUrl ? 'white' : 'rgba(84, 84, 84, 0.70)',
|
||||
color: qortalUrl
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
@ -39,7 +39,8 @@ import { Spacer } from '../../common/Spacer';
|
||||
import { AppInfoSnippet } from './AppInfoSnippet';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { ShowMessageReturnButton } from '../Group/Forum/Mail-styles';
|
||||
import { ComposeP, ShowMessageReturnButton } from '../Group/Forum/Mail-styles';
|
||||
import { ReturnIcon } from '../../assets/Icons/ReturnIcon.tsx';
|
||||
|
||||
const officialAppList = [
|
||||
'q-tube',
|
||||
@ -273,7 +274,10 @@ export const AppsLibraryDesktop = ({
|
||||
onClick={() => {
|
||||
executeEvent('navigateBack', {});
|
||||
}}
|
||||
></ShowMessageReturnButton>
|
||||
>
|
||||
<ReturnIcon />
|
||||
<ComposeP>Return to Apps Dashboard</ComposeP>
|
||||
</ShowMessageReturnButton>
|
||||
|
||||
<Spacer height="20px" />
|
||||
|
||||
@ -467,11 +471,13 @@ export const AppsLibraryDesktop = ({
|
||||
borderRadius: '6px',
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '4px',
|
||||
boxShadow: '2px 4px 0px 0px #000000',
|
||||
display: 'flex',
|
||||
height: '50px',
|
||||
justifyContent: 'center',
|
||||
padding: '0px 20px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'action.hover', // background on hover
|
||||
},
|
||||
}}
|
||||
>
|
||||
All
|
||||
@ -495,11 +501,13 @@ export const AppsLibraryDesktop = ({
|
||||
borderRadius: '6px',
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '4px',
|
||||
boxShadow: '2px 4px 0px 0px #000000',
|
||||
display: 'flex',
|
||||
height: '50px',
|
||||
justifyContent: 'center',
|
||||
padding: '0px 20px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'action.hover', // background on hover
|
||||
},
|
||||
}}
|
||||
>
|
||||
{category?.name}
|
||||
|
@ -160,7 +160,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
maxHeight: '70vh',
|
||||
padding: '10px',
|
||||
position: 'relative',
|
||||
width: '60px',
|
||||
width: '59px',
|
||||
}}
|
||||
>
|
||||
<AppsNavBarLeft
|
||||
@ -190,7 +190,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
'& .MuiTabs-indicator': {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
maxHeight: `320px`, // Ensure the tabs container fits within the available space
|
||||
maxHeight: `275px`, // Ensure the tabs container fits within the available space
|
||||
overflow: 'hidden', // Prevents overflow on small screens
|
||||
}}
|
||||
>
|
||||
@ -361,7 +361,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
height={20}
|
||||
sx={{
|
||||
color: isSelectedAppPinned
|
||||
? 'var(--danger)'
|
||||
? theme.palette.other.danger
|
||||
: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
@ -372,7 +372,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
color: isSelectedAppPinned
|
||||
? 'var(--danger)'
|
||||
? theme.palette.other.danger
|
||||
: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
|
@ -261,6 +261,12 @@ export const AppsPrivate = ({ myName }) => {
|
||||
}}
|
||||
maxWidth="md"
|
||||
fullWidth={true}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
boxShadow: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Tabs
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { Box, Checkbox, FormControlLabel, Typography } from '@mui/material';
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
FormControlLabel,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { Return } from '../../assets/Icons/Return';
|
||||
import { CustomButton, CustomLabel, TextP } from '../../styles/App-styles';
|
||||
@ -24,7 +30,7 @@ export const DownloadWallet = ({
|
||||
useState<string>('');
|
||||
const [newPassword, setNewPassword] = useState<string>('');
|
||||
const [keepCurrentPassword, setKeepCurrentPassword] = useState<boolean>(true);
|
||||
|
||||
const theme = useTheme();
|
||||
const [walletToBeDownloadedError, setWalletToBeDownloadedError] =
|
||||
useState<string>('');
|
||||
|
||||
@ -184,6 +190,14 @@ export const DownloadWallet = ({
|
||||
edge="start"
|
||||
tabIndex={-1}
|
||||
disableRipple
|
||||
sx={{
|
||||
'&.Mui-checked': {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
'& .MuiSvgIcon-root': {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={
|
||||
|
@ -110,7 +110,6 @@ export const BuyQortInformation = ({ balance }) => {
|
||||
</Typography>
|
||||
<List
|
||||
sx={{
|
||||
bgcolor: theme.palette.background.default,
|
||||
maxWidth: 360,
|
||||
width: '100%',
|
||||
}}
|
||||
@ -118,21 +117,13 @@ export const BuyQortInformation = ({ balance }) => {
|
||||
>
|
||||
<ListItem disablePadding>
|
||||
<ListItemIcon>
|
||||
<RadioButtonCheckedIcon
|
||||
sx={{
|
||||
color: theme.palette.primary.dark,
|
||||
}}
|
||||
/>
|
||||
<RadioButtonCheckedIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Create transactions on the Qortal Blockchain" />
|
||||
</ListItem>
|
||||
<ListItem disablePadding>
|
||||
<ListItemIcon>
|
||||
<RadioButtonCheckedIcon
|
||||
sx={{
|
||||
color: theme.palette.primary.dark,
|
||||
}}
|
||||
/>
|
||||
<RadioButtonCheckedIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Having at least 4 QORT in your balance allows you to send chat messages at near instant speed." />
|
||||
</ListItem>
|
||||
|
@ -101,7 +101,6 @@ export const AnnouncementItem = ({
|
||||
sx={{
|
||||
fontWight: 600,
|
||||
fontFamily: 'Inter',
|
||||
color: 'cadetBlue',
|
||||
}}
|
||||
>
|
||||
{message?.name}
|
||||
|
@ -690,7 +690,8 @@ export const ChatDirect = ({
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
color: messageSize > 4000 ? 'var(--danger)' : 'unset',
|
||||
color:
|
||||
messageSize > 4000 ? theme.palette.other.danger : 'unset',
|
||||
}}
|
||||
>{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}</Typography>
|
||||
</Box>
|
||||
|
@ -997,6 +997,7 @@ export const ChatGroup = ({
|
||||
opacity: hide ? 0 : 1,
|
||||
position: hide ? 'absolute' : 'relative',
|
||||
width: '100%',
|
||||
padding: '10px',
|
||||
}}
|
||||
>
|
||||
<ChatList
|
||||
@ -1021,7 +1022,7 @@ export const ChatGroup = ({
|
||||
{(!!secretKey || isPrivate === false) && (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
bottom: isFocusedParent ? '0px' : 'unset',
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
@ -1034,6 +1035,8 @@ export const ChatGroup = ({
|
||||
top: isFocusedParent ? '0px' : 'unset',
|
||||
width: '100%',
|
||||
zIndex: isFocusedParent ? 5 : 'unset',
|
||||
border: `1px solid ${theme.palette.border.subtle}`,
|
||||
borderRadius: '10px',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
@ -1115,7 +1118,8 @@ export const ChatGroup = ({
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
color: messageSize > 4000 ? 'var(--danger)' : 'unset',
|
||||
color:
|
||||
messageSize > 4000 ? theme.palette.other.danger : 'unset',
|
||||
}}
|
||||
>{`Your message size is of ${messageSize} bytes out of a maximum of 4000`}</Typography>
|
||||
</Box>
|
||||
@ -1214,7 +1218,7 @@ export const ChatGroup = ({
|
||||
>
|
||||
<CloseIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
@ -2,7 +2,7 @@ import { useCallback, useState, useEffect, useRef, useMemo } from 'react';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { MessageItem } from './MessageItem';
|
||||
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
|
||||
import { Box, Typography, useTheme } from '@mui/material';
|
||||
import { Box, Button, Typography, useTheme } from '@mui/material';
|
||||
import { ChatOptions } from './ChatOptions';
|
||||
import ErrorBoundary from '../../common/ErrorBoundary';
|
||||
|
||||
@ -390,7 +390,7 @@ export const ChatList = ({
|
||||
<button
|
||||
onClick={() => scrollToBottom()}
|
||||
style={{
|
||||
backgroundColor: 'var(--unread)',
|
||||
backgroundColor: theme.palette.other.unread,
|
||||
border: 'none',
|
||||
borderRadius: '20px',
|
||||
bottom: 20,
|
||||
@ -407,10 +407,11 @@ export const ChatList = ({
|
||||
</button>
|
||||
)}
|
||||
{showScrollDownButton && !showScrollButton && (
|
||||
<button
|
||||
<Button
|
||||
onClick={() => scrollToBottom()}
|
||||
variant="contained"
|
||||
style={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
border: 'none',
|
||||
borderRadius: '20px',
|
||||
bottom: 20,
|
||||
@ -422,10 +423,11 @@ export const ChatList = ({
|
||||
position: 'absolute',
|
||||
right: 20,
|
||||
zIndex: 10,
|
||||
textTransform: 'none',
|
||||
}}
|
||||
>
|
||||
Scroll to bottom
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{enableMentions && (hasSecretKey || isPrivate === false) && (
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
AppsSearchLeft,
|
||||
AppsSearchRight,
|
||||
} from '../Apps/Apps-styles';
|
||||
import IconSearch from '../../assets/svgs/Search.svg';
|
||||
|
||||
import IconClearInput from '../../assets/svgs/ClearInput.svg';
|
||||
import { CellMeasurerCache } from 'react-virtualized';
|
||||
import { getBaseApiReact } from '../../App';
|
||||
@ -358,14 +358,14 @@ export const ChatOptions = ({
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
borderBottomLeftRadius: '20px',
|
||||
borderTopLeftRadius: '20px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexGrow: 0,
|
||||
flexShrink: 0,
|
||||
height: '100%',
|
||||
height: '98%',
|
||||
overflow: 'auto',
|
||||
width: '300px',
|
||||
}}
|
||||
@ -398,7 +398,11 @@ export const ChatOptions = ({
|
||||
>
|
||||
<AppsSearchContainer>
|
||||
<AppsSearchLeft>
|
||||
<img src={IconSearch} />
|
||||
<SearchIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<InputBase
|
||||
value={searchValue}
|
||||
onChange={(e) => setSearchValue(e.target.value)}
|
||||
@ -576,7 +580,7 @@ export const ChatOptions = ({
|
||||
<Box
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderBottomLeftRadius: '20px',
|
||||
borderTopLeftRadius: '20px',
|
||||
display: 'flex',
|
||||
@ -710,8 +714,8 @@ export const ChatOptions = ({
|
||||
mentionList?.length > 0 &&
|
||||
(!lastMentionTimestamp ||
|
||||
lastMentionTimestamp < mentionList[0]?.timestamp)
|
||||
? 'var(--unread)'
|
||||
: 'white',
|
||||
? theme.palette.other.unread
|
||||
: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -767,7 +771,6 @@ const ShowMessage = ({ message, goToMessage, messages }) => {
|
||||
sx={{
|
||||
fontWight: 600,
|
||||
fontFamily: 'Inter',
|
||||
color: 'cadetBlue',
|
||||
}}
|
||||
>
|
||||
{message?.senderName}
|
||||
|
@ -674,7 +674,7 @@ export const GroupAnnouncements = ({
|
||||
}}
|
||||
style={{
|
||||
alignSelf: 'center',
|
||||
background: 'var(--danger)',
|
||||
background: theme.palette.other.danger,
|
||||
cursor: isSending ? 'default' : 'pointer',
|
||||
flexShrink: 0,
|
||||
fontSize: '14px',
|
||||
|
@ -248,7 +248,6 @@ export const MessageItem = React.memo(
|
||||
sx={{
|
||||
fontWight: 600,
|
||||
fontFamily: 'Inter',
|
||||
color: 'cadetBlue',
|
||||
}}
|
||||
>
|
||||
{message?.senderName || message?.sender}
|
||||
@ -304,7 +303,7 @@ export const MessageItem = React.memo(
|
||||
<Spacer height="20px" />
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
borderRadius: '5px',
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
@ -319,9 +318,10 @@ export const MessageItem = React.memo(
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
background: theme.palette.background.default,
|
||||
background: theme.palette.text.primary,
|
||||
height: '100%',
|
||||
width: '5px',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
@ -384,7 +384,7 @@ export const MessageItem = React.memo(
|
||||
<ButtonBase
|
||||
key={reaction}
|
||||
sx={{
|
||||
background: theme.palette.background.paper,
|
||||
background: theme.palette.background.surface,
|
||||
borderRadius: '7px',
|
||||
height: '30px',
|
||||
minWidth: '45px',
|
||||
@ -571,7 +571,7 @@ export const ReplyPreview = ({ message, isEdit = false }) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
borderRadius: '5px',
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
@ -584,9 +584,10 @@ export const ReplyPreview = ({ message, isEdit = false }) => {
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
background: theme.palette.background.default,
|
||||
background: theme.palette.text.primary,
|
||||
height: '100%',
|
||||
width: '5px',
|
||||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
|
@ -365,6 +365,7 @@ export default ({
|
||||
membersWithNames,
|
||||
enableMentions,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const [isDisabledEditorEnter, setIsDisabledEditorEnter] = useRecoilState(
|
||||
isDisabledEditorEnterAtom
|
||||
);
|
||||
@ -483,12 +484,16 @@ export default ({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
justifyContent: 'space-between',
|
||||
'--text-primary': theme.palette.text.primary,
|
||||
'--text-secondary': theme.palette.text.secondary,
|
||||
'--background-default': theme.palette.background.default,
|
||||
'--background-secondary': theme.palette.background.paper,
|
||||
}}
|
||||
>
|
||||
<EditorProvider
|
||||
@ -537,6 +542,6 @@ export default ({
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -1,35 +1,46 @@
|
||||
import React, { useState, useRef, useMemo, useEffect } from 'react';
|
||||
import { ListItemIcon, Menu, MenuItem, Typography, styled } from '@mui/material';
|
||||
import {
|
||||
ListItemIcon,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Typography,
|
||||
styled,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import MailOutlineIcon from '@mui/icons-material/MailOutline';
|
||||
import NotificationsOffIcon from '@mui/icons-material/NotificationsOff';
|
||||
import { executeEvent } from '../utils/events';
|
||||
|
||||
const CustomStyledMenu = styled(Menu)(({ theme }) => ({
|
||||
'& .MuiPaper-root': {
|
||||
backgroundColor: '#f9f9f9',
|
||||
borderRadius: '12px',
|
||||
padding: theme.spacing(1),
|
||||
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.2)',
|
||||
'& .MuiPaper-root': {
|
||||
// backgroundColor: '#f9f9f9',
|
||||
borderRadius: '12px',
|
||||
padding: theme.spacing(1),
|
||||
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.2)',
|
||||
},
|
||||
'& .MuiMenuItem-root': {
|
||||
fontSize: '14px', // Smaller font size for the menu item text
|
||||
// color: '#444',
|
||||
transition: '0.3s background-color',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action.hover, // Explicit hover state
|
||||
},
|
||||
'& .MuiMenuItem-root': {
|
||||
fontSize: '14px', // Smaller font size for the menu item text
|
||||
color: '#444',
|
||||
transition: '0.3s background-color',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f0f0', // Explicit hover state
|
||||
},
|
||||
|
||||
},
|
||||
}));
|
||||
},
|
||||
}));
|
||||
|
||||
export const ContextMenu = ({ children, groupId, getUserSettings, mutedGroups }) => {
|
||||
export const ContextMenu = ({
|
||||
children,
|
||||
groupId,
|
||||
getUserSettings,
|
||||
mutedGroups,
|
||||
}) => {
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const longPressTimeout = useRef(null);
|
||||
const preventClick = useRef(false); // Flag to prevent click after long-press or right-click
|
||||
|
||||
const isMuted = useMemo(()=> {
|
||||
return mutedGroups.includes(groupId)
|
||||
}, [mutedGroups, groupId])
|
||||
const theme = useTheme();
|
||||
const isMuted = useMemo(() => {
|
||||
return mutedGroups.includes(groupId);
|
||||
}, [mutedGroups, groupId]);
|
||||
|
||||
// Handle right-click (context menu) for desktop
|
||||
const handleContextMenu = (event) => {
|
||||
@ -67,56 +78,52 @@ export const ContextMenu = ({ children, groupId, getUserSettings, mutedGroups })
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleSetGroupMute = ()=> {
|
||||
const handleSetGroupMute = () => {
|
||||
try {
|
||||
let value = [...mutedGroups]
|
||||
if(isMuted){
|
||||
value = value.filter((group)=> group !== groupId)
|
||||
} else {
|
||||
value.push(groupId)
|
||||
}
|
||||
window.sendMessage("addUserSettings", {
|
||||
let value = [...mutedGroups];
|
||||
if (isMuted) {
|
||||
value = value.filter((group) => group !== groupId);
|
||||
} else {
|
||||
value.push(groupId);
|
||||
}
|
||||
window
|
||||
.sendMessage('addUserSettings', {
|
||||
keyValue: {
|
||||
key: 'mutedGroups',
|
||||
value,
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
if (response?.error) {
|
||||
console.error("Error adding user settings:", response.error);
|
||||
} else {
|
||||
console.log("User settings added successfully");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to add user settings:", error.message || "An error occurred");
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
getUserSettings()
|
||||
}, 400);
|
||||
.then((response) => {
|
||||
if (response?.error) {
|
||||
console.error('Error adding user settings:', response.error);
|
||||
} else {
|
||||
console.log('User settings added successfully');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
'Failed to add user settings:',
|
||||
error.message || 'An error occurred'
|
||||
);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
getUserSettings();
|
||||
}, 400);
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const handleClose = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopPropagation();
|
||||
setMenuPosition(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onContextMenu={handleContextMenu} // For desktop right-click
|
||||
onTouchStart={handleTouchStart} // For mobile long-press start
|
||||
onTouchEnd={handleTouchEnd} // For mobile long-press end
|
||||
|
||||
onContextMenu={handleContextMenu} // For desktop right-click
|
||||
onTouchStart={handleTouchStart} // For mobile long-press start
|
||||
onTouchEnd={handleTouchEnd} // For mobile long-press end
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
>
|
||||
{children}
|
||||
@ -131,35 +138,48 @@ export const ContextMenu = ({ children, groupId, getUserSettings, mutedGroups })
|
||||
? { top: menuPosition.mouseY, left: menuPosition.mouseX }
|
||||
: undefined
|
||||
}
|
||||
onClick={(e)=> {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MenuItem onClick={(e) => {
|
||||
handleClose(e)
|
||||
executeEvent("markAsRead", {
|
||||
groupId
|
||||
});
|
||||
}}>
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
handleClose(e);
|
||||
executeEvent('markAsRead', {
|
||||
groupId,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: '32px' }}>
|
||||
<MailOutlineIcon fontSize="small" />
|
||||
<MailOutlineIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
fontSize="small"
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<Typography variant="inherit" sx={{ fontSize: '14px' }}>
|
||||
Mark As Read
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={(e) => {
|
||||
|
||||
handleClose(e)
|
||||
handleSetGroupMute()
|
||||
|
||||
}}>
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
handleClose(e);
|
||||
handleSetGroupMute();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: '32px' }}>
|
||||
<NotificationsOffIcon fontSize="small" sx={{
|
||||
color: isMuted && 'red'
|
||||
}} />
|
||||
<NotificationsOffIcon
|
||||
fontSize="small"
|
||||
sx={{
|
||||
color: isMuted ? 'red' : theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<Typography variant="inherit" sx={{ fontSize: '14px', color: isMuted && 'red' }}>
|
||||
<Typography
|
||||
variant="inherit"
|
||||
sx={{ fontSize: '14px', color: isMuted && 'red' }}
|
||||
>
|
||||
{isMuted ? 'Unmute ' : 'Mute '}Push Notifications
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
@ -167,5 +187,3 @@ export const ContextMenu = ({ children, groupId, getUserSettings, mutedGroups })
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
MenuItem,
|
||||
Typography,
|
||||
styled,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import PushPinIcon from '@mui/icons-material/PushPin';
|
||||
import { saveToLocalStorage } from './Apps/AppsNavBarDesktop';
|
||||
@ -13,7 +14,6 @@ import { sortablePinnedAppsAtom } from '../atoms/global';
|
||||
|
||||
const CustomStyledMenu = styled(Menu)(({ theme }) => ({
|
||||
'& .MuiPaper-root': {
|
||||
backgroundColor: '#f9f9f9',
|
||||
borderRadius: '12px',
|
||||
padding: theme.spacing(1),
|
||||
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.2)',
|
||||
@ -23,7 +23,7 @@ const CustomStyledMenu = styled(Menu)(({ theme }) => ({
|
||||
color: '#444',
|
||||
transition: '0.3s background-color',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f0f0',
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
},
|
||||
},
|
||||
}));
|
||||
@ -37,6 +37,7 @@ export const ContextMenuPinnedApps = ({ children, app, isMine }) => {
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(
|
||||
sortablePinnedAppsAtom
|
||||
);
|
||||
const theme = useTheme();
|
||||
|
||||
const handleContextMenu = (event) => {
|
||||
if (isMine) return;
|
||||
@ -170,9 +171,14 @@ export const ContextMenuPinnedApps = ({ children, app, isMine }) => {
|
||||
}}
|
||||
>
|
||||
<ListItemIcon sx={{ minWidth: '32px' }}>
|
||||
<PushPinIcon fontSize="small" />
|
||||
<PushPinIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
fontSize="small"
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<Typography variant="inherit" sx={{ fontSize: '14px' }}>
|
||||
<Typography sx={{ fontSize: '14px' }} color="text.primary">
|
||||
Unpin app
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
|
@ -122,7 +122,7 @@ export const DesktopFooter = ({
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadGroups
|
||||
? 'var(--danger)'
|
||||
? theme.palette.other.danger
|
||||
: isGroups
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -141,7 +141,7 @@ export const DesktopFooter = ({
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadDirects
|
||||
? 'var(--danger)'
|
||||
? theme.palette.other.danger
|
||||
: isDirects
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
|
@ -104,14 +104,14 @@ export const DesktopHeader = ({
|
||||
{isPrivate && (
|
||||
<LockIcon
|
||||
sx={{
|
||||
color: 'var(--green)',
|
||||
color: theme.palette.other.positive,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{isPrivate === false && (
|
||||
<NoEncryptionGmailerrorredIcon
|
||||
sx={{
|
||||
color: 'var(--danger)',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@ -155,7 +155,7 @@ export const DesktopHeader = ({
|
||||
width={20}
|
||||
color={
|
||||
isUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: isAnnouncement
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -183,7 +183,7 @@ export const DesktopHeader = ({
|
||||
width={20}
|
||||
color={
|
||||
isUnreadChat
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: isChat
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Box, ButtonBase, useTheme } from '@mui/material';
|
||||
import { HomeIcon } from '../assets/Icons/HomeIcon';
|
||||
import { MessagingIcon } from '../assets/Icons/MessagingIcon';
|
||||
import { Save } from './Save/Save';
|
||||
import { IconWrapper } from './Desktop/DesktopFooter';
|
||||
import { useRecoilState } from 'recoil';
|
||||
@ -9,6 +8,7 @@ import { AppsIcon } from '../assets/Icons/AppsIcon';
|
||||
import ThemeSelector from './Theme/ThemeSelector';
|
||||
import { CoreSyncStatus } from './CoreSyncStatus';
|
||||
import LanguageSelector from './Language/LanguageSelector';
|
||||
import { MessagingIconFilled } from '../assets/Icons/MessagingIconFilled';
|
||||
|
||||
export const DesktopSideBar = ({
|
||||
goToHome,
|
||||
@ -40,6 +40,8 @@ export const DesktopSideBar = ({
|
||||
gap: '25px',
|
||||
height: '100vh',
|
||||
width: '60px',
|
||||
backgroundColor: theme.palette.background.surface,
|
||||
borderRight: `1px solid ${theme.palette.border.subtle}`,
|
||||
}}
|
||||
>
|
||||
<ButtonBase
|
||||
@ -101,7 +103,7 @@ export const DesktopSideBar = ({
|
||||
<IconWrapper
|
||||
color={
|
||||
hasUnreadDirects || hasUnreadGroups
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopViewMode === 'chat'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -109,11 +111,11 @@ export const DesktopSideBar = ({
|
||||
label="Chat"
|
||||
disableWidth
|
||||
>
|
||||
<MessagingIcon
|
||||
<MessagingIconFilled
|
||||
height={30}
|
||||
color={
|
||||
hasUnreadDirects || hasUnreadGroups
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopViewMode === 'chat'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { MyContext, getBaseApiReact } from "../../App";
|
||||
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
@ -15,285 +15,295 @@ import {
|
||||
Dialog,
|
||||
IconButton,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
import { base64ToBlobUrl } from "../../utils/fileReading";
|
||||
import { saveFileToDiskGeneric } from "../../utils/generateWallet/generateWallet";
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { base64ToBlobUrl } from '../../utils/fileReading';
|
||||
import { saveFileToDiskGeneric } from '../../utils/generateWallet/generateWallet';
|
||||
import AttachmentIcon from '@mui/icons-material/Attachment';
|
||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
|
||||
import { CustomLoader } from "../../common/CustomLoader";
|
||||
import { Spacer } from "../../common/Spacer";
|
||||
import { FileAttachmentContainer, FileAttachmentFont } from "./Embed-styles";
|
||||
import DownloadIcon from "@mui/icons-material/Download";
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||
import { CustomLoader } from '../../common/CustomLoader';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { FileAttachmentContainer, FileAttachmentFont } from './Embed-styles';
|
||||
import DownloadIcon from '@mui/icons-material/Download';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import { useSetRecoilState } from "recoil";
|
||||
import { blobControllerAtom } from "../../atoms/global";
|
||||
import { decodeIfEncoded } from "../../utils/decode";
|
||||
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { blobControllerAtom } from '../../atoms/global';
|
||||
import { decodeIfEncoded } from '../../utils/decode';
|
||||
|
||||
export const AttachmentCard = ({
|
||||
resourceData,
|
||||
resourceDetails,
|
||||
owner,
|
||||
refresh,
|
||||
openExternal,
|
||||
external,
|
||||
isLoadingParent,
|
||||
errorMsg,
|
||||
encryptionType,
|
||||
selectedGroupId
|
||||
}) => {
|
||||
resourceData,
|
||||
resourceDetails,
|
||||
owner,
|
||||
refresh,
|
||||
openExternal,
|
||||
external,
|
||||
isLoadingParent,
|
||||
errorMsg,
|
||||
encryptionType,
|
||||
selectedGroupId,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const { downloadResource } = useContext(MyContext);
|
||||
const theme = useTheme();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const { downloadResource } = useContext(MyContext);
|
||||
|
||||
const saveToDisk = async ()=> {
|
||||
const { name, service, identifier } = resourceData;
|
||||
|
||||
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}`;
|
||||
fetch(url)
|
||||
.then(response => response.blob())
|
||||
.then(async blob => {
|
||||
await saveFileToDiskGeneric(blob, resourceData?.fileName)
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error fetching the video:", error);
|
||||
});
|
||||
}
|
||||
|
||||
const saveToDiskEncrypted = async ()=> {
|
||||
let blobUrl
|
||||
const saveToDisk = async () => {
|
||||
const { name, service, identifier } = resourceData;
|
||||
|
||||
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}`;
|
||||
fetch(url)
|
||||
.then((response) => response.blob())
|
||||
.then(async (blob) => {
|
||||
await saveFileToDiskGeneric(blob, resourceData?.fileName);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error fetching the video:', error);
|
||||
});
|
||||
};
|
||||
|
||||
const saveToDiskEncrypted = async () => {
|
||||
let blobUrl;
|
||||
try {
|
||||
const { name, service, identifier, key } = resourceData;
|
||||
|
||||
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}?encoding=base64`;
|
||||
const res = await fetch(url);
|
||||
const data = await res.text();
|
||||
let decryptedData;
|
||||
try {
|
||||
const { name, service, identifier,key } = resourceData;
|
||||
|
||||
const url = `${getBaseApiReact()}/arbitrary/${service}/${name}/${identifier}?encoding=base64`;
|
||||
const res = await fetch(url)
|
||||
const data = await res.text();
|
||||
let decryptedData
|
||||
try {
|
||||
if(key && encryptionType === 'private'){
|
||||
decryptedData = await window.sendMessage(
|
||||
"DECRYPT_DATA_WITH_SHARING_KEY",
|
||||
|
||||
{
|
||||
encryptedData: data,
|
||||
key: decodeURIComponent(key),
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
if(encryptionType === 'group'){
|
||||
decryptedData = await window.sendMessage(
|
||||
"DECRYPT_QORTAL_GROUP_DATA",
|
||||
|
||||
{
|
||||
data64: data,
|
||||
groupId: selectedGroupId,
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('Unable to decrypt')
|
||||
if (key && encryptionType === 'private') {
|
||||
decryptedData = await window.sendMessage(
|
||||
'DECRYPT_DATA_WITH_SHARING_KEY',
|
||||
|
||||
{
|
||||
encryptedData: data,
|
||||
key: decodeURIComponent(key),
|
||||
}
|
||||
);
|
||||
}
|
||||
if (encryptionType === 'group') {
|
||||
decryptedData = await window.sendMessage(
|
||||
'DECRYPT_QORTAL_GROUP_DATA',
|
||||
|
||||
{
|
||||
data64: data,
|
||||
groupId: selectedGroupId,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!decryptedData || decryptedData?.error) throw new Error("Could not decrypt data");
|
||||
blobUrl = base64ToBlobUrl(decryptedData, resourceData?.mimeType)
|
||||
const response = await fetch(blobUrl);
|
||||
const blob = await response.blob();
|
||||
await saveFileToDiskGeneric(blob, resourceData?.fileName)
|
||||
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
if(blobUrl){
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
|
||||
throw new Error('Unable to decrypt');
|
||||
}
|
||||
|
||||
if (!decryptedData || decryptedData?.error)
|
||||
throw new Error('Could not decrypt data');
|
||||
blobUrl = base64ToBlobUrl(decryptedData, resourceData?.mimeType);
|
||||
const response = await fetch(blobUrl);
|
||||
const blob = await response.blob();
|
||||
await saveFileToDiskGeneric(blob, resourceData?.fileName);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
if (blobUrl) {
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Card
|
||||
};
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
height: '250px',
|
||||
// height: isOpen ? "auto" : "150px",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#1F2023",
|
||||
height: "250px",
|
||||
// height: isOpen ? "auto" : "150px",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '16px 16px 0px 16px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "16px 16px 0px 16px",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
<AttachmentIcon
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
>
|
||||
<AttachmentIcon
|
||||
/>
|
||||
<Typography>ATTACHMENT embed</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
<ButtonBase>
|
||||
<RefreshIcon
|
||||
onClick={refresh}
|
||||
sx={{
|
||||
color: "white",
|
||||
fontSize: '24px',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>ATTACHMENT embed</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
</ButtonBase>
|
||||
{external && (
|
||||
<ButtonBase>
|
||||
<RefreshIcon
|
||||
onClick={refresh}
|
||||
<OpenInNewIcon
|
||||
onClick={openExternal}
|
||||
sx={{
|
||||
fontSize: "24px",
|
||||
color: "white",
|
||||
fontSize: '24px',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
{external && (
|
||||
<ButtonBase>
|
||||
<OpenInNewIcon
|
||||
onClick={openExternal}
|
||||
sx={{
|
||||
fontSize: "24px",
|
||||
color: "white",
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
padding: "8px 16px 8px 16px",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "12px",
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
Created by {decodeIfEncoded(owner)}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "12px",
|
||||
color: "cadetblue",
|
||||
}}
|
||||
>
|
||||
{encryptionType === 'private' ? "ENCRYPTED" : encryptionType === 'group' ? 'GROUP ENCRYPTED' : "Not encrypted"}
|
||||
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ borderColor: "rgb(255 255 255 / 10%)" }} />
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
|
||||
{isLoadingParent && isOpen && (
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
<CustomLoader />{" "}
|
||||
</Box>
|
||||
)}
|
||||
{errorMsg && (
|
||||
<Box
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
padding: '8px 16px 8px 16px',
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
Created by {decodeIfEncoded(owner)}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
{encryptionType === 'private'
|
||||
? 'ENCRYPTED'
|
||||
: encryptionType === 'group'
|
||||
? 'GROUP ENCRYPTED'
|
||||
: 'Not encrypted'}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ borderColor: 'rgb(255 255 255 / 10%)' }} />
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{isLoadingParent && isOpen && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
<CustomLoader />{' '}
|
||||
</Box>
|
||||
)}
|
||||
{errorMsg && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
<Typography
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
fontSize: '14px',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
{errorMsg}
|
||||
</Typography>{' '}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<CardContent>
|
||||
{resourceData?.fileName && (
|
||||
<>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
color: "var(--danger)",
|
||||
fontSize: '14px',
|
||||
}}
|
||||
>
|
||||
{errorMsg}
|
||||
</Typography>{" "}
|
||||
</Box>
|
||||
{resourceData?.fileName}
|
||||
</Typography>
|
||||
<Spacer height="10px" />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<CardContent>
|
||||
{resourceData?.fileName && (
|
||||
<ButtonBase
|
||||
sx={{
|
||||
width: '90%',
|
||||
maxWidth: '400px',
|
||||
}}
|
||||
onClick={() => {
|
||||
if (resourceDetails?.status?.status === 'READY') {
|
||||
if (encryptionType) {
|
||||
saveToDiskEncrypted();
|
||||
return;
|
||||
}
|
||||
saveToDisk();
|
||||
return;
|
||||
}
|
||||
downloadResource(resourceData);
|
||||
}}
|
||||
>
|
||||
<FileAttachmentContainer>
|
||||
<Typography>
|
||||
{resourceDetails?.status?.status === 'DOWNLOADED'
|
||||
? 'BUILDING'
|
||||
: resourceDetails?.status?.status}
|
||||
</Typography>
|
||||
{!resourceDetails && (
|
||||
<>
|
||||
<Typography sx={{
|
||||
fontSize: '14px'
|
||||
}}>{resourceData?.fileName}</Typography>
|
||||
<Spacer height="10px" />
|
||||
<DownloadIcon />
|
||||
<FileAttachmentFont>Download File</FileAttachmentFont>
|
||||
</>
|
||||
)}
|
||||
<ButtonBase sx={{
|
||||
width: '90%',
|
||||
maxWidth: '400px'
|
||||
}} onClick={()=> {
|
||||
if(resourceDetails?.status?.status === 'READY'){
|
||||
if(encryptionType){
|
||||
saveToDiskEncrypted()
|
||||
return
|
||||
}
|
||||
saveToDisk()
|
||||
return
|
||||
}
|
||||
downloadResource(resourceData)
|
||||
}}>
|
||||
|
||||
<FileAttachmentContainer >
|
||||
<Typography>{resourceDetails?.status?.status === 'DOWNLOADED' ? 'BUILDING' : resourceDetails?.status?.status}</Typography>
|
||||
{!resourceDetails && (
|
||||
<>
|
||||
<DownloadIcon />
|
||||
<FileAttachmentFont>Download File</FileAttachmentFont>
|
||||
|
||||
</>
|
||||
)}
|
||||
{resourceDetails && resourceDetails?.status?.status !== 'READY' && resourceDetails?.status?.status !== 'FAILED_TO_DOWNLOAD' && (
|
||||
<>
|
||||
<CircularProgress sx={{
|
||||
color: 'white'
|
||||
}} size={20} />
|
||||
<FileAttachmentFont>Downloading: {resourceDetails?.status?.percentLoaded || '0'}%</FileAttachmentFont>
|
||||
|
||||
</>
|
||||
)}
|
||||
{resourceDetails && resourceDetails?.status?.status === 'READY' && (
|
||||
<>
|
||||
<SaveIcon />
|
||||
<FileAttachmentFont>Save to Disk</FileAttachmentFont>
|
||||
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
</FileAttachmentContainer>
|
||||
</ButtonBase>
|
||||
|
||||
</CardContent>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
{resourceDetails &&
|
||||
resourceDetails?.status?.status !== 'READY' &&
|
||||
resourceDetails?.status?.status !== 'FAILED_TO_DOWNLOAD' && (
|
||||
<>
|
||||
<CircularProgress
|
||||
size={20}
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<FileAttachmentFont>
|
||||
Downloading:{' '}
|
||||
{resourceDetails?.status?.percentLoaded || '0'}%
|
||||
</FileAttachmentFont>
|
||||
</>
|
||||
)}
|
||||
{resourceDetails &&
|
||||
resourceDetails?.status?.status === 'READY' && (
|
||||
<>
|
||||
<SaveIcon />
|
||||
<FileAttachmentFont>Save to Disk</FileAttachmentFont>
|
||||
</>
|
||||
)}
|
||||
</FileAttachmentContainer>
|
||||
</ButtonBase>
|
||||
</CardContent>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
@ -1,265 +1,266 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
Typography,
|
||||
|
||||
Box,
|
||||
ButtonBase,
|
||||
Divider,
|
||||
Dialog,
|
||||
IconButton,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
|
||||
} from "@mui/material";
|
||||
|
||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
|
||||
import { CustomLoader } from "../../common/CustomLoader";
|
||||
import ImageIcon from "@mui/icons-material/Image";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { decodeIfEncoded } from "../../utils/decode";
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||
import { CustomLoader } from '../../common/CustomLoader';
|
||||
import ImageIcon from '@mui/icons-material/Image';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { decodeIfEncoded } from '../../utils/decode';
|
||||
|
||||
export const ImageCard = ({
|
||||
image,
|
||||
fetchImage,
|
||||
owner,
|
||||
refresh,
|
||||
openExternal,
|
||||
external,
|
||||
isLoadingParent,
|
||||
errorMsg,
|
||||
encryptionType,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [height, setHeight] = useState('400px')
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
fetchImage();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
// useEffect(()=> {
|
||||
// if(errorMsg){
|
||||
// setHeight('300px')
|
||||
// }
|
||||
// }, [errorMsg])
|
||||
|
||||
return (
|
||||
<Card
|
||||
image,
|
||||
fetchImage,
|
||||
owner,
|
||||
refresh,
|
||||
openExternal,
|
||||
external,
|
||||
isLoadingParent,
|
||||
errorMsg,
|
||||
encryptionType,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [height, setHeight] = useState('400px');
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
fetchImage();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
// useEffect(()=> {
|
||||
// if(errorMsg){
|
||||
// setHeight('300px')
|
||||
// }
|
||||
// }, [errorMsg])
|
||||
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
backgroundColor: theme.palette.background.default,
|
||||
height: height,
|
||||
transition: 'height 0.6s ease-in-out',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#1F2023",
|
||||
height: height,
|
||||
transition: "height 0.6s ease-in-out",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '16px 16px 0px 16px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "16px 16px 0px 16px",
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
<ImageIcon
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
>
|
||||
<ImageIcon
|
||||
/>
|
||||
<Typography>IMAGE embed</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
<ButtonBase>
|
||||
<RefreshIcon
|
||||
onClick={refresh}
|
||||
sx={{
|
||||
color: "white",
|
||||
fontSize: '24px',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>IMAGE embed</Typography>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
</ButtonBase>
|
||||
{external && (
|
||||
<ButtonBase>
|
||||
<RefreshIcon
|
||||
onClick={refresh}
|
||||
<OpenInNewIcon
|
||||
onClick={openExternal}
|
||||
sx={{
|
||||
fontSize: "24px",
|
||||
color: "white",
|
||||
fontSize: '24px',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
{external && (
|
||||
<ButtonBase>
|
||||
<OpenInNewIcon
|
||||
onClick={openExternal}
|
||||
sx={{
|
||||
fontSize: "24px",
|
||||
color: "white",
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
)}
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
padding: '8px 16px 8px 16px',
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
Created by {decodeIfEncoded(owner)}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
{encryptionType === 'private'
|
||||
? 'ENCRYPTED'
|
||||
: encryptionType === 'group'
|
||||
? 'GROUP ENCRYPTED'
|
||||
: 'Not encrypted'}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ borderColor: 'rgb(255 255 255 / 10%)' }} />
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{isLoadingParent && isOpen && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
<CustomLoader />{' '}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
padding: "8px 16px 8px 16px",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
)}
|
||||
{errorMsg && (
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: "12px",
|
||||
color: "white",
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
Created by {decodeIfEncoded(owner)}
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "12px",
|
||||
color: "cadetblue",
|
||||
}}
|
||||
>
|
||||
{encryptionType === 'private' ? "ENCRYPTED" : encryptionType === 'group' ? 'GROUP ENCRYPTED' : "Not encrypted"}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ borderColor: "rgb(255 255 255 / 10%)" }} />
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
|
||||
{isLoadingParent && isOpen && (
|
||||
<Box
|
||||
{' '}
|
||||
<Typography
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
fontSize: '14px',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
<CustomLoader />{" "}
|
||||
</Box>
|
||||
)}
|
||||
{errorMsg && (
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{" "}
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: "14px",
|
||||
color: "var(--danger)",
|
||||
}}
|
||||
>
|
||||
{errorMsg}
|
||||
</Typography>{" "}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<CardContent>
|
||||
<ImageViewer src={image} />
|
||||
</CardContent>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
{errorMsg}
|
||||
</Typography>{' '}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
export function ImageViewer({ src, alt = "" }) {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const handleOpenFullscreen = () => setIsFullscreen(true);
|
||||
const handleCloseFullscreen = () => setIsFullscreen(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Image in container */}
|
||||
<Box>
|
||||
<CardContent>
|
||||
<ImageViewer src={image} />
|
||||
</CardContent>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export function ImageViewer({ src, alt = '' }) {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const handleOpenFullscreen = () => setIsFullscreen(true);
|
||||
const handleCloseFullscreen = () => setIsFullscreen(false);
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<>
|
||||
{/* Image in container */}
|
||||
<Box
|
||||
sx={{
|
||||
maxWidth: '100%', // Prevent horizontal overflow
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={handleOpenFullscreen}
|
||||
>
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
style={{
|
||||
maxWidth: '100%',
|
||||
maxHeight: '450px', // Adjust max height for small containers
|
||||
objectFit: 'contain', // Preserve aspect ratio
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Fullscreen Viewer */}
|
||||
<Dialog
|
||||
open={isFullscreen}
|
||||
onClose={handleCloseFullscreen}
|
||||
maxWidth="lg"
|
||||
fullWidth
|
||||
fullScreen
|
||||
sx={{
|
||||
'& .MuiDialog-paper': {
|
||||
margin: 0,
|
||||
maxWidth: '100%',
|
||||
width: '100%',
|
||||
height: '100vh',
|
||||
overflow: 'hidden', // Prevent scrollbars
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
maxWidth: "100%", // Prevent horizontal overflow
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.paper, // Optional: dark background for fullscreen mode
|
||||
}}
|
||||
onClick={handleOpenFullscreen}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<IconButton
|
||||
onClick={handleCloseFullscreen}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 8,
|
||||
right: 8,
|
||||
zIndex: 10,
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
|
||||
{/* Fullscreen Image */}
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
style={{
|
||||
maxWidth: "100%",
|
||||
maxHeight: "450px", // Adjust max height for small containers
|
||||
objectFit: "contain", // Preserve aspect ratio
|
||||
maxWidth: '100%',
|
||||
maxHeight: '100%',
|
||||
objectFit: 'contain', // Preserve aspect ratio
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Fullscreen Viewer */}
|
||||
<Dialog
|
||||
open={isFullscreen}
|
||||
onClose={handleCloseFullscreen}
|
||||
maxWidth="lg"
|
||||
fullWidth
|
||||
fullScreen
|
||||
sx={{
|
||||
"& .MuiDialog-paper": {
|
||||
margin: 0,
|
||||
maxWidth: "100%",
|
||||
width: "100%",
|
||||
height: "100vh",
|
||||
overflow: "hidden", // Prevent scrollbars
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#000", // Optional: dark background for fullscreen mode
|
||||
}}
|
||||
>
|
||||
{/* Close Button */}
|
||||
<IconButton
|
||||
onClick={handleCloseFullscreen}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
top: 8,
|
||||
right: 8,
|
||||
zIndex: 10,
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
|
||||
{/* Fullscreen Image */}
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
style={{
|
||||
maxWidth: "100%",
|
||||
maxHeight: "100%",
|
||||
objectFit: "contain", // Preserve aspect ratio
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
}
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
Box,
|
||||
ButtonBase,
|
||||
Divider,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { getNameInfo } from '../Group/Group';
|
||||
import PollIcon from '@mui/icons-material/Poll';
|
||||
@ -37,6 +38,7 @@ export const PollCard = ({
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { show, userInfo } = useContext(MyContext);
|
||||
const [isLoadingSubmit, setIsLoadingSubmit] = useState(false);
|
||||
const theme = useTheme();
|
||||
const handleVote = async () => {
|
||||
const fee = await getFee('VOTE_ON_POLL');
|
||||
|
||||
@ -103,7 +105,7 @@ export const PollCard = ({
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
backgroundColor: '#1F2023',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
height: isOpen ? 'auto' : '150px',
|
||||
}}
|
||||
>
|
||||
@ -124,7 +126,7 @@ export const PollCard = ({
|
||||
>
|
||||
<PollIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>POLL embed</Typography>
|
||||
@ -141,7 +143,7 @@ export const PollCard = ({
|
||||
onClick={refresh}
|
||||
sx={{
|
||||
fontSize: '24px',
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
@ -151,7 +153,7 @@ export const PollCard = ({
|
||||
onClick={openExternal}
|
||||
sx={{
|
||||
fontSize: '24px',
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
@ -186,9 +188,6 @@ export const PollCard = ({
|
||||
<Button
|
||||
size="small"
|
||||
variant="contained"
|
||||
sx={{
|
||||
backgroundColor: 'var(--green)',
|
||||
}}
|
||||
onClick={() => {
|
||||
setIsOpen(true);
|
||||
}}
|
||||
@ -221,7 +220,7 @@ export const PollCard = ({
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '14px',
|
||||
color: 'var(--danger)',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
>
|
||||
{errorMsg}
|
||||
@ -260,16 +259,7 @@ export const PollCard = ({
|
||||
<FormControlLabel
|
||||
key={index}
|
||||
value={index}
|
||||
control={
|
||||
<Radio
|
||||
sx={{
|
||||
color: 'white', // Unchecked color
|
||||
'&.Mui-checked': {
|
||||
color: 'var(--green)', // Checked color
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
control={<Radio />}
|
||||
label={option?.optionName}
|
||||
sx={{
|
||||
'& .MuiFormControlLabel-label': {
|
||||
|
@ -63,7 +63,7 @@ export const GeneralNotifications = ({ address }) => {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -76,8 +76,8 @@ export const GeneralNotifications = ({ address }) => {
|
||||
<NotificationsIcon
|
||||
sx={{
|
||||
color: hasNewPayment
|
||||
? 'var(--unread)'
|
||||
: theme.palette.text.primary,
|
||||
? theme.palette.other.unread
|
||||
: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -149,7 +149,7 @@ export const GeneralNotifications = ({ address }) => {
|
||||
>
|
||||
<AccountBalanceWalletIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>{' '}
|
||||
{formatDate(latestTx?.timestamp)}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { CustomButton, CustomButtonAccept } from '../../styles/App-styles';
|
||||
import { getBaseApiReact, MyContext } from '../../App';
|
||||
@ -23,6 +24,7 @@ export const JoinGroup = ({ memberGroups }) => {
|
||||
const [groupInfo, setGroupInfo] = useState(null);
|
||||
const [isLoadingInfo, setIsLoadingInfo] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const theme = useTheme();
|
||||
const [isLoadingJoinGroup, setIsLoadingJoinGroup] = useState(false);
|
||||
const handleJoinGroup = async (e) => {
|
||||
setGroupInfo(null);
|
||||
@ -151,7 +153,7 @@ export const JoinGroup = ({ memberGroups }) => {
|
||||
<CircularProgress
|
||||
size={25}
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>{' '}
|
||||
</Box>
|
||||
@ -228,7 +230,7 @@ export const JoinGroup = ({ memberGroups }) => {
|
||||
>
|
||||
<CustomButtonAccept
|
||||
color="black"
|
||||
bgColor="var(--green)"
|
||||
bgColor={theme.palette.other.positive}
|
||||
sx={{
|
||||
minWidth: '102px',
|
||||
height: '45px',
|
||||
@ -242,7 +244,7 @@ export const JoinGroup = ({ memberGroups }) => {
|
||||
|
||||
<CustomButtonAccept
|
||||
color="black"
|
||||
bgColor="var(--danger)"
|
||||
bgColor={theme.palette.other.danger}
|
||||
sx={{
|
||||
minWidth: '102px',
|
||||
height: '45px',
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
Popover,
|
||||
TextField,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import {
|
||||
useCallback,
|
||||
@ -45,7 +46,7 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => {
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [filteredItems, setFilteredItems] = useState(groups);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const handleFilter = useCallback(
|
||||
(query) => {
|
||||
if (query) {
|
||||
@ -254,14 +255,14 @@ export const AddGroupList = ({ setInfoSnack, setOpenSnack }) => {
|
||||
{group?.isOpen === false && (
|
||||
<LockIcon
|
||||
sx={{
|
||||
color: 'var(--green)',
|
||||
color: theme.palette.other.positive,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{group?.isOpen === true && (
|
||||
<NoEncryptionGmailerrorredIcon
|
||||
sx={{
|
||||
color: 'var(--danger)',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -1,45 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import DOMPurify from 'dompurify';
|
||||
import 'react-quill/dist/quill.snow.css';
|
||||
import 'react-quill/dist/quill.core.css';
|
||||
import 'react-quill/dist/quill.bubble.css';
|
||||
import { Box, styled } from '@mui/material';
|
||||
import { convertQortalLinks } from '../../../utils/qortalLink';
|
||||
|
||||
const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
fontFamily: 'Mulish',
|
||||
fontSize: '19px',
|
||||
fontWeight: 400,
|
||||
letterSpacing: 0,
|
||||
color: theme.palette.text.primary,
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
export const DisplayHtml = ({ html, textColor }: any) => {
|
||||
const cleanContent = useMemo(() => {
|
||||
if (!html) return null;
|
||||
|
||||
const sanitize: string = DOMPurify.sanitize(html, {
|
||||
USE_PROFILES: { html: true },
|
||||
});
|
||||
const anchorQortal = convertQortalLinks(sanitize);
|
||||
return anchorQortal;
|
||||
}, [html]);
|
||||
|
||||
if (!cleanContent) return null;
|
||||
|
||||
return (
|
||||
<CrowdfundInlineContent>
|
||||
<div
|
||||
className="ql-editor-display"
|
||||
style={{
|
||||
color: textColor || 'white',
|
||||
fontWeight: 400,
|
||||
fontSize: '16px',
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: cleanContent }}
|
||||
/>
|
||||
</CrowdfundInlineContent>
|
||||
);
|
||||
};
|
@ -5,7 +5,7 @@ import React, {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Avatar, Box, Popover, Typography } from '@mui/material';
|
||||
import { Avatar, Box, Popover, Typography, useTheme } from '@mui/material';
|
||||
// import { MAIL_SERVICE_TYPE, THREAD_SERVICE_TYPE } from "../../constants/mail";
|
||||
import { Thread } from './Thread';
|
||||
import {
|
||||
@ -49,7 +49,6 @@ import {
|
||||
handleUnencryptedPublishes,
|
||||
} from '../../Chat/GroupAnnouncements';
|
||||
import CheckSVG from '../../../assets/svgs/Check.svg';
|
||||
import SortSVG from '../../../assets/svgs/Sort.svg';
|
||||
import ArrowDownSVG from '../../../assets/svgs/ArrowDown.svg';
|
||||
import { LoadingSnackbar } from '../../Snackbar/LoadingSnackbar';
|
||||
import { executeEvent } from '../../../utils/events';
|
||||
@ -57,9 +56,11 @@ import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import { getArbitraryEndpointReact, getBaseApiReact } from '../../../App';
|
||||
import { addDataPublishesFunc, getDataPublishesFunc } from '../Group';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SortIcon } from '../../../assets/Icons/SortIcon';
|
||||
import { CustomButton } from '../../../styles/App-styles';
|
||||
|
||||
const filterOptions = ['Recently active', 'Newest', 'Oldest'];
|
||||
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
export const threadIdentifier = 'DOCUMENT';
|
||||
|
||||
export const GroupMail = ({
|
||||
@ -83,7 +84,7 @@ export const GroupMail = ({
|
||||
const [tempPublishedList, setTempPublishedList] = useState([]);
|
||||
const dataPublishes = useRef({});
|
||||
const { t } = useTranslation(['core']);
|
||||
|
||||
const theme = useTheme();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const groupIdRef = useRef<any>(null);
|
||||
const groupId = useMemo(() => {
|
||||
@ -605,13 +606,19 @@ export const GroupMail = ({
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor:
|
||||
filterMode === filter ? 'rgba(74, 158, 244, 1)' : 'unset',
|
||||
filterMode === filter
|
||||
? theme.palette.action.selected
|
||||
: 'unset',
|
||||
}}
|
||||
key={filter}
|
||||
>
|
||||
<InstanceListContainerRowCheck>
|
||||
{filter === filterMode && (
|
||||
<InstanceListContainerRowCheckIcon src={CheckSVG} />
|
||||
<CheckIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</InstanceListContainerRowCheck>
|
||||
<InstanceListContainerRowMain>
|
||||
@ -657,7 +664,7 @@ export const GroupMail = ({
|
||||
}}
|
||||
ref={anchorElInstanceFilter}
|
||||
>
|
||||
<ComposeIcon src={SortSVG} />
|
||||
<SortIcon />
|
||||
|
||||
<SelectInstanceContainerFilterInner>
|
||||
<ComposeP>Sort by</ComposeP>
|
||||
@ -680,8 +687,8 @@ export const GroupMail = ({
|
||||
<RefreshIcon
|
||||
onClick={refetchThreadsLists}
|
||||
sx={{
|
||||
color: 'white',
|
||||
cursor: 'pointer',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@ -771,7 +778,7 @@ export const GroupMail = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Box
|
||||
<CustomButton
|
||||
onClick={() => {
|
||||
setTimeout(() => {
|
||||
executeEvent('threadFetchMode', {
|
||||
@ -781,7 +788,6 @@ export const GroupMail = ({
|
||||
}}
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#27282c',
|
||||
borderRadius: '5px',
|
||||
bottom: '2px',
|
||||
cursor: 'pointer',
|
||||
@ -790,14 +796,11 @@ export const GroupMail = ({
|
||||
padding: '5px',
|
||||
position: 'absolute',
|
||||
right: '2px',
|
||||
'&:hover': {
|
||||
background: 'rgba(255, 255, 255, 0.60)',
|
||||
},
|
||||
minWidth: 'unset',
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
color: 'white',
|
||||
fontSize: '12px',
|
||||
}}
|
||||
>
|
||||
@ -807,11 +810,11 @@ export const GroupMail = ({
|
||||
</Typography>
|
||||
<ArrowForwardIosIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
fontSize: '12px',
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</CustomButton>
|
||||
</SingleThreadParent>
|
||||
);
|
||||
})}
|
||||
|
@ -1,16 +1,6 @@
|
||||
import { Typography, Box, TextField } from '@mui/material';
|
||||
import { Typography, Box } from '@mui/material';
|
||||
import { styled } from '@mui/system';
|
||||
|
||||
export const InstanceContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
backgroundColor: 'var(--color-instance)',
|
||||
height: '59px',
|
||||
flexShrink: 0,
|
||||
justifyContent: 'space-between',
|
||||
}));
|
||||
|
||||
export const MailContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
@ -88,7 +78,7 @@ export const ComposeContainer = styled(Box)(({ theme }) => ({
|
||||
transition: '0.2s background-color',
|
||||
justifyContent: 'center',
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(67, 68, 72, 1)',
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
},
|
||||
}));
|
||||
|
||||
@ -141,19 +131,6 @@ export const SelectInstanceContainer = styled(Box)(({ theme }) => ({
|
||||
gap: '17px',
|
||||
}));
|
||||
|
||||
export const SelectInstanceContainerInner = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '3px',
|
||||
cursor: 'pointer',
|
||||
padding: '8px',
|
||||
transition: 'all 0.2s',
|
||||
'&:hover': {
|
||||
borderRadius: '8px',
|
||||
background: '#434448',
|
||||
},
|
||||
}));
|
||||
|
||||
export const SelectInstanceContainerFilterInner = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@ -174,100 +151,21 @@ export const InstanceP = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 500,
|
||||
}));
|
||||
|
||||
export const MailMessageRowContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
justifyContent: 'space-between',
|
||||
borderRadius: '56px 5px 10px 56px',
|
||||
paddingRight: '15px',
|
||||
transition: 'background 0.2s',
|
||||
gap: '10px',
|
||||
'&:hover': {
|
||||
background: '#434448',
|
||||
},
|
||||
}));
|
||||
|
||||
export const MailMessageRowProfile = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
justifyContent: 'flex-start',
|
||||
gap: '10px',
|
||||
width: '50%',
|
||||
overflow: 'hidden',
|
||||
}));
|
||||
|
||||
export const MailMessageRowInfo = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
justifyContent: 'flex-start',
|
||||
gap: '7px',
|
||||
width: '50%',
|
||||
}));
|
||||
|
||||
export const MailMessageRowInfoStatusNotDecrypted = styled(Typography)(
|
||||
({ theme }) => ({
|
||||
fontSize: '16px',
|
||||
fontWeight: 900,
|
||||
textTransform: 'uppercase',
|
||||
paddingTop: '2px',
|
||||
})
|
||||
);
|
||||
|
||||
export const MailMessageRowInfoStatusRead = styled(Typography)(({ theme }) => ({
|
||||
fontSize: '16px',
|
||||
fontWeight: 300,
|
||||
}));
|
||||
|
||||
export const MessageExtraInfo = styled(Box)(({ theme }) => ({
|
||||
export const InstanceListParent = styled(Typography)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '2px',
|
||||
overflow: 'hidden',
|
||||
width: '425px', // only one width now
|
||||
minHeight: '246px',
|
||||
maxHeight: '325px',
|
||||
padding: '10px 0px 7px 0px',
|
||||
border: '1px solid rgba(0, 0, 0, 0.1)',
|
||||
}));
|
||||
|
||||
export const MessageExtraName = styled(Typography)(({ theme }) => ({
|
||||
fontSize: '16px',
|
||||
fontWeight: 900,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
}));
|
||||
|
||||
export const MessageExtraDate = styled(Typography)(({ theme }) => ({
|
||||
fontSize: '15px',
|
||||
fontWeight: 500,
|
||||
}));
|
||||
|
||||
export const MessagesContainer = styled(Box)(({ theme }) => ({
|
||||
width: '460px',
|
||||
maxWidth: '90%',
|
||||
export const InstanceListHeader = styled(Typography)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '12px',
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
export const InstanceListParent = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: 246px;
|
||||
max-height: 325px;
|
||||
width: 425px;
|
||||
padding: 10px 0px 7px 0px;
|
||||
background-color: var(--color-instance-popover-bg);
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
`;
|
||||
|
||||
export const InstanceListHeader = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background-color: var(--color-instance-popover-bg);
|
||||
`;
|
||||
|
||||
export const InstanceFooter = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -330,7 +228,7 @@ export const InstanceListContainerRow = styled(Box)(({ theme }) => ({
|
||||
cursor: 'pointer',
|
||||
transition: '0.2s background',
|
||||
'&:hover': {
|
||||
background: 'rgba(67, 68, 72, 1)',
|
||||
background: theme.palette.action.hover,
|
||||
},
|
||||
flexShrink: 0,
|
||||
}));
|
||||
@ -378,44 +276,6 @@ export const InstanceListContainerRowGroupIcon = styled('img')({
|
||||
userSelect: 'none',
|
||||
objectFit: 'contain',
|
||||
});
|
||||
export const TypeInAliasTextfield = styled(TextField)({
|
||||
width: '340px', // Adjust the width as needed
|
||||
borderRadius: '5px',
|
||||
backgroundColor: 'rgba(30, 30, 32, 1)',
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
input: {
|
||||
fontSize: 16,
|
||||
color: 'white',
|
||||
'&::placeholder': {
|
||||
fontSize: 16,
|
||||
color: 'rgba(255, 255, 255, 0.2)',
|
||||
},
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
padding: '10px',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
border: 'none',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
border: 'none',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
border: 'none',
|
||||
},
|
||||
},
|
||||
'& .MuiInput-underline:before': {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
'& .MuiInput-underline:hover:not(.Mui-disabled):before': {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
'& .MuiInput-underline:after': {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
});
|
||||
|
||||
export const NewMessageCloseImg = styled('img')({
|
||||
width: 'auto',
|
||||
@ -427,6 +287,7 @@ export const NewMessageCloseImg = styled('img')({
|
||||
export const NewMessageHeaderP = styled(Typography)(({ theme }) => ({
|
||||
fontSize: '18px',
|
||||
fontWeight: 600,
|
||||
color: theme.palette.text.primary,
|
||||
}));
|
||||
|
||||
export const NewMessageInputRow = styled(Box)(({ theme }) => ({
|
||||
@ -480,29 +341,24 @@ export const NewMessageAttachmentImg = styled('img')({
|
||||
border: '1px dashed #646464',
|
||||
});
|
||||
|
||||
export const NewMessageSendButton = styled(Box)`
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||
display: inline-flex;
|
||||
padding: 8px 16px 8px 12px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: fit-content;
|
||||
transition: all 0.2s;
|
||||
color: black;
|
||||
min-width: 120px;
|
||||
gap: 8px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: rgba(41, 41, 43, 1);
|
||||
color: white;
|
||||
svg path {
|
||||
fill: white; // Fill color changes to white on hover
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const NewMessageSendButton = styled(Box)(({ theme }) => ({
|
||||
borderRadius: '4px',
|
||||
border: `1px solid ${theme.palette.border.main}`, // you can replace with theme.palette.divider or whatever you want later
|
||||
display: 'inline-flex',
|
||||
padding: '8px 16px 8px 12px',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: 'fit-content',
|
||||
transition: 'all 0.2s',
|
||||
color: theme.palette.text.primary, // replace later with theme.palette.text.primary if needed
|
||||
minWidth: '120px',
|
||||
position: 'relative',
|
||||
gap: '8px',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action.hover, // replace with theme value if needed
|
||||
},
|
||||
}));
|
||||
|
||||
export const NewMessageSendP = styled(Typography)`
|
||||
font-family: Roboto;
|
||||
@ -524,14 +380,7 @@ export const ShowMessageNameP = styled(Typography)`
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
`;
|
||||
export const ShowMessageTimeP = styled(Typography)`
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
font-family: Roboto;
|
||||
font-size: 15px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
`;
|
||||
|
||||
export const ShowMessageSubjectP = styled(Typography)`
|
||||
font-family: Roboto;
|
||||
font-size: 16px;
|
||||
@ -541,61 +390,44 @@ export const ShowMessageSubjectP = styled(Typography)`
|
||||
text-align: left;
|
||||
`;
|
||||
|
||||
export const ShowMessageButton = styled(Box)`
|
||||
display: inline-flex;
|
||||
padding: 8px 16px 8px 16px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: fit-content;
|
||||
transition: all 0.2s;
|
||||
color: white;
|
||||
background-color: rgba(41, 41, 43, 1)
|
||||
min-width: 120px;
|
||||
gap: 8px;
|
||||
border-radius: 4px;
|
||||
border: 0.5px solid rgba(255, 255, 255, 0.70);
|
||||
font-family: Roboto;
|
||||
export const ShowMessageButton = styled(Box)(({ theme }) => ({
|
||||
display: 'inline-flex',
|
||||
padding: '8px 16px',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: 'fit-content',
|
||||
transition: 'all 0.2s',
|
||||
color: theme.palette.text.primary, // you'll replace with theme value
|
||||
minWidth: '120px',
|
||||
gap: '8px',
|
||||
borderRadius: '4px',
|
||||
border: theme.palette.border.main, // you'll replace
|
||||
fontFamily: 'Roboto',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
background: theme.palette.action.hover, // you'll replace
|
||||
borderRadius: '4px',
|
||||
},
|
||||
}));
|
||||
|
||||
min-width: 120px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
border-radius: 4px;
|
||||
border: 0.5px solid rgba(255, 255, 255, 0.70);
|
||||
background: #434448;
|
||||
}
|
||||
`;
|
||||
export const ShowMessageReturnButton = styled(Box)`
|
||||
display: inline-flex;
|
||||
padding: 8px 16px 8px 16px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
width: fit-content;
|
||||
transition: all 0.2s;
|
||||
color: white;
|
||||
background-color: rgba(41, 41, 43, 1)
|
||||
min-width: 120px;
|
||||
gap: 8px;
|
||||
border-radius: 4px;
|
||||
font-family: Roboto;
|
||||
|
||||
min-width: 120px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
border-radius: 4px;
|
||||
background: #434448;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ShowMessageButtonP = styled(Typography)`
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 120%; /* 19.2px */
|
||||
letter-spacing: -0.16px;
|
||||
color: white;
|
||||
`;
|
||||
export const ShowMessageReturnButton = styled(Box)(({ theme }) => ({
|
||||
display: 'inline-flex',
|
||||
padding: '8px 16px',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: 'fit-content',
|
||||
transition: 'all 0.2s',
|
||||
color: theme.palette.text.primary, // you'll replace with theme value
|
||||
minWidth: '120px',
|
||||
gap: '8px',
|
||||
borderRadius: '4px',
|
||||
fontFamily: 'Roboto',
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
background: theme.palette.action.hover, // you'll replace
|
||||
borderRadius: '4px',
|
||||
},
|
||||
}));
|
||||
|
||||
export const ShowMessageButtonImg = styled('img')({
|
||||
width: 'auto',
|
||||
@ -630,18 +462,16 @@ export const MoreImg = styled('img')({
|
||||
},
|
||||
});
|
||||
|
||||
export const MoreP = styled(Typography)`
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
|
||||
/* Attachments */
|
||||
font-family: Roboto;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 120%; /* 19.2px */
|
||||
letter-spacing: -0.16px;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
export const MoreP = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.text.primary, // Now dynamic
|
||||
fontFamily: 'Roboto',
|
||||
fontSize: '16px',
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 400,
|
||||
lineHeight: '120%', // 19.2px
|
||||
letterSpacing: '-0.16px',
|
||||
whiteSpace: 'nowrap',
|
||||
}));
|
||||
|
||||
export const ThreadContainerFullWidth = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
@ -658,7 +488,6 @@ export const ThreadContainer = styled(Box)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export const GroupNameP = styled(Typography)`
|
||||
color: #fff;
|
||||
font-size: 25px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
@ -667,7 +496,6 @@ export const GroupNameP = styled(Typography)`
|
||||
`;
|
||||
|
||||
export const AllThreadP = styled(Typography)`
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
@ -675,32 +503,32 @@ export const AllThreadP = styled(Typography)`
|
||||
letter-spacing: 0.15px;
|
||||
`;
|
||||
|
||||
export const SingleThreadParent = styled(Box)`
|
||||
border-radius: 35px 4px 4px 35px;
|
||||
position: relative;
|
||||
background: #434448;
|
||||
display: flex;
|
||||
padding: 13px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 5px;
|
||||
height: 76px;
|
||||
align-items: center;
|
||||
transition: 0.2s all;
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
`;
|
||||
export const SingleThreadParent = styled(Box)(({ theme }) => ({
|
||||
borderRadius: '35px 4px 4px 35px',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
padding: '13px',
|
||||
cursor: 'pointer',
|
||||
marginBottom: '5px',
|
||||
height: '76px',
|
||||
alignItems: 'center',
|
||||
transition: '0.2s all',
|
||||
backgroundColor: theme.palette.background.paper, // or remove if you want no background by default
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
},
|
||||
}));
|
||||
|
||||
export const SingleTheadMessageParent = styled(Box)`
|
||||
border-radius: 35px 4px 4px 35px;
|
||||
background: #434448;
|
||||
display: flex;
|
||||
padding: 13px;
|
||||
cursor: pointer;
|
||||
margin-bottom: 5px;
|
||||
height: 76px;
|
||||
align-items: center;
|
||||
`;
|
||||
export const SingleTheadMessageParent = styled(Box)(({ theme }) => ({
|
||||
borderRadius: '35px 4px 4px 35px',
|
||||
background: theme.palette.background.paper,
|
||||
display: 'flex',
|
||||
padding: '13px',
|
||||
cursor: 'pointer',
|
||||
marginBottom: '5px',
|
||||
height: '76px',
|
||||
alignItems: 'center',
|
||||
}));
|
||||
|
||||
export const ThreadInfoColumn = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
@ -713,7 +541,6 @@ export const ThreadInfoColumn = styled(Box)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export const ThreadInfoColumnNameP = styled(Typography)`
|
||||
color: #fff;
|
||||
font-family: Roboto;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
@ -724,26 +551,25 @@ export const ThreadInfoColumnNameP = styled(Typography)`
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
export const ThreadInfoColumnbyP = styled('span')`
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-family: Roboto;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
`;
|
||||
export const ThreadInfoColumnbyP = styled('span')(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
fontFamily: 'Roboto',
|
||||
fontSize: '16px',
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 500,
|
||||
lineHeight: 'normal',
|
||||
}));
|
||||
|
||||
export const ThreadInfoColumnTime = styled(Typography)`
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-family: Roboto;
|
||||
font-size: 15px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
`;
|
||||
export const ThreadInfoColumnTime = styled(Typography)(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
fontFamily: 'Roboto',
|
||||
fontSize: '15px',
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 500,
|
||||
lineHeight: 'normal',
|
||||
}));
|
||||
|
||||
export const ThreadSingleTitle = styled(Typography)`
|
||||
color: #fff;
|
||||
font-family: Roboto;
|
||||
font-size: 23px;
|
||||
font-style: normal;
|
||||
@ -755,7 +581,6 @@ export const ThreadSingleTitle = styled(Typography)`
|
||||
`;
|
||||
|
||||
export const ThreadSingleLastMessageP = styled(Typography)`
|
||||
color: #fff;
|
||||
font-family: Roboto;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
@ -764,7 +589,6 @@ export const ThreadSingleLastMessageP = styled(Typography)`
|
||||
`;
|
||||
|
||||
export const ThreadSingleLastMessageSpanP = styled('span')`
|
||||
color: #fff;
|
||||
font-family: Roboto;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
@ -792,6 +616,6 @@ export const CloseContainer = styled(Box)(({ theme }) => ({
|
||||
height: '50px',
|
||||
borderRadius: '0px 12px 0px 0px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(162, 31, 31, 1)',
|
||||
backgroundColor: theme.palette.action.hover,
|
||||
},
|
||||
}));
|
||||
|
@ -1,12 +1,9 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Box, CircularProgress, Input } from '@mui/material';
|
||||
import { Box, CircularProgress, Input, useTheme } from '@mui/material';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import ModalCloseSVG from '../../../assets/svgs/ModalClose.svg';
|
||||
import ComposeIconSVG from '../../../assets/svgs/ComposeIcon.svg';
|
||||
import {
|
||||
CloseContainer,
|
||||
ComposeContainer,
|
||||
ComposeIcon,
|
||||
ComposeP,
|
||||
InstanceFooter,
|
||||
InstanceListContainer,
|
||||
@ -29,6 +26,8 @@ import { MessageDisplay } from '../../Chat/MessageDisplay';
|
||||
import { CustomizedSnackbars } from '../../Snackbar/Snackbar';
|
||||
import { saveTempPublish } from '../../Chat/GroupAnnouncements';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ComposeIcon } from '../../../assets/Icons/ComposeIcon';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
@ -152,6 +151,7 @@ export const NewThread = ({
|
||||
const [openSnack, setOpenSnack] = React.useState(false);
|
||||
const [infoSnack, setInfoSnack] = React.useState(null);
|
||||
const editorRef = useRef(null);
|
||||
const theme = useTheme();
|
||||
const setEditorRef = (editorInstance) => {
|
||||
editorRef.current = editorInstance;
|
||||
};
|
||||
@ -406,7 +406,7 @@ export const NewThread = ({
|
||||
}}
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<ComposeIcon src={ComposeIconSVG} />
|
||||
<ComposeIcon />
|
||||
<ComposeP>{currentThread ? 'New Post' : 'New Thread'}</ComposeP>
|
||||
</ComposeContainer>
|
||||
|
||||
@ -417,7 +417,7 @@ export const NewThread = ({
|
||||
maxWidth: '950px',
|
||||
height: '700px',
|
||||
borderRadius: '12px 12px 0px 0px',
|
||||
background: '#434448',
|
||||
background: theme.palette.background.paper,
|
||||
padding: '0px',
|
||||
gap: '0px',
|
||||
}}
|
||||
@ -429,7 +429,7 @@ export const NewThread = ({
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: '#434448',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
}}
|
||||
>
|
||||
<NewMessageHeaderP>
|
||||
@ -441,12 +441,16 @@ export const NewThread = ({
|
||||
}}
|
||||
onClick={closeModal}
|
||||
>
|
||||
<NewMessageCloseImg src={ModalCloseSVG} />
|
||||
<CloseIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</CloseContainer>
|
||||
</InstanceListHeader>
|
||||
<InstanceListContainer
|
||||
sx={{
|
||||
backgroundColor: '#434448',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
padding: '20px 42px',
|
||||
height: 'calc(100% - 165px)',
|
||||
flexShrink: 0,
|
||||
@ -468,9 +472,7 @@ export const NewThread = ({
|
||||
autoCorrect="off"
|
||||
sx={{
|
||||
width: '100%',
|
||||
color: 'white',
|
||||
'& .MuiInput-input::placeholder': {
|
||||
color: 'rgba(255,255,255, 0.70) !important',
|
||||
fontSize: '20px',
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 400,
|
||||
@ -525,7 +527,7 @@ export const NewThread = ({
|
||||
|
||||
<InstanceFooter
|
||||
sx={{
|
||||
backgroundColor: '#434448',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
padding: '20px 42px',
|
||||
alignItems: 'center',
|
||||
height: '90px',
|
||||
@ -543,7 +545,12 @@ export const NewThread = ({
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<CircularProgress sx={{}} size={'12px'} />
|
||||
<CircularProgress
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
size={'12px'}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@ -552,9 +559,14 @@ export const NewThread = ({
|
||||
</NewMessageSendP>
|
||||
|
||||
{isMessage ? (
|
||||
<SendNewMessage opacity={1} height="25px" width="25px" />
|
||||
<SendNewMessage />
|
||||
) : (
|
||||
<CreateThreadIcon opacity={1} height="25px" width="25px" />
|
||||
<CreateThreadIcon
|
||||
color={theme.palette.text.primary}
|
||||
opacity={1}
|
||||
height="25px"
|
||||
width="25px"
|
||||
/>
|
||||
)}
|
||||
</NewMessageSendButton>
|
||||
</InstanceFooter>
|
||||
|
@ -5,7 +5,14 @@ import React, {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Avatar, Box, Button, ButtonBase, Typography } from '@mui/material';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
ButtonBase,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { ShowMessage } from './ShowMessageWithoutModal';
|
||||
import {
|
||||
ComposeP,
|
||||
@ -22,7 +29,6 @@ import {
|
||||
} from './Mail-styles';
|
||||
import { Spacer } from '../../../common/Spacer';
|
||||
import { threadIdentifier } from './GroupMail';
|
||||
import ReturnSVG from '../../../assets/svgs/Return.svg';
|
||||
import { NewThread } from './NewThread';
|
||||
import {
|
||||
decryptPublishes,
|
||||
@ -43,6 +49,7 @@ import { CustomLoader } from '../../../common/CustomLoader';
|
||||
import { WrapperUserAction } from '../../WrapperUserAction';
|
||||
import { formatTimestampForum } from '../../../utils/time';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReturnIcon } from '../../../assets/Icons/ReturnIcon';
|
||||
|
||||
const requestQueueSaveToLocal = new RequestQueueWithPromise(1);
|
||||
|
||||
@ -116,7 +123,7 @@ export const Thread = ({
|
||||
const [postReply, setPostReply] = useState(null);
|
||||
const [hasLastPage, setHasLastPage] = useState(false);
|
||||
const { t } = useTranslation(['core']);
|
||||
|
||||
const theme = useTheme();
|
||||
// Update: Use a new ref for the scrollable container
|
||||
const threadContainerRef = useRef(null);
|
||||
const threadBeginningRef = useRef(null);
|
||||
@ -606,7 +613,7 @@ export const Thread = ({
|
||||
closeThread();
|
||||
}}
|
||||
>
|
||||
<MailIconImg src={ReturnSVG} />
|
||||
<ReturnIcon />
|
||||
<ComposeP>
|
||||
{t('group:action.return_to_thread', {
|
||||
postProcess: 'capitalize',
|
||||
@ -619,7 +626,7 @@ export const Thread = ({
|
||||
<ButtonBase onClick={scrollToPosition}>
|
||||
<ArrowUpwardIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
cursor: 'pointer',
|
||||
fontSize: '36px',
|
||||
}}
|
||||
@ -629,7 +636,7 @@ export const Thread = ({
|
||||
<ButtonBase onClick={scrollToPosition}>
|
||||
<ArrowDownwardIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
cursor: 'pointer',
|
||||
fontSize: '36px',
|
||||
}}
|
||||
@ -825,7 +832,6 @@ export const Thread = ({
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '18px',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
{fullMessage?.error}
|
||||
@ -925,7 +931,6 @@ export const Thread = ({
|
||||
<Typography
|
||||
sx={{
|
||||
fontSize: '18px',
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
{t('core:downloading_qdn', { postProcess: 'capitalize' })}
|
||||
@ -958,9 +963,6 @@ export const Thread = ({
|
||||
groupInfo?.groupId
|
||||
);
|
||||
}}
|
||||
sx={{
|
||||
color: 'white',
|
||||
}}
|
||||
>
|
||||
{t('group:action.refetch_page', {
|
||||
postProcess: 'capitalize',
|
||||
|
@ -1556,12 +1556,13 @@ export const Group = ({
|
||||
<div
|
||||
style={{
|
||||
alignItems: 'flex-start',
|
||||
background: theme.palette.background.default,
|
||||
background: theme.palette.background.surface,
|
||||
borderRadius: '0px 15px 15px 0px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
width: '380px',
|
||||
padding: '0px 2px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@ -1581,7 +1582,7 @@ export const Group = ({
|
||||
<IconWrapper
|
||||
color={
|
||||
groupChatHasUnread || groupsAnnHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'groups'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1594,7 +1595,7 @@ export const Group = ({
|
||||
height={24}
|
||||
color={
|
||||
groupChatHasUnread || groupsAnnHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'groups'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1611,7 +1612,7 @@ export const Group = ({
|
||||
customWidth="75px"
|
||||
color={
|
||||
directChatHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'directs'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1623,7 +1624,7 @@ export const Group = ({
|
||||
height={24}
|
||||
color={
|
||||
directChatHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'directs'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1744,7 +1745,7 @@ export const Group = ({
|
||||
direct?.timestamp) && (
|
||||
<MarkChatUnreadIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@ -1779,7 +1780,7 @@ export const Group = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
console.log('groupsProperties', groupsProperties);
|
||||
|
||||
const renderGroups = () => {
|
||||
return (
|
||||
<div
|
||||
@ -1789,8 +1790,9 @@ export const Group = ({
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
height: '100%',
|
||||
background: theme.palette.background.default,
|
||||
background: theme.palette.background.surface,
|
||||
borderRadius: '0px 15px 15px 0px',
|
||||
padding: '0px 2px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@ -1810,7 +1812,7 @@ export const Group = ({
|
||||
<IconWrapper
|
||||
color={
|
||||
groupChatHasUnread || groupsAnnHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'groups'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1823,7 +1825,7 @@ export const Group = ({
|
||||
height={24}
|
||||
color={
|
||||
groupChatHasUnread || groupsAnnHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'groups'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1840,7 +1842,7 @@ export const Group = ({
|
||||
customWidth="75px"
|
||||
color={
|
||||
directChatHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'directs'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1852,7 +1854,7 @@ export const Group = ({
|
||||
height={24}
|
||||
color={
|
||||
directChatHasUnread
|
||||
? 'var(--unread)'
|
||||
? theme.palette.other.unread
|
||||
: desktopSideView === 'directs'
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary
|
||||
@ -1957,7 +1959,7 @@ export const Group = ({
|
||||
}/qortal_avatar?async=true`} /> */}
|
||||
<LockIcon
|
||||
sx={{
|
||||
color: 'var(--green)',
|
||||
color: theme.palette.other.positive,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@ -1975,7 +1977,7 @@ export const Group = ({
|
||||
>
|
||||
<NoEncryptionGmailerrorredIcon
|
||||
sx={{
|
||||
color: 'var(--danger)',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@ -2016,7 +2018,7 @@ export const Group = ({
|
||||
!groupAnnouncements[group?.groupId]?.seentimestamp && (
|
||||
<CampaignIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
marginRight: '5px',
|
||||
}}
|
||||
/>
|
||||
@ -2032,7 +2034,7 @@ export const Group = ({
|
||||
group?.timestamp) && (
|
||||
<MarkChatUnreadIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -71,7 +71,7 @@ export const GroupInvites = ({ myAddress, setOpenAddGroup }) => {
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
>
|
||||
{t('group:group_invites', { postProcess: 'capitalize' })}{' '}
|
||||
{t('group:group.invites', { postProcess: 'capitalize' })}{' '}
|
||||
{groupsWithJoinRequests?.length > 0 &&
|
||||
` (${groupsWithJoinRequests?.length})`}
|
||||
</Typography>
|
||||
|
@ -7,7 +7,7 @@ import IconButton from '@mui/material/IconButton';
|
||||
import { RequestQueueWithPromise } from '../../utils/queue/queue';
|
||||
import GroupAddIcon from '@mui/icons-material/GroupAdd';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { Box, ButtonBase, Collapse, Typography } from '@mui/material';
|
||||
import { Box, ButtonBase, Collapse, Typography, useTheme } from '@mui/material';
|
||||
import { CustomLoader } from '../../common/CustomLoader';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { myGroupsWhereIAmAdminAtom } from '../../atoms/global';
|
||||
@ -35,7 +35,7 @@ export const GroupJoinRequests = ({
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const { txList, setTxList } = React.useContext(MyContext);
|
||||
const setMyGroupsWhereIAmAdmin = useSetRecoilState(myGroupsWhereIAmAdminAtom);
|
||||
|
||||
const theme = useTheme();
|
||||
const getJoinRequests = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@ -244,7 +244,7 @@ export const GroupJoinRequests = ({
|
||||
<IconButton edge="end" aria-label="comments">
|
||||
<GroupAddIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
fontSize: '18px',
|
||||
}}
|
||||
/>
|
||||
|
@ -1,254 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Menu,
|
||||
MenuItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Box,
|
||||
} from '@mui/material';
|
||||
import { ArrowDownIcon } from '../../assets/Icons/ArrowDownIcon';
|
||||
import { NotificationIcon2 } from '../../assets/Icons/NotificationIcon2';
|
||||
import { ChatIcon } from '../../assets/Icons/ChatIcon';
|
||||
import { ThreadsIcon } from '../../assets/Icons/ThreadsIcon';
|
||||
import { MembersIcon } from '../../assets/Icons/MembersIcon';
|
||||
|
||||
export const GroupMenu = ({
|
||||
setGroupSection,
|
||||
groupSection,
|
||||
setOpenManageMembers,
|
||||
goToAnnouncements,
|
||||
goToChat,
|
||||
hasUnreadChat,
|
||||
hasUnreadAnnouncements,
|
||||
}) => {
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
const open = Boolean(anchorEl);
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
marginTop: '14px',
|
||||
marginBottom: '14px',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
aria-controls={open ? 'home-menu' : undefined}
|
||||
aria-haspopup="true"
|
||||
aria-expanded={open ? 'true' : undefined}
|
||||
onClick={handleClick}
|
||||
variant="contained"
|
||||
sx={{
|
||||
backgroundColor: 'var(--bg-primary)',
|
||||
width: '148px',
|
||||
borderRadius: '5px',
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
color: '#fff',
|
||||
textTransform: 'none',
|
||||
padding: '5px',
|
||||
height: '25px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '6px',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '6px',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{groupSection === 'announcement' && (
|
||||
<>
|
||||
{' '}
|
||||
<NotificationIcon2
|
||||
color={
|
||||
hasUnreadAnnouncements || hasUnreadChat
|
||||
? 'var(--danger)'
|
||||
: 'white'
|
||||
}
|
||||
/>{' '}
|
||||
{' Announcements'}
|
||||
</>
|
||||
)}
|
||||
{groupSection === 'chat' && (
|
||||
<>
|
||||
{' '}
|
||||
<ChatIcon
|
||||
color={
|
||||
hasUnreadAnnouncements || hasUnreadChat
|
||||
? 'var(--danger)'
|
||||
: 'white'
|
||||
}
|
||||
/>{' '}
|
||||
{' Group Chats'}
|
||||
</>
|
||||
)}
|
||||
{groupSection === 'forum' && (
|
||||
<>
|
||||
{' '}
|
||||
<ThreadsIcon
|
||||
color={
|
||||
hasUnreadAnnouncements || hasUnreadChat
|
||||
? 'var(--danger)'
|
||||
: 'white'
|
||||
}
|
||||
/>{' '}
|
||||
{' Threads'}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<ArrowDownIcon color="white" />
|
||||
</Box>
|
||||
</Button>
|
||||
|
||||
<Menu
|
||||
id="home-menu"
|
||||
anchorEl={anchorEl}
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
MenuListProps={{
|
||||
'aria-labelledby': 'basic-button',
|
||||
}}
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
backgroundColor: 'var(--bg-primary)',
|
||||
color: '#fff',
|
||||
width: '148px',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
},
|
||||
}}
|
||||
sx={{
|
||||
marginTop: '10px',
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
goToChat();
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: '24px !important',
|
||||
}}
|
||||
>
|
||||
<ChatIcon color={hasUnreadChat ? 'var(--danger)' : '#fff'} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
sx={{
|
||||
'& .MuiTypography-root': {
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
color: hasUnreadChat ? 'var(--danger)' : '#fff',
|
||||
},
|
||||
}}
|
||||
primary="Chat"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
goToAnnouncements();
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: '24px !important',
|
||||
}}
|
||||
>
|
||||
<NotificationIcon2
|
||||
color={hasUnreadAnnouncements ? 'var(--danger)' : '#fff'}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
sx={{
|
||||
'& .MuiTypography-root': {
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
color: hasUnreadAnnouncements ? 'var(--danger)' : '#fff',
|
||||
},
|
||||
}}
|
||||
primary="Announcements"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setGroupSection('forum');
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: '24px !important',
|
||||
}}
|
||||
>
|
||||
<ThreadsIcon color={'#fff'} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
sx={{
|
||||
'& .MuiTypography-root': {
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
},
|
||||
}}
|
||||
primary="Threads"
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setOpenManageMembers(true);
|
||||
handleClose();
|
||||
}}
|
||||
>
|
||||
<ListItemIcon
|
||||
sx={{
|
||||
minWidth: '24px !important',
|
||||
}}
|
||||
>
|
||||
<MembersIcon sx={{ color: '#fff' }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
sx={{
|
||||
'& .MuiTypography-root': {
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
},
|
||||
}}
|
||||
primary="Members"
|
||||
/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Box>
|
||||
);
|
||||
};
|
@ -242,27 +242,6 @@ export const HomeDesktop = ({
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Spacer height="26px" />
|
||||
|
||||
{/* <Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="outlined"
|
||||
startIcon={<RefreshIcon />}
|
||||
onClick={refreshHomeDataFunc}
|
||||
sx={{
|
||||
color: "white",
|
||||
}}
|
||||
>
|
||||
Refresh home data
|
||||
</Button>
|
||||
</Box> */}
|
||||
|
||||
<Spacer height="180px" />
|
||||
</Box>
|
||||
);
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
Select,
|
||||
TextField,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
@ -47,6 +48,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import ErrorBoundary from '../../common/ErrorBoundary';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
||||
import { getFee } from '../../background';
|
||||
export const requestQueuePromos = new RequestQueueWithPromise(20);
|
||||
|
||||
export function utf8ToBase64(inputString: string): string {
|
||||
@ -90,7 +92,7 @@ export const ListOfGroupPromotions = () => {
|
||||
const [isLoadingJoinGroup, setIsLoadingJoinGroup] = useState(false);
|
||||
const [isLoadingPublish, setIsLoadingPublish] = useState(false);
|
||||
const { show, setTxList } = useContext(MyContext);
|
||||
|
||||
const theme = useTheme();
|
||||
const listRef = useRef();
|
||||
const rowVirtualizer = useVirtualizer({
|
||||
count: promotions.length,
|
||||
@ -673,7 +675,7 @@ export const ListOfGroupPromotions = () => {
|
||||
<Avatar
|
||||
sx={{
|
||||
backgroundColor: '#27282c',
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
alt={promotion?.name}
|
||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
||||
@ -687,7 +689,6 @@ export const ListOfGroupPromotions = () => {
|
||||
sx={{
|
||||
fontWight: 600,
|
||||
fontFamily: 'Inter',
|
||||
color: 'cadetBlue',
|
||||
}}
|
||||
>
|
||||
{promotion?.name}
|
||||
@ -698,7 +699,6 @@ export const ListOfGroupPromotions = () => {
|
||||
sx={{
|
||||
fontWight: 600,
|
||||
fontFamily: 'Inter',
|
||||
color: 'cadetBlue',
|
||||
}}
|
||||
>
|
||||
{promotion?.groupName}
|
||||
@ -717,14 +717,14 @@ export const ListOfGroupPromotions = () => {
|
||||
{promotion?.isOpen === false && (
|
||||
<LockIcon
|
||||
sx={{
|
||||
color: 'var(--green)',
|
||||
color: theme.palette.other.positive,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{promotion?.isOpen === true && (
|
||||
<NoEncryptionGmailerrorredIcon
|
||||
sx={{
|
||||
color: 'var(--danger)',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@ -746,7 +746,6 @@ export const ListOfGroupPromotions = () => {
|
||||
sx={{
|
||||
fontWight: 600,
|
||||
fontFamily: 'Inter',
|
||||
color: 'cadetBlue',
|
||||
}}
|
||||
>
|
||||
{promotion?.data}
|
||||
@ -768,7 +767,7 @@ export const ListOfGroupPromotions = () => {
|
||||
}
|
||||
sx={{
|
||||
fontSize: '12px',
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
>
|
||||
Join Group: {` ${promotion?.groupName}`}
|
||||
@ -848,10 +847,10 @@ export const ListOfGroupPromotions = () => {
|
||||
multiline={true}
|
||||
sx={{
|
||||
'& .MuiFormLabel-root': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
'& .MuiFormLabel-root.Mui-focused': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
ListItemText,
|
||||
Popover,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { useRef, useState } from 'react';
|
||||
import {
|
||||
@ -39,7 +40,7 @@ const ListOfMembers = ({
|
||||
const [isLoadingBan, setIsLoadingBan] = useState(false);
|
||||
const [isLoadingMakeAdmin, setIsLoadingMakeAdmin] = useState(false);
|
||||
const [isLoadingRemoveAdmin, setIsLoadingRemoveAdmin] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const listRef = useRef();
|
||||
|
||||
const handlePopoverOpen = (event, index) => {
|
||||
@ -354,7 +355,7 @@ const ListOfMembers = ({
|
||||
{member?.isAdmin && (
|
||||
<Typography
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
marginLeft: 'auto',
|
||||
}}
|
||||
>
|
||||
|
@ -13,7 +13,7 @@ import { InviteMember } from './InviteMember';
|
||||
import { ListOfInvites } from './ListOfInvites';
|
||||
import { ListOfBans } from './ListOfBans';
|
||||
import { ListOfJoinRequests } from './ListOfJoinRequests';
|
||||
import { Box, ButtonBase, Card, Tab, Tabs } from '@mui/material';
|
||||
import { Box, ButtonBase, Card, Tab, Tabs, useTheme } from '@mui/material';
|
||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import { getGroupMembers, getNames } from './Group';
|
||||
@ -60,6 +60,7 @@ export const ManageMembers = ({
|
||||
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
const theme = useTheme();
|
||||
const { show, setTxList } = React.useContext(MyContext);
|
||||
|
||||
const handleClose = () => {
|
||||
@ -172,9 +173,14 @@ export const ManageMembers = ({
|
||||
onClose={handleClose}
|
||||
TransitionComponent={Transition}
|
||||
>
|
||||
<AppBar sx={{ position: 'relative', bgcolor: '#232428' }}>
|
||||
<AppBar
|
||||
sx={{
|
||||
position: 'relative',
|
||||
bgcolor: theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<Typography sx={{ ml: 2, flex: 1 }} variant="h6" component="div">
|
||||
<Typography sx={{ ml: 2, flex: 1 }} variant="h4" component="div">
|
||||
Manage Members
|
||||
</Typography>
|
||||
<IconButton
|
||||
@ -189,8 +195,8 @@ export const ManageMembers = ({
|
||||
</AppBar>
|
||||
<Box
|
||||
sx={{
|
||||
bgcolor: '#27282c',
|
||||
color: 'white',
|
||||
bgcolor: theme.palette.background.default,
|
||||
color: theme.palette.text.primary,
|
||||
flexGrow: 1,
|
||||
overflowY: 'auto',
|
||||
}}
|
||||
@ -205,7 +211,7 @@ export const ManageMembers = ({
|
||||
allowScrollButtonsMobile // Show scroll buttons on mobile as well
|
||||
sx={{
|
||||
'& .MuiTabs-indicator': {
|
||||
backgroundColor: 'white',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
maxWidth: '100%', // Ensure the tabs container fits within the available space
|
||||
overflow: 'hidden', // Prevents overflow on small screens
|
||||
@ -216,7 +222,7 @@ export const ManageMembers = ({
|
||||
{...a11yProps(0)}
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
@ -227,7 +233,7 @@ export const ManageMembers = ({
|
||||
{...a11yProps(1)}
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
@ -238,7 +244,7 @@ export const ManageMembers = ({
|
||||
{...a11yProps(2)}
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
@ -249,7 +255,7 @@ export const ManageMembers = ({
|
||||
{...a11yProps(3)}
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
@ -260,7 +266,7 @@ export const ManageMembers = ({
|
||||
{...a11yProps(4)}
|
||||
sx={{
|
||||
'&.Mui-selected': {
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
fontSize: '1rem',
|
||||
}}
|
||||
|
@ -153,7 +153,9 @@ export const QMailMessages = ({ userName, userAddress }) => {
|
||||
</Typography>
|
||||
<MarkEmailUnreadIcon
|
||||
sx={{
|
||||
color: anyUnread ? 'var(--unread)' : 'white',
|
||||
color: anyUnread
|
||||
? theme.palette.other.unread
|
||||
: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
{isExpanded ? (
|
||||
@ -165,7 +167,9 @@ export const QMailMessages = ({ userName, userAddress }) => {
|
||||
) : (
|
||||
<ExpandMoreIcon
|
||||
sx={{
|
||||
color: anyUnread ? 'var(--unread)' : 'white',
|
||||
color: anyUnread
|
||||
? theme.palette.other.unread
|
||||
: theme.palette.text.primary,
|
||||
marginLeft: 'auto',
|
||||
}}
|
||||
/>
|
||||
@ -262,26 +266,26 @@ export const QMailMessages = ({ userName, userAddress }) => {
|
||||
isLessThanOneWeekOld(mail?.created) ? (
|
||||
<MailIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
}}
|
||||
/>
|
||||
) : !lastEnteredTimestamp ? (
|
||||
<MailOutlineIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
) : lastEnteredTimestamp < mail?.created &&
|
||||
isLessThanOneWeekOld(mail?.created) ? (
|
||||
<MailIcon
|
||||
sx={{
|
||||
color: 'var(--unread)',
|
||||
color: theme.palette.other.unread,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<MailOutlineIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -1,4 +1,12 @@
|
||||
import { forwardRef, Fragment, ReactElement, Ref, useEffect } from 'react';
|
||||
import {
|
||||
ChangeEvent,
|
||||
forwardRef,
|
||||
Fragment,
|
||||
ReactElement,
|
||||
Ref,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import AppBar from '@mui/material/AppBar';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
@ -10,6 +18,7 @@ import { TransitionProps } from '@mui/material/transitions';
|
||||
import { Box, FormControlLabel, Switch, styled, useTheme } from '@mui/material';
|
||||
import { enabledDevModeAtom } from '../../atoms/global';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import ThemeManager from '../Theme/ThemeManager';
|
||||
|
||||
const LocalNodeSwitch = styled(Switch)(({ theme }) => ({
|
||||
padding: 8,
|
||||
@ -54,12 +63,12 @@ const Transition = forwardRef(function Transition(
|
||||
});
|
||||
|
||||
export const Settings = ({ address, open, setOpen }) => {
|
||||
const [checked, setChecked] = React.useState(false);
|
||||
const [checked, setChecked] = useState(false);
|
||||
const [isEnabledDevMode, setIsEnabledDevMode] =
|
||||
useRecoilState(enabledDevModeAtom);
|
||||
const theme = useTheme();
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
setChecked(event.target.checked);
|
||||
window
|
||||
.sendMessage('addUserSettings', {
|
||||
@ -123,9 +132,7 @@ export const Settings = ({ address, open, setOpen }) => {
|
||||
onClose={handleClose}
|
||||
TransitionComponent={Transition}
|
||||
>
|
||||
<AppBar
|
||||
sx={{ position: 'relative', bgcolor: theme.palette.background }}
|
||||
>
|
||||
<AppBar sx={{ position: 'relative' }}>
|
||||
<Toolbar>
|
||||
<Typography sx={{ ml: 2, flex: 1 }} variant="h4" component="div">
|
||||
General Settings
|
||||
@ -144,7 +151,6 @@ export const Settings = ({ address, open, setOpen }) => {
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
bgcolor: theme.palette.background,
|
||||
flexGrow: 1,
|
||||
overflowY: 'auto',
|
||||
color: theme.palette.text.primary,
|
||||
@ -165,9 +171,6 @@ export const Settings = ({ address, open, setOpen }) => {
|
||||
/>
|
||||
{window?.electronAPI && (
|
||||
<FormControlLabel
|
||||
sx={{
|
||||
color: 'white',
|
||||
}}
|
||||
control={
|
||||
<LocalNodeSwitch
|
||||
checked={isEnabledDevMode}
|
||||
@ -183,6 +186,7 @@ export const Settings = ({ address, open, setOpen }) => {
|
||||
label="Enable dev mode"
|
||||
/>
|
||||
)}
|
||||
<ThemeManager />
|
||||
</Box>
|
||||
</Dialog>
|
||||
</Fragment>
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
ListItemText,
|
||||
Popover,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { useContext, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
@ -54,7 +55,7 @@ export const UserListOfInvites = ({
|
||||
const { txList, setTxList, show } = useContext(MyContext);
|
||||
const [invites, setInvites] = useState<any[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const [popoverAnchor, setPopoverAnchor] = useState(null); // Track which list item the popover is anchored to
|
||||
const [openPopoverIndex, setOpenPopoverIndex] = useState(null); // Track which list item has the popover open
|
||||
const listRef = useRef();
|
||||
@ -205,14 +206,14 @@ export const UserListOfInvites = ({
|
||||
{invite?.isOpen === false && (
|
||||
<LockIcon
|
||||
sx={{
|
||||
color: 'var(--green)',
|
||||
color: theme.palette.other.positive,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{invite?.isOpen === true && (
|
||||
<NoEncryptionGmailerrorredIcon
|
||||
sx={{
|
||||
color: 'var(--danger)',
|
||||
color: theme.palette.other.danger,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, ButtonBase, Divider, Typography } from '@mui/material';
|
||||
import { Box, ButtonBase, Divider, Typography, useTheme } from '@mui/material';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import AppViewerContainer from '../Apps/AppViewerContainer';
|
||||
@ -25,7 +25,7 @@ export const WalletsAppWrapper = () => {
|
||||
service: 'APP',
|
||||
path: 'qortal?authOnMount=true',
|
||||
});
|
||||
|
||||
const theme = useTheme();
|
||||
const isDisableBackButton = useMemo(() => {
|
||||
if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack)
|
||||
return false;
|
||||
@ -62,7 +62,7 @@ export const WalletsAppWrapper = () => {
|
||||
position: 'fixed',
|
||||
height: '100vh',
|
||||
width: '100vw',
|
||||
backgroundColor: '#27282c', // TODO: set color theme
|
||||
backgroundColor: theme.palette.background.paper, // TODO: set color theme
|
||||
zIndex: 100,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
@ -92,7 +92,7 @@ export const WalletsAppWrapper = () => {
|
||||
<ButtonBase onClick={handleClose}>
|
||||
<CloseIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
@ -116,7 +116,7 @@ export const QortPrice = () => {
|
||||
>
|
||||
<Tooltip
|
||||
title={
|
||||
<span style={{ color: 'white', fontSize: '14px', fontWeight: 700 }}>
|
||||
<span style={{ fontSize: '14px', fontWeight: 700 }}>
|
||||
Based on the latest 20 trades
|
||||
</span>
|
||||
}
|
||||
@ -127,7 +127,7 @@ export const QortPrice = () => {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -156,7 +156,7 @@ export const QortPrice = () => {
|
||||
</Typography>
|
||||
|
||||
{!ltcPerQort ? (
|
||||
<BarSpinner width="16px" color="white" />
|
||||
<BarSpinner width="16px" color={theme.palette.text.primary} />
|
||||
) : (
|
||||
<Typography
|
||||
sx={{
|
||||
@ -187,7 +187,7 @@ export const QortPrice = () => {
|
||||
</Typography>
|
||||
|
||||
{!supply ? (
|
||||
<BarSpinner width="16px" color="white" />
|
||||
<BarSpinner width="16px" color={theme.palette.text.primary} />
|
||||
) : (
|
||||
<Typography
|
||||
sx={{
|
||||
@ -200,7 +200,7 @@ export const QortPrice = () => {
|
||||
</Box>
|
||||
<Tooltip
|
||||
title={
|
||||
<span style={{ color: 'white', fontSize: '14px', fontWeight: 700 }}>
|
||||
<span style={{ fontSize: '14px', fontWeight: 700 }}>
|
||||
{lastBlock?.timestamp && formatDate(lastBlock?.timestamp)}
|
||||
</span>
|
||||
}
|
||||
@ -211,7 +211,7 @@ export const QortPrice = () => {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -240,7 +240,7 @@ export const QortPrice = () => {
|
||||
</Typography>
|
||||
|
||||
{!lastBlock?.height ? (
|
||||
<BarSpinner width="16px" color="white" />
|
||||
<BarSpinner width="16px" color={theme.palette.text.primary} />
|
||||
) : (
|
||||
<Typography
|
||||
sx={{
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
ButtonBase,
|
||||
Popover,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { Spacer } from '../common/Spacer';
|
||||
import ImageUploader from '../common/ImageUploader';
|
||||
@ -222,6 +223,7 @@ const PopoverComp = ({
|
||||
isLoading,
|
||||
myName,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Popover
|
||||
id={id}
|
||||
@ -260,7 +262,7 @@ const PopoverComp = ({
|
||||
>
|
||||
<ErrorIcon
|
||||
sx={{
|
||||
color: 'white',
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>
|
||||
|
@ -638,14 +638,14 @@ export const Minting = ({
|
||||
}}
|
||||
disabled={mintingAccounts?.length > 1}
|
||||
sx={{
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: 'black',
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
maxWidth: '90%',
|
||||
width: '200px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
@ -702,14 +702,14 @@ export const Minting = ({
|
||||
<Button
|
||||
size="small"
|
||||
sx={{
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 'bold',
|
||||
maxWidth: '90%',
|
||||
opacity: 0.7,
|
||||
width: '200px',
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: theme.palette.text.primary,
|
||||
opacity: 1,
|
||||
},
|
||||
@ -763,13 +763,13 @@ export const Minting = ({
|
||||
<Button
|
||||
size="small"
|
||||
sx={{
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: theme.palette.text.primary,
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
|
@ -43,7 +43,7 @@ export const QMailStatus = () => {
|
||||
{hasNewMail && (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'var(--unread)',
|
||||
backgroundColor: theme.palette.other.unread,
|
||||
borderRadius: '50%',
|
||||
height: '15px',
|
||||
outline: '1px solid white',
|
||||
@ -77,7 +77,7 @@ export const QMailStatus = () => {
|
||||
tooltip: {
|
||||
sx: {
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
@ -87,7 +87,11 @@ export const QMailStatus = () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Mail />
|
||||
<Mail
|
||||
sx={{
|
||||
color: theme.palette.text.secondary,
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</ButtonBase>
|
||||
);
|
||||
|
@ -1,28 +1,29 @@
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
ButtonBase,
|
||||
Collapse,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Input,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
List,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Select,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
Avatar,
|
||||
Box,
|
||||
Button,
|
||||
ButtonBase,
|
||||
Collapse,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Input,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
List,
|
||||
MenuItem,
|
||||
Popover,
|
||||
Select,
|
||||
TextField,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { Label } from './Group/AddGroup';
|
||||
import { Spacer } from '../common/Spacer';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
@ -35,278 +36,313 @@ import CheckIcon from '@mui/icons-material/Check';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
|
||||
enum Availability {
|
||||
NULL = 'null',
|
||||
LOADING = 'loading',
|
||||
AVAILABLE = 'available',
|
||||
NOT_AVAILABLE = 'not-available'
|
||||
NULL = 'null',
|
||||
LOADING = 'loading',
|
||||
AVAILABLE = 'available',
|
||||
NOT_AVAILABLE = 'not-available',
|
||||
}
|
||||
export const RegisterName = ({setOpenSnack, setInfoSnack, userInfo, show, setTxList, balance}) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [registerNameValue, setRegisterNameValue] = useState('')
|
||||
const [isLoadingRegisterName, setIsLoadingRegisterName] = useState(false)
|
||||
const [isNameAvailable, setIsNameAvailable] = useState<Availability>(Availability.NULL)
|
||||
const [nameFee, setNameFee] = useState(null)
|
||||
export const RegisterName = ({
|
||||
setOpenSnack,
|
||||
setInfoSnack,
|
||||
userInfo,
|
||||
show,
|
||||
setTxList,
|
||||
balance,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [registerNameValue, setRegisterNameValue] = useState('');
|
||||
const [isLoadingRegisterName, setIsLoadingRegisterName] = useState(false);
|
||||
const [isNameAvailable, setIsNameAvailable] = useState<Availability>(
|
||||
Availability.NULL
|
||||
);
|
||||
const [nameFee, setNameFee] = useState(null);
|
||||
const theme = useTheme();
|
||||
const checkIfNameExisits = async (name) => {
|
||||
if (!name?.trim()) {
|
||||
setIsNameAvailable(Availability.NULL);
|
||||
|
||||
const checkIfNameExisits = async (name)=> {
|
||||
if(!name?.trim()){
|
||||
setIsNameAvailable(Availability.NULL)
|
||||
|
||||
return
|
||||
return;
|
||||
}
|
||||
setIsNameAvailable(Availability.LOADING)
|
||||
setIsNameAvailable(Availability.LOADING);
|
||||
try {
|
||||
const res = await fetch(`${getBaseApiReact()}/names/` + name);
|
||||
const data = await res.json()
|
||||
if(data?.message === 'name unknown'){
|
||||
setIsNameAvailable(Availability.AVAILABLE)
|
||||
} else {
|
||||
setIsNameAvailable(Availability.NOT_AVAILABLE)
|
||||
}
|
||||
const res = await fetch(`${getBaseApiReact()}/names/` + name);
|
||||
const data = await res.json();
|
||||
if (data?.message === 'name unknown') {
|
||||
setIsNameAvailable(Availability.AVAILABLE);
|
||||
} else {
|
||||
setIsNameAvailable(Availability.NOT_AVAILABLE);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
console.error(error);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
// Debounce logic
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
checkIfNameExisits(registerNameValue);
|
||||
}, 500);
|
||||
|
||||
// Cleanup timeout if searchValue changes before the timeout completes
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [registerNameValue]);
|
||||
};
|
||||
// Debounce logic
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
checkIfNameExisits(registerNameValue);
|
||||
}, 500);
|
||||
|
||||
const openRegisterNameFunc = useCallback((e) => {
|
||||
setIsOpen(true)
|
||||
// Cleanup timeout if searchValue changes before the timeout completes
|
||||
return () => {
|
||||
clearTimeout(handler);
|
||||
};
|
||||
}, [registerNameValue]);
|
||||
|
||||
}, [ setIsOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
subscribeToEvent("openRegisterName", openRegisterNameFunc);
|
||||
|
||||
return () => {
|
||||
unsubscribeFromEvent("openRegisterName", openRegisterNameFunc);
|
||||
};
|
||||
}, [openRegisterNameFunc]);
|
||||
const openRegisterNameFunc = useCallback(
|
||||
(e) => {
|
||||
setIsOpen(true);
|
||||
},
|
||||
[setIsOpen]
|
||||
);
|
||||
|
||||
useEffect(()=> {
|
||||
const nameRegistrationFee = async ()=> {
|
||||
try {
|
||||
const fee = await getFee("REGISTER_NAME");
|
||||
setNameFee(fee?.fee)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
nameRegistrationFee()
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
subscribeToEvent('openRegisterName', openRegisterNameFunc);
|
||||
|
||||
const registerName = async () => {
|
||||
return () => {
|
||||
unsubscribeFromEvent('openRegisterName', openRegisterNameFunc);
|
||||
};
|
||||
}, [openRegisterNameFunc]);
|
||||
|
||||
useEffect(() => {
|
||||
const nameRegistrationFee = async () => {
|
||||
try {
|
||||
if (!userInfo?.address) throw new Error("Your address was not found");
|
||||
if(!registerNameValue) throw new Error('Enter a name')
|
||||
|
||||
const fee = await getFee("REGISTER_NAME");
|
||||
await show({
|
||||
message: "Would you like to register this name?",
|
||||
publishFee: fee.fee + " QORT",
|
||||
});
|
||||
setIsLoadingRegisterName(true);
|
||||
new Promise((res, rej) => {
|
||||
window
|
||||
.sendMessage("registerName", {
|
||||
name: registerNameValue,
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response?.error) {
|
||||
res(response);
|
||||
setIsLoadingRegisterName(false);
|
||||
setInfoSnack({
|
||||
type: "success",
|
||||
message:
|
||||
"Successfully registered. It may take a couple of minutes for the changes to propagate",
|
||||
});
|
||||
setIsOpen(false);
|
||||
setRegisterNameValue("");
|
||||
setOpenSnack(true);
|
||||
setTxList((prev) => [
|
||||
{
|
||||
...response,
|
||||
type: "register-name",
|
||||
label: `Registered name: awaiting confirmation. This may take a couple minutes.`,
|
||||
labelDone: `Registered name: success!`,
|
||||
done: false,
|
||||
},
|
||||
...prev.filter((item) => !item.done),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
setInfoSnack({
|
||||
type: "error",
|
||||
message: response?.error,
|
||||
});
|
||||
setOpenSnack(true);
|
||||
rej(response.error);
|
||||
})
|
||||
.catch((error) => {
|
||||
setInfoSnack({
|
||||
type: "error",
|
||||
message: error.message || "An error occurred",
|
||||
});
|
||||
setOpenSnack(true);
|
||||
rej(error);
|
||||
});
|
||||
});
|
||||
const fee = await getFee('REGISTER_NAME');
|
||||
setNameFee(fee?.fee);
|
||||
} catch (error) {
|
||||
if (error?.message) {
|
||||
setOpenSnack(true)
|
||||
setInfoSnack({
|
||||
type: "error",
|
||||
message: error?.message,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
setIsLoadingRegisterName(false);
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
nameRegistrationFee();
|
||||
}, []);
|
||||
|
||||
const registerName = async () => {
|
||||
try {
|
||||
if (!userInfo?.address) throw new Error('Your address was not found');
|
||||
if (!registerNameValue) throw new Error('Enter a name');
|
||||
|
||||
const fee = await getFee('REGISTER_NAME');
|
||||
await show({
|
||||
message: 'Would you like to register this name?',
|
||||
publishFee: fee.fee + ' QORT',
|
||||
});
|
||||
setIsLoadingRegisterName(true);
|
||||
new Promise((res, rej) => {
|
||||
window
|
||||
.sendMessage('registerName', {
|
||||
name: registerNameValue,
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response?.error) {
|
||||
res(response);
|
||||
setIsLoadingRegisterName(false);
|
||||
setInfoSnack({
|
||||
type: 'success',
|
||||
message:
|
||||
'Successfully registered. It may take a couple of minutes for the changes to propagate',
|
||||
});
|
||||
setIsOpen(false);
|
||||
setRegisterNameValue('');
|
||||
setOpenSnack(true);
|
||||
setTxList((prev) => [
|
||||
{
|
||||
...response,
|
||||
type: 'register-name',
|
||||
label: `Registered name: awaiting confirmation. This may take a couple minutes.`,
|
||||
labelDone: `Registered name: success!`,
|
||||
done: false,
|
||||
},
|
||||
...prev.filter((item) => !item.done),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
setInfoSnack({
|
||||
type: 'error',
|
||||
message: response?.error,
|
||||
});
|
||||
setOpenSnack(true);
|
||||
rej(response.error);
|
||||
})
|
||||
.catch((error) => {
|
||||
setInfoSnack({
|
||||
type: 'error',
|
||||
message: error.message || 'An error occurred',
|
||||
});
|
||||
setOpenSnack(true);
|
||||
rej(error);
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
if (error?.message) {
|
||||
setOpenSnack(true);
|
||||
setInfoSnack({
|
||||
type: 'error',
|
||||
message: error?.message,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
setIsLoadingRegisterName(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{"Register name"}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box
|
||||
open={isOpen}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">{'Register name'}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box
|
||||
sx={{
|
||||
width: "400px",
|
||||
width: '400px',
|
||||
maxWidth: '90vw',
|
||||
height: "500px",
|
||||
height: '500px',
|
||||
maxHeight: '90vh',
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
gap: "10px",
|
||||
padding: "10px",
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: '10px',
|
||||
padding: '10px',
|
||||
}}
|
||||
>
|
||||
<Label>Choose a name</Label>
|
||||
<TextField
|
||||
autoComplete='off'
|
||||
autoFocus
|
||||
autoComplete="off"
|
||||
autoFocus
|
||||
onChange={(e) => setRegisterNameValue(e.target.value)}
|
||||
value={registerNameValue}
|
||||
placeholder="Choose a name"
|
||||
/>
|
||||
{(!balance || (nameFee && balance && balance < nameFee))&& (
|
||||
{(!balance || (nameFee && balance && balance < nameFee)) && (
|
||||
<>
|
||||
<Spacer height="10px" />
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
gap: '5px',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<ErrorIcon sx={{
|
||||
color: 'white'
|
||||
}} />
|
||||
<Typography>Your balance is {balance ?? 0} QORT. A name registration requires a {nameFee} QORT fee</Typography>
|
||||
</Box>
|
||||
<Spacer height="10px" />
|
||||
|
||||
<Spacer height="10px" />
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '5px',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<ErrorIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>
|
||||
Your balance is {balance ?? 0} QORT. A name registration
|
||||
requires a {nameFee} QORT fee
|
||||
</Typography>
|
||||
</Box>
|
||||
<Spacer height="10px" />
|
||||
</>
|
||||
)}
|
||||
<Spacer height="5px" />
|
||||
{isNameAvailable === Availability.AVAILABLE && (
|
||||
<Box sx={{
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '5px',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<CheckIcon sx={{
|
||||
color: 'white'
|
||||
}} />
|
||||
<Typography>{registerNameValue} is available</Typography>
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>{registerNameValue} is available</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{isNameAvailable === Availability.NOT_AVAILABLE && (
|
||||
<Box sx={{
|
||||
{isNameAvailable === Availability.NOT_AVAILABLE && (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '5px',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<ErrorIcon sx={{
|
||||
color: 'white'
|
||||
}} />
|
||||
<Typography>{registerNameValue} is unavailable</Typography>
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<ErrorIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
<Typography>{registerNameValue} is unavailable</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{isNameAvailable === Availability.LOADING && (
|
||||
<Box sx={{
|
||||
{isNameAvailable === Availability.LOADING && (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '5px',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<BarSpinner width="16px" color="white" />
|
||||
<Typography>Checking if name already existis</Typography>
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<BarSpinner width="16px" color={theme.palette.text.primary} />
|
||||
<Typography>Checking if name already existis</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Spacer height="25px" />
|
||||
<Typography sx={{
|
||||
textDecoration: 'underline'
|
||||
}}>Benefits of a name</Typography>
|
||||
<List
|
||||
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
|
||||
aria-label="contacts"
|
||||
>
|
||||
<ListItem disablePadding>
|
||||
|
||||
<ListItemIcon>
|
||||
<RadioButtonCheckedIcon sx={{
|
||||
color: 'white'
|
||||
}} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Publish data to Qortal: anything from apps to videos. Fully decentralized!" />
|
||||
|
||||
</ListItem>
|
||||
<ListItem disablePadding>
|
||||
|
||||
<ListItemIcon>
|
||||
<RadioButtonCheckedIcon sx={{
|
||||
color: 'white'
|
||||
}} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Secure ownership of data published by your name. You can even sell your name, along with your data to a third party." />
|
||||
|
||||
</ListItem>
|
||||
</List>
|
||||
<Typography
|
||||
sx={{
|
||||
textDecoration: 'underline',
|
||||
}}
|
||||
>
|
||||
Benefits of a name
|
||||
</Typography>
|
||||
<List
|
||||
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
|
||||
aria-label="contacts"
|
||||
>
|
||||
<ListItem disablePadding>
|
||||
<ListItemIcon>
|
||||
<RadioButtonCheckedIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Publish data to Qortal: anything from apps to videos. Fully decentralized!" />
|
||||
</ListItem>
|
||||
<ListItem disablePadding>
|
||||
<ListItemIcon>
|
||||
<RadioButtonCheckedIcon
|
||||
sx={{
|
||||
color: theme.palette.text.primary,
|
||||
}}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Secure ownership of data published by your name. You can even sell your name, along with your data to a third party." />
|
||||
</ListItem>
|
||||
</List>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
disabled={isLoadingRegisterName}
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setIsOpen(false)
|
||||
setRegisterNameValue('')
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!registerNameValue.trim() ||isLoadingRegisterName || isNameAvailable !== Availability.AVAILABLE || !balance || ((balance && nameFee) && +balance < +nameFee)}
|
||||
variant="contained"
|
||||
onClick={registerName}
|
||||
autoFocus
|
||||
>
|
||||
Register Name
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
disabled={isLoadingRegisterName}
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
setRegisterNameValue('');
|
||||
}}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
!registerNameValue.trim() ||
|
||||
isLoadingRegisterName ||
|
||||
isNameAvailable !== Availability.AVAILABLE ||
|
||||
!balance ||
|
||||
(balance && nameFee && +balance < +nameFee)
|
||||
}
|
||||
variant="contained"
|
||||
onClick={registerName}
|
||||
autoFocus
|
||||
>
|
||||
Register Name
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
@ -321,12 +321,12 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
|
||||
}}
|
||||
variant="contained"
|
||||
sx={{
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
@ -393,12 +393,12 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
|
||||
|
||||
<LoadingButton
|
||||
sx={{
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: 'black',
|
||||
opacity: 0.7,
|
||||
fontWeight: 'bold',
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--green)',
|
||||
backgroundColor: theme.palette.other.positive,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
@ -432,12 +432,12 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
|
||||
onClick={revertChanges}
|
||||
variant="contained"
|
||||
sx={{
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
@ -503,12 +503,12 @@ export const Save = ({ isDesktop, disableWidth, myName }) => {
|
||||
onClick={saveToQdn}
|
||||
variant="contained"
|
||||
sx={{
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
fontWeight: 'bold',
|
||||
opacity: 0.7,
|
||||
'&:hover': {
|
||||
backgroundColor: 'var(--danger)',
|
||||
backgroundColor: theme.palette.other.danger,
|
||||
color: 'black',
|
||||
opacity: 1,
|
||||
},
|
||||
|
@ -6,57 +6,129 @@ import {
|
||||
useEffect,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
|
||||
import { darkTheme } from '../../styles/theme-dark';
|
||||
import { lightTheme } from '../../styles/theme-light';
|
||||
import {
|
||||
ThemeProvider as MuiThemeProvider,
|
||||
createTheme,
|
||||
} from '@mui/material/styles';
|
||||
import { lightThemeOptions } from '../../styles/theme-light';
|
||||
import { darkThemeOptions } from '../../styles/theme-dark';
|
||||
|
||||
const defaultTheme = {
|
||||
id: 'default',
|
||||
name: 'Default Theme',
|
||||
light: lightThemeOptions.palette,
|
||||
dark: darkThemeOptions.palette,
|
||||
};
|
||||
|
||||
const ThemeContext = createContext({
|
||||
themeMode: 'light',
|
||||
toggleTheme: () => {},
|
||||
userThemes: [defaultTheme],
|
||||
addUserTheme: (themes) => {},
|
||||
setUserTheme: (theme) => {},
|
||||
currentThemeId: 'default',
|
||||
});
|
||||
|
||||
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
export const ThemeProvider = ({ children }) => {
|
||||
const [themeMode, setThemeMode] = useState('light');
|
||||
const [userThemes, setUserThemes] = useState([defaultTheme]);
|
||||
const [currentThemeId, setCurrentThemeId] = useState('default');
|
||||
|
||||
const theme = useMemo(
|
||||
() => (themeMode === 'light' ? lightTheme : darkTheme),
|
||||
[themeMode]
|
||||
);
|
||||
const currentTheme =
|
||||
userThemes.find((theme) => theme.id === currentThemeId) || defaultTheme;
|
||||
|
||||
const muiTheme = useMemo(() => {
|
||||
if (themeMode === 'light') {
|
||||
return createTheme({
|
||||
...lightThemeOptions,
|
||||
palette: {
|
||||
...currentTheme.light,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return createTheme({
|
||||
...lightThemeOptions,
|
||||
palette: {
|
||||
...currentTheme.dark,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [themeMode, currentTheme]);
|
||||
|
||||
const saveSettings = (
|
||||
themes = userThemes,
|
||||
mode = themeMode,
|
||||
themeId = currentThemeId
|
||||
) => {
|
||||
localStorage.setItem(
|
||||
'saved_ui_theme',
|
||||
JSON.stringify({
|
||||
mode,
|
||||
userThemes: themes,
|
||||
currentThemeId: themeId,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const toggleTheme = () => {
|
||||
setThemeMode((prevMode) => {
|
||||
const newMode = prevMode === 'light' ? 'dark' : 'light';
|
||||
|
||||
const themeProperties = {
|
||||
mode: newMode,
|
||||
};
|
||||
|
||||
localStorage.setItem('saved_ui_theme', JSON.stringify(themeProperties));
|
||||
|
||||
setThemeMode((prev) => {
|
||||
const newMode = prev === 'light' ? 'dark' : 'light';
|
||||
saveSettings(userThemes, newMode, currentThemeId);
|
||||
return newMode;
|
||||
});
|
||||
};
|
||||
|
||||
const getSavedTheme = useCallback(async () => {
|
||||
try {
|
||||
const themeProperties = JSON.parse(
|
||||
localStorage.getItem(`saved_ui_theme`) || '{}'
|
||||
);
|
||||
const addUserTheme = (themes) => {
|
||||
setUserThemes(themes);
|
||||
saveSettings(themes);
|
||||
};
|
||||
|
||||
const theme = themeProperties?.mode || 'light';
|
||||
setThemeMode(theme);
|
||||
} catch (error) {
|
||||
console.log('error', error);
|
||||
const setUserTheme = (theme) => {
|
||||
if (theme.id === 'default') {
|
||||
setCurrentThemeId('default');
|
||||
saveSettings(userThemes, themeMode, 'default');
|
||||
} else {
|
||||
setCurrentThemeId(theme.id);
|
||||
saveSettings(userThemes, themeMode, theme.id);
|
||||
}
|
||||
};
|
||||
|
||||
const loadSettings = useCallback(() => {
|
||||
const saved = localStorage.getItem('saved_ui_theme');
|
||||
if (saved) {
|
||||
try {
|
||||
const parsed = JSON.parse(saved);
|
||||
if (parsed.mode === 'light' || parsed.mode === 'dark')
|
||||
setThemeMode(parsed.mode);
|
||||
if (Array.isArray(parsed.userThemes)) {
|
||||
const filteredThemes = parsed.userThemes.filter(
|
||||
(theme) => theme.id !== 'default'
|
||||
);
|
||||
setUserThemes([defaultTheme, ...filteredThemes]);
|
||||
}
|
||||
if (parsed.currentThemeId) setCurrentThemeId(parsed.currentThemeId);
|
||||
} catch (error) {
|
||||
console.error('Failed to parse saved_ui_theme:', error);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getSavedTheme();
|
||||
}, [getSavedTheme]);
|
||||
loadSettings();
|
||||
}, [loadSettings]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ themeMode, toggleTheme }}>
|
||||
<MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>
|
||||
<ThemeContext.Provider
|
||||
value={{
|
||||
themeMode,
|
||||
toggleTheme,
|
||||
userThemes,
|
||||
addUserTheme,
|
||||
setUserTheme,
|
||||
currentThemeId,
|
||||
}}
|
||||
>
|
||||
<MuiThemeProvider theme={muiTheme}>{children}</MuiThemeProvider>
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
403
src/components/Theme/ThemeManager.tsx
Normal file
@ -0,0 +1,403 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
IconButton,
|
||||
Typography,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
List,
|
||||
ListItemText,
|
||||
ListItemSecondaryAction,
|
||||
TextField,
|
||||
Tabs,
|
||||
Tab,
|
||||
ListItemButton,
|
||||
} from '@mui/material';
|
||||
import { Sketch } from '@uiw/react-color';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import { useThemeContext } from './ThemeContext';
|
||||
import { darkThemeOptions } from '../../styles/theme-dark';
|
||||
import { lightThemeOptions } from '../../styles/theme-light';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import { rgbStringToHsva, rgbaStringToHsva } from '@uiw/color-convert';
|
||||
import FileDownloadIcon from '@mui/icons-material/FileDownload';
|
||||
import { saveFileToDiskGeneric } from '../../utils/generateWallet/generateWallet';
|
||||
import { handleImportClick } from '../../utils/fileReading';
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
function detectColorFormat(color) {
|
||||
if (typeof color !== 'string') return null;
|
||||
if (color.startsWith('rgba')) return 'rgba';
|
||||
if (color.startsWith('rgb')) return 'rgb';
|
||||
return null;
|
||||
}
|
||||
|
||||
const validateTheme = (theme) => {
|
||||
if (typeof theme !== 'object' || !theme) return false;
|
||||
if (typeof theme.name !== 'string') return false;
|
||||
if (!theme.light || typeof theme.light !== 'object') return false;
|
||||
if (!theme.dark || typeof theme.dark !== 'object') return false;
|
||||
|
||||
// Optional: deeper checks on structure
|
||||
const requiredKeys = [
|
||||
'primary',
|
||||
'secondary',
|
||||
'background',
|
||||
'text',
|
||||
'border',
|
||||
'other',
|
||||
];
|
||||
|
||||
for (const mode of ['light', 'dark']) {
|
||||
const modeTheme = theme[mode];
|
||||
if (modeTheme.mode !== mode) return false;
|
||||
|
||||
for (const key of requiredKeys) {
|
||||
if (!modeTheme[key] || typeof modeTheme[key] !== 'object') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export default function ThemeManager() {
|
||||
const { userThemes, addUserTheme, setUserTheme, currentThemeId } =
|
||||
useThemeContext();
|
||||
const [openEditor, setOpenEditor] = useState(false);
|
||||
const [themeDraft, setThemeDraft] = useState({
|
||||
id: '',
|
||||
name: '',
|
||||
light: {},
|
||||
dark: {},
|
||||
});
|
||||
const [currentTab, setCurrentTab] = useState('light');
|
||||
const nameInputRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (openEditor && nameInputRef.current) {
|
||||
nameInputRef.current.focus();
|
||||
}
|
||||
}, [openEditor]);
|
||||
|
||||
const handleAddTheme = () => {
|
||||
setThemeDraft({
|
||||
id: '',
|
||||
name: '',
|
||||
light: structuredClone(lightThemeOptions.palette),
|
||||
dark: structuredClone(darkThemeOptions.palette),
|
||||
});
|
||||
setOpenEditor(true);
|
||||
};
|
||||
|
||||
const handleEditTheme = (themeId) => {
|
||||
const themeToEdit = userThemes.find((theme) => theme.id === themeId);
|
||||
if (themeToEdit) {
|
||||
setThemeDraft({ ...themeToEdit });
|
||||
setOpenEditor(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveTheme = () => {
|
||||
if (themeDraft.id) {
|
||||
const updatedThemes = [...userThemes];
|
||||
const index = updatedThemes.findIndex(
|
||||
(theme) => theme.id === themeDraft.id
|
||||
);
|
||||
if (index !== -1) {
|
||||
updatedThemes[index] = themeDraft;
|
||||
addUserTheme(updatedThemes);
|
||||
}
|
||||
} else {
|
||||
const newTheme = { ...themeDraft, id: uid.rnd() };
|
||||
const updatedThemes = [...userThemes, newTheme];
|
||||
addUserTheme(updatedThemes);
|
||||
setUserTheme(newTheme);
|
||||
}
|
||||
setOpenEditor(false);
|
||||
};
|
||||
|
||||
const handleDeleteTheme = (id) => {
|
||||
const updatedThemes = userThemes.filter((theme) => theme.id !== id);
|
||||
addUserTheme(updatedThemes);
|
||||
|
||||
if (id === currentThemeId) {
|
||||
// Find the default theme object in the list
|
||||
const defaultTheme = updatedThemes.find(
|
||||
(theme) => theme.id === 'default'
|
||||
);
|
||||
|
||||
if (defaultTheme) {
|
||||
setUserTheme(defaultTheme);
|
||||
} else {
|
||||
// Emergency fallback
|
||||
setUserTheme({
|
||||
light: lightThemeOptions,
|
||||
dark: darkThemeOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleApplyTheme = (theme) => {
|
||||
setUserTheme(theme);
|
||||
};
|
||||
|
||||
const handleColorChange = (mode, fieldPath, color) => {
|
||||
setThemeDraft((prev) => {
|
||||
const updated = { ...prev };
|
||||
const paths = fieldPath.split('.');
|
||||
updated[mode][paths[0]][paths[1]] = color.hex;
|
||||
return updated;
|
||||
});
|
||||
};
|
||||
|
||||
const renderColorPicker = (mode, label, fieldPath, currentValue) => {
|
||||
let color = currentValue || '#ffffff';
|
||||
const format = detectColorFormat(currentValue);
|
||||
if (format === 'rgba') {
|
||||
color = rgbaStringToHsva(currentValue);
|
||||
} else if (format === 'rgb') {
|
||||
color = rgbStringToHsva(currentValue);
|
||||
}
|
||||
return (
|
||||
<Box
|
||||
mb={2}
|
||||
{...{ 'data-color-mode': mode === 'dark' ? 'dark' : 'light' }}
|
||||
>
|
||||
<Typography variant="body2" mb={1}>
|
||||
{label}
|
||||
</Typography>
|
||||
<Sketch
|
||||
key={`${mode}-${fieldPath}`}
|
||||
color={color}
|
||||
onChange={(color) => handleColorChange(mode, fieldPath, color)}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const exportTheme = async (theme) => {
|
||||
try {
|
||||
const copyTheme = structuredClone(theme);
|
||||
delete copyTheme.id;
|
||||
const fileName = `ui_theme_${theme.name}.json`;
|
||||
|
||||
const blob = new Blob([JSON.stringify(copyTheme, null, 2)], {
|
||||
type: 'application/json',
|
||||
});
|
||||
|
||||
await saveFileToDiskGeneric(blob, fileName);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const importTheme = async (theme) => {
|
||||
try {
|
||||
const fileContent = await handleImportClick('.json');
|
||||
const importedTheme = JSON.parse(fileContent);
|
||||
if (!validateTheme(importedTheme)) {
|
||||
throw new Error('Invalid theme format');
|
||||
}
|
||||
const newTheme = { ...importedTheme, id: uid.rnd() };
|
||||
const updatedThemes = [...userThemes, newTheme];
|
||||
addUserTheme(updatedThemes);
|
||||
setUserTheme(newTheme);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box p={2}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
Theme Manager
|
||||
</Typography>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
startIcon={<AddIcon />}
|
||||
onClick={handleAddTheme}
|
||||
>
|
||||
Add Theme
|
||||
</Button>
|
||||
<Button
|
||||
sx={{
|
||||
marginLeft: '20px',
|
||||
}}
|
||||
variant="contained"
|
||||
startIcon={<AddIcon />}
|
||||
onClick={importTheme}
|
||||
>
|
||||
Import theme
|
||||
</Button>
|
||||
<List>
|
||||
{userThemes?.map((theme, index) => (
|
||||
<ListItemButton
|
||||
key={theme?.id || index}
|
||||
selected={theme?.id === currentThemeId}
|
||||
>
|
||||
<ListItemText
|
||||
primary={`${theme?.name || `Theme ${index + 1}`} ${theme?.id === currentThemeId ? '(Current)' : ''}`}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
{theme.id !== 'default' && (
|
||||
<>
|
||||
<IconButton onClick={() => exportTheme(theme)}>
|
||||
<FileDownloadIcon />
|
||||
</IconButton>
|
||||
<IconButton onClick={() => handleEditTheme(theme.id)}>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
<IconButton onClick={() => handleDeleteTheme(theme.id)}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
<IconButton onClick={() => handleApplyTheme(theme)}>
|
||||
<CheckIcon />
|
||||
</IconButton>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
))}
|
||||
</List>
|
||||
|
||||
<Dialog
|
||||
open={openEditor}
|
||||
onClose={() => setOpenEditor(false)}
|
||||
fullWidth
|
||||
maxWidth="md"
|
||||
>
|
||||
<DialogTitle>
|
||||
{themeDraft.id ? 'Edit Theme' : 'Add New Theme'}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
inputRef={nameInputRef}
|
||||
margin="dense"
|
||||
label="Theme Name"
|
||||
fullWidth
|
||||
value={themeDraft.name}
|
||||
onChange={(e) =>
|
||||
setThemeDraft((prev) => ({ ...prev, name: e.target.value }))
|
||||
}
|
||||
/>
|
||||
|
||||
<Tabs
|
||||
value={currentTab}
|
||||
onChange={(e, newValue) => setCurrentTab(newValue)}
|
||||
sx={{ mt: 2, mb: 2 }}
|
||||
>
|
||||
<Tab label="Light" value="light" />
|
||||
<Tab label="Dark" value="dark" />
|
||||
</Tabs>
|
||||
|
||||
<Box>
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Primary Main',
|
||||
'primary.main',
|
||||
themeDraft[currentTab]?.primary?.main
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Primary Dark',
|
||||
'primary.dark',
|
||||
themeDraft[currentTab]?.primary?.dark
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Primary Light',
|
||||
'primary.light',
|
||||
themeDraft[currentTab]?.primary?.light
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Secondary Main',
|
||||
'secondary.main',
|
||||
themeDraft[currentTab]?.secondary?.main
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Background Default',
|
||||
'background.default',
|
||||
themeDraft[currentTab]?.background?.default
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Background Paper',
|
||||
'background.paper',
|
||||
themeDraft[currentTab]?.background?.paper
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Background Surface',
|
||||
'background.surface',
|
||||
themeDraft[currentTab]?.background?.surface
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Text Primary',
|
||||
'text.primary',
|
||||
themeDraft[currentTab]?.text?.primary
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Text Secondary',
|
||||
'text.secondary',
|
||||
themeDraft[currentTab]?.text?.secondary
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Border Main',
|
||||
'border.main',
|
||||
themeDraft[currentTab]?.border?.main
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Border Subtle',
|
||||
'border.subtle',
|
||||
themeDraft[currentTab]?.border?.subtle
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Positive',
|
||||
'other.positive',
|
||||
themeDraft[currentTab]?.other?.positive
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Danger',
|
||||
'other.danger',
|
||||
themeDraft[currentTab]?.other?.danger
|
||||
)}
|
||||
{renderColorPicker(
|
||||
currentTab,
|
||||
'Unread',
|
||||
'other.unread',
|
||||
themeDraft[currentTab]?.other?.unread
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setOpenEditor(false)}>Cancel</Button>
|
||||
<Button
|
||||
disabled={!themeDraft.name}
|
||||
onClick={handleSaveTheme}
|
||||
variant="contained"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Box>
|
||||
);
|
||||
}
|
39
src/components/Theme/themeManager.css
Normal file
@ -0,0 +1,39 @@
|
||||
[data-color-mode*='dark'] .w-color-sketch {
|
||||
--sketch-background: #323232 !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-swatch {
|
||||
--sketch-swatch-border-top: 1px solid #525252 !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-block {
|
||||
--block-background-color: #323232 !important;
|
||||
--block-box-shadow: rgb(0 0 0 / 10%) 0 1px !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-editable-input {
|
||||
--editable-input-label-color: #757575 !important;
|
||||
--editable-input-box-shadow: #616161 0px 0px 0px 1px inset !important;
|
||||
--editable-input-color: #bbb !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-github {
|
||||
--github-border: 1px solid rgba(0, 0, 0, 0.2) !important;
|
||||
--github-background-color: #323232 !important;
|
||||
--github-box-shadow: rgb(0 0 0 / 15%) 0px 3px 12px !important;
|
||||
--github-arrow-border-color: rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-compact {
|
||||
--compact-background-color: #323232 !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-material {
|
||||
--material-background-color: #323232 !important;
|
||||
--material-border-bottom-color: #707070 !important;
|
||||
}
|
||||
|
||||
[data-color-mode*='dark'] .w-color-alpha {
|
||||
--alpha-pointer-background-color: #6a6a6a !important;
|
||||
--alpha-pointer-box-shadow: rgb(0 0 0 / 37%) 0px 1px 4px 0px !important;
|
||||
}
|
@ -54,7 +54,6 @@ export const AuthenticatedContainerInnerTop = styled(Box)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export const TextP = styled(Typography)(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.default,
|
||||
color: theme.palette.text.primary,
|
||||
fontFamily: 'Inter',
|
||||
fontSize: '13px',
|
||||
@ -62,7 +61,6 @@ export const TextP = styled(Typography)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export const TextItalic = styled('span')(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.default,
|
||||
color: theme.palette.text.primary,
|
||||
fontFamily: 'Inter',
|
||||
fontSize: '13px',
|
||||
@ -71,7 +69,6 @@ export const TextItalic = styled('span')(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export const TextSpan = styled('span')(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.default,
|
||||
color: theme.palette.text.primary,
|
||||
fontFamily: 'Inter',
|
||||
fontSize: '13px',
|
||||
@ -131,9 +128,8 @@ export const CustomButton = styled(Box)(({ theme }) => ({
|
||||
width: 'fit-content',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
color: theme.palette.text.secondary,
|
||||
'svg path': {
|
||||
fill: theme.palette.background.paper,
|
||||
fill: theme.palette.background.secondary,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
@ -1,26 +1,36 @@
|
||||
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||
import { commonThemeOptions } from './theme-common';
|
||||
|
||||
const darkThemeOptions: ThemeOptions = {
|
||||
export const darkThemeOptions: ThemeOptions = {
|
||||
...commonThemeOptions,
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
primary: {
|
||||
main: 'rgb(46, 61, 96)',
|
||||
dark: 'rgb(5, 20, 53)',
|
||||
light: 'rgb(45, 92, 201)',
|
||||
main: 'rgb(100, 155, 240)',
|
||||
dark: 'rgb(45, 92, 201)',
|
||||
light: 'rgb(130, 185, 255)',
|
||||
},
|
||||
secondary: {
|
||||
main: 'rgb(69, 173, 255)',
|
||||
},
|
||||
background: {
|
||||
default: 'rgb(49, 51, 56)',
|
||||
paper: 'rgb(96, 96, 97)',
|
||||
paper: 'rgb(62, 64, 68)',
|
||||
surface: 'rgb(58, 60, 65)',
|
||||
},
|
||||
text: {
|
||||
primary: 'rgb(255, 255, 255)',
|
||||
secondary: 'rgb(179, 179, 179)',
|
||||
},
|
||||
border: {
|
||||
main: 'rgba(255, 255, 255, 0.12)',
|
||||
subtle: 'rgba(255, 255, 255, 0.08)',
|
||||
},
|
||||
other: {
|
||||
positive: 'rgb(94, 176, 73)',
|
||||
danger: 'rgb(177, 70, 70)',
|
||||
unread: 'rgb(66, 151, 226)',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiCard: {
|
||||
@ -76,6 +86,20 @@ const darkThemeOptions: ThemeOptions = {
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDialog: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
backgroundImage: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPopover: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
backgroundImage: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,25 +1,35 @@
|
||||
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||
import { commonThemeOptions } from './theme-common';
|
||||
|
||||
const lightThemeOptions: ThemeOptions = {
|
||||
export const lightThemeOptions: ThemeOptions = {
|
||||
...commonThemeOptions,
|
||||
palette: {
|
||||
mode: 'light',
|
||||
primary: {
|
||||
main: 'rgba(244, 244, 251, 1)',
|
||||
main: 'rgb(162, 162, 221)', // old light becomes main
|
||||
dark: 'rgb(113, 198, 212)',
|
||||
light: 'rgb(162, 162, 221)',
|
||||
light: 'rgba(244, 244, 251, 1)', // former main becomes light
|
||||
},
|
||||
secondary: {
|
||||
main: 'rgba(194, 222, 236, 1)',
|
||||
},
|
||||
background: {
|
||||
default: 'rgba(250, 250, 250, 1)',
|
||||
paper: 'rgb(228, 228, 228)',
|
||||
paper: 'rgb(220, 220, 220)', // darker card background
|
||||
surface: 'rgb(240, 240, 240)', // optional middle gray for replies, side panels
|
||||
},
|
||||
text: {
|
||||
primary: 'rgba(0, 0, 0, 1)',
|
||||
secondary: 'rgba(82, 82, 82, 1)',
|
||||
primary: 'rgba(0, 0, 0, 0.87)', // 87% black (slightly softened)
|
||||
secondary: 'rgba(0, 0, 0, 0.6)', // 60% black
|
||||
},
|
||||
border: {
|
||||
main: 'rgba(0, 0, 0, 0.12)',
|
||||
subtle: 'rgba(0, 0, 0, 0.08)',
|
||||
},
|
||||
other: {
|
||||
positive: 'rgb(94, 176, 73)',
|
||||
danger: 'rgb(177, 70, 70)',
|
||||
unread: 'rgb(66, 151, 226)',
|
||||
},
|
||||
},
|
||||
components: {
|
||||
@ -77,6 +87,20 @@ const lightThemeOptions: ThemeOptions = {
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiDialog: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
backgroundImage: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPopover: {
|
||||
styleOverrides: {
|
||||
paper: {
|
||||
backgroundImage: 'none',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
29
src/styles/theme.d.ts
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
import '@mui/material/styles';
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface TypeBackground {
|
||||
surface: string;
|
||||
}
|
||||
interface Palette {
|
||||
border: {
|
||||
main: string;
|
||||
subtle: string;
|
||||
};
|
||||
other: {
|
||||
positive: string;
|
||||
danger: string;
|
||||
unread: string;
|
||||
};
|
||||
}
|
||||
interface PaletteOptions {
|
||||
border?: {
|
||||
main?: string;
|
||||
subtle?: string;
|
||||
};
|
||||
other?: {
|
||||
positive?: string;
|
||||
danger?: string;
|
||||
unread?: string;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,63 +1,93 @@
|
||||
// @ts-nocheck
|
||||
|
||||
class Semaphore {
|
||||
constructor(count) {
|
||||
this.count = count
|
||||
this.waiting = []
|
||||
}
|
||||
acquire() {
|
||||
return new Promise(resolve => {
|
||||
if (this.count > 0) {
|
||||
this.count--
|
||||
resolve()
|
||||
} else {
|
||||
this.waiting.push(resolve)
|
||||
}
|
||||
})
|
||||
}
|
||||
release() {
|
||||
if (this.waiting.length > 0) {
|
||||
const resolve = this.waiting.shift()
|
||||
resolve()
|
||||
} else {
|
||||
this.count++
|
||||
}
|
||||
}
|
||||
constructor(count) {
|
||||
this.count = count;
|
||||
this.waiting = [];
|
||||
}
|
||||
acquire() {
|
||||
return new Promise((resolve) => {
|
||||
if (this.count > 0) {
|
||||
this.count--;
|
||||
resolve();
|
||||
} else {
|
||||
this.waiting.push(resolve);
|
||||
}
|
||||
});
|
||||
}
|
||||
release() {
|
||||
if (this.waiting.length > 0) {
|
||||
const resolve = this.waiting.shift();
|
||||
resolve();
|
||||
} else {
|
||||
this.count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let semaphore = new Semaphore(1)
|
||||
let reader = new FileReader()
|
||||
let semaphore = new Semaphore(1);
|
||||
let reader = new FileReader();
|
||||
|
||||
export const fileToBase64 = (file) => new Promise(async (resolve, reject) => {
|
||||
const reader = new FileReader(); // Create a new instance
|
||||
await semaphore.acquire();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => {
|
||||
const dataUrl = reader.result;
|
||||
semaphore.release();
|
||||
if (typeof dataUrl === 'string') {
|
||||
resolve(dataUrl.split(',')[1]);
|
||||
} else {
|
||||
reject(new Error('Invalid data URL'));
|
||||
}
|
||||
reader.onload = null; // Clear the handler
|
||||
reader.onerror = null; // Clear the handle
|
||||
};
|
||||
reader.onerror = (error) => {
|
||||
semaphore.release();
|
||||
reject(error);
|
||||
reader.onload = null; // Clear the handler
|
||||
reader.onerror = null; // Clear the handle
|
||||
};
|
||||
export const fileToBase64 = (file) =>
|
||||
new Promise(async (resolve, reject) => {
|
||||
const reader = new FileReader(); // Create a new instance
|
||||
await semaphore.acquire();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = () => {
|
||||
const dataUrl = reader.result;
|
||||
semaphore.release();
|
||||
if (typeof dataUrl === 'string') {
|
||||
resolve(dataUrl.split(',')[1]);
|
||||
} else {
|
||||
reject(new Error('Invalid data URL'));
|
||||
}
|
||||
reader.onload = null; // Clear the handler
|
||||
reader.onerror = null; // Clear the handle
|
||||
};
|
||||
reader.onerror = (error) => {
|
||||
semaphore.release();
|
||||
reject(error);
|
||||
reader.onload = null; // Clear the handler
|
||||
reader.onerror = null; // Clear the handle
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
export const base64ToBlobUrl = (base64, mimeType = "image/png") => {
|
||||
const binary = atob(base64);
|
||||
const array = [];
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
array.push(binary.charCodeAt(i));
|
||||
}
|
||||
const blob = new Blob([new Uint8Array(array)], { type: mimeType });
|
||||
return URL.createObjectURL(blob);
|
||||
};
|
||||
export const base64ToBlobUrl = (base64, mimeType = 'image/png') => {
|
||||
const binary = atob(base64);
|
||||
const array = [];
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
array.push(binary.charCodeAt(i));
|
||||
}
|
||||
const blob = new Blob([new Uint8Array(array)], { type: mimeType });
|
||||
return URL.createObjectURL(blob);
|
||||
};
|
||||
|
||||
export const handleImportClick = async (fileTypes) => {
|
||||
const fileInput = document.createElement('input');
|
||||
fileInput.type = 'file';
|
||||
fileInput.accept = fileTypes;
|
||||
|
||||
// Create a promise to handle file selection and reading synchronously
|
||||
return await new Promise((resolve, reject) => {
|
||||
fileInput.onchange = () => {
|
||||
const file = fileInput.files[0];
|
||||
if (!file) {
|
||||
reject(new Error('No file selected'));
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
resolve(e.target.result); // Resolve with the file content
|
||||
};
|
||||
reader.onerror = () => {
|
||||
reject(new Error('Error reading file'));
|
||||
};
|
||||
|
||||
reader.readAsText(file); // Read the file as text (Base64 string)
|
||||
};
|
||||
|
||||
// Trigger the file input dialog
|
||||
fileInput.click();
|
||||
});
|
||||
};
|
||||
|