mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-29 14:16:36 +00:00
Resize modal to show content appropriately
Change-type: patch Changelog-entry: Resize modal to show content appropriately Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
This commit is contained in:
parent
5c5273bd6c
commit
630f6c691c
@ -120,10 +120,6 @@ export function SettingsModal({ toggleModal }: SettingsModalProps) {
|
||||
</Txt>
|
||||
}
|
||||
done={() => toggleModal(false)}
|
||||
style={{
|
||||
width: 780,
|
||||
height: 420,
|
||||
}}
|
||||
>
|
||||
<Flex flexDirection="column">
|
||||
{_.map(settingsList, (setting: Setting, i: number) => {
|
||||
|
@ -52,6 +52,7 @@ import {
|
||||
Modal,
|
||||
StepButton,
|
||||
StepNameButton,
|
||||
ScrollableFlex,
|
||||
} from '../../styled-components';
|
||||
import { colors } from '../../theme';
|
||||
import { middleEllipsis } from '../../utils/middle-ellipsis';
|
||||
@ -61,19 +62,24 @@ import ImageSvg from '../../../assets/image.svg';
|
||||
|
||||
const recentUrlImagesKey = 'recentUrlImages';
|
||||
|
||||
function normalizeRecentUrlImages(urls: any): string[] {
|
||||
function normalizeRecentUrlImages(urls: any[]): URL[] {
|
||||
if (!Array.isArray(urls)) {
|
||||
urls = [];
|
||||
}
|
||||
return _.chain(urls)
|
||||
.filter(_.isString)
|
||||
.reject(_.isEmpty)
|
||||
.uniq()
|
||||
.takeRight(5)
|
||||
.value();
|
||||
urls = urls
|
||||
.map((url) => {
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch (error) {
|
||||
// Invalid URL, skip
|
||||
}
|
||||
})
|
||||
.filter((url) => url !== undefined);
|
||||
urls = _.uniqBy(urls, (url) => url.href);
|
||||
return urls.slice(urls.length - 5);
|
||||
}
|
||||
|
||||
function getRecentUrlImages(): string[] {
|
||||
function getRecentUrlImages(): URL[] {
|
||||
let urls = [];
|
||||
try {
|
||||
urls = JSON.parse(localStorage.getItem(recentUrlImagesKey) || '[]');
|
||||
@ -83,11 +89,9 @@ function getRecentUrlImages(): string[] {
|
||||
return normalizeRecentUrlImages(urls);
|
||||
}
|
||||
|
||||
function setRecentUrlImages(urls: string[]) {
|
||||
localStorage.setItem(
|
||||
recentUrlImagesKey,
|
||||
JSON.stringify(normalizeRecentUrlImages(urls)),
|
||||
);
|
||||
function setRecentUrlImages(urls: URL[]) {
|
||||
const normalized = normalizeRecentUrlImages(urls.map((url: URL) => url.href));
|
||||
localStorage.setItem(recentUrlImagesKey, JSON.stringify(normalized));
|
||||
}
|
||||
|
||||
const Card = styled(BaseCard)`
|
||||
@ -124,13 +128,13 @@ const URLSelector = ({
|
||||
}) => {
|
||||
const [imageURL, setImageURL] = React.useState('');
|
||||
const [recentImages, setRecentImages]: [
|
||||
string[],
|
||||
(value: React.SetStateAction<string[]>) => void,
|
||||
URL[],
|
||||
(value: React.SetStateAction<URL[]>) => void,
|
||||
] = React.useState([]);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
React.useEffect(() => {
|
||||
const fetchRecentUrlImages = async () => {
|
||||
const recentUrlImages: string[] = await getRecentUrlImages();
|
||||
const recentUrlImages: URL[] = await getRecentUrlImages();
|
||||
setRecentImages(recentUrlImages);
|
||||
};
|
||||
fetchRecentUrlImages();
|
||||
@ -139,15 +143,16 @@ const URLSelector = ({
|
||||
<Modal
|
||||
cancel={cancel}
|
||||
primaryButtonProps={{
|
||||
disabled: loading || !imageURL,
|
||||
className: loading || !imageURL ? 'disabled' : '',
|
||||
}}
|
||||
done={async () => {
|
||||
setLoading(true);
|
||||
const sanitizedRecentUrls = normalizeRecentUrlImages([
|
||||
...recentImages,
|
||||
const urlStrings = recentImages.map((url: URL) => url.href);
|
||||
const normalizedRecentUrls = normalizeRecentUrlImages([
|
||||
...urlStrings,
|
||||
imageURL,
|
||||
]);
|
||||
setRecentUrlImages(sanitizedRecentUrls);
|
||||
setRecentUrlImages(normalizedRecentUrls);
|
||||
await done(imageURL);
|
||||
}}
|
||||
>
|
||||
@ -164,24 +169,29 @@ const URLSelector = ({
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
{!_.isEmpty(recentImages) && (
|
||||
<Flex flexDirection="column">
|
||||
{recentImages.length > 0 && (
|
||||
<Flex flexDirection="column" height="78.6%">
|
||||
<Txt fontSize={18}>Recent</Txt>
|
||||
<Card
|
||||
style={{ padding: '10px 15px' }}
|
||||
rows={_.map(recentImages, (recent) => (
|
||||
<Txt
|
||||
key={recent}
|
||||
onClick={() => {
|
||||
setImageURL(recent);
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
{_.last(_.split(recent, '/'))} - {recent}
|
||||
</span>
|
||||
</Txt>
|
||||
))}
|
||||
/>
|
||||
<ScrollableFlex flexDirection="column">
|
||||
<Card
|
||||
p="10px 15px"
|
||||
rows={recentImages
|
||||
.map((recent) => (
|
||||
<Txt
|
||||
key={recent.href}
|
||||
onClick={() => {
|
||||
setImageURL(recent.href);
|
||||
}}
|
||||
style={{
|
||||
overflowWrap: 'break-word',
|
||||
}}
|
||||
>
|
||||
{recent.pathname.split('/').pop()} - {recent.href}
|
||||
</Txt>
|
||||
))
|
||||
.reverse()}
|
||||
/>
|
||||
</ScrollableFlex>
|
||||
</Flex>
|
||||
)}
|
||||
</Modal>
|
||||
@ -280,7 +290,7 @@ export class SourceSelector extends React.Component<
|
||||
|
||||
private async onSelectImage(_event: IpcRendererEvent, imagePath: string) {
|
||||
const isURL =
|
||||
_.startsWith(imagePath, 'https://') || _.startsWith(imagePath, 'http://');
|
||||
imagePath.startsWith('https://') || imagePath.startsWith('http://');
|
||||
await this.selectImageByPath({
|
||||
imagePath,
|
||||
SourceType: isURL ? sourceDestination.Http : sourceDestination.File,
|
||||
@ -354,8 +364,8 @@ export class SourceSelector extends React.Component<
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
!_.startsWith(imagePath, 'https://') &&
|
||||
!_.startsWith(imagePath, 'http://')
|
||||
!imagePath.startsWith('https://') &&
|
||||
!imagePath.startsWith('http://')
|
||||
) {
|
||||
const invalidImageError = errors.createUserError({
|
||||
title: 'Unsupported protocol',
|
||||
|
@ -50,7 +50,7 @@ import {
|
||||
import { store } from '../../models/store';
|
||||
import { logEvent, logException } from '../../modules/analytics';
|
||||
import { open as openExternal } from '../../os/open-external/services/open-external';
|
||||
import { Modal } from '../../styled-components';
|
||||
import { Modal, ScrollableFlex } from '../../styled-components';
|
||||
|
||||
import TargetSVGIcon from '../../../assets/tgt.svg';
|
||||
|
||||
@ -83,19 +83,6 @@ function isDrivelistDrive(
|
||||
return typeof (drive as scanner.adapters.DrivelistDrive).size === 'number';
|
||||
}
|
||||
|
||||
const ScrollableFlex = styled(Flex)`
|
||||
overflow: auto;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> div > div {
|
||||
/* This is required for the sticky table header in TargetsTable */
|
||||
overflow-x: visible;
|
||||
}
|
||||
`;
|
||||
|
||||
const TargetsTable = styled(({ refFn, ...props }) => {
|
||||
return (
|
||||
<div>
|
||||
@ -376,10 +363,6 @@ export class TargetSelectorModal extends React.Component<
|
||||
cancel={cancel}
|
||||
done={() => done(selectedList)}
|
||||
action={`Select (${selectedList.length})`}
|
||||
style={{
|
||||
width: '780px',
|
||||
height: '420px',
|
||||
}}
|
||||
primaryButtonProps={{
|
||||
primary: !hasStatus,
|
||||
warning: hasStatus,
|
||||
@ -387,7 +370,7 @@ export class TargetSelectorModal extends React.Component<
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
<Flex width="100%" height="100%">
|
||||
<Flex width="100%" height="90%">
|
||||
{!hasAvailableDrives() ? (
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
@ -399,11 +382,7 @@ export class TargetSelectorModal extends React.Component<
|
||||
<b>Plug a target drive</b>
|
||||
</Flex>
|
||||
) : (
|
||||
<ScrollableFlex
|
||||
flexDirection="column"
|
||||
width="100%"
|
||||
height="calc(100% - 15px)"
|
||||
>
|
||||
<ScrollableFlex flexDirection="column" width="100%">
|
||||
<TargetsTable
|
||||
refFn={(t: Table<Target>) => {
|
||||
if (t !== null) {
|
||||
|
@ -63,5 +63,5 @@ button:focus,
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.2;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
@ -121,8 +121,7 @@ export const DetailsText = (props: FlexProps) => (
|
||||
/>
|
||||
);
|
||||
|
||||
export const Modal = styled((props) => {
|
||||
const { style = { height: 420 } } = props;
|
||||
export const Modal = styled(({ style, ...props }) => {
|
||||
return (
|
||||
<Provider
|
||||
theme={{
|
||||
@ -143,23 +142,29 @@ export const Modal = styled((props) => {
|
||||
>
|
||||
<ModalBase
|
||||
position="top"
|
||||
width={780}
|
||||
width="96vw"
|
||||
cancelButtonProps={{
|
||||
style: {
|
||||
marginRight: '20px',
|
||||
border: 'solid 1px #2a506f',
|
||||
},
|
||||
}}
|
||||
style={style}
|
||||
style={{
|
||||
height: '86.5vh',
|
||||
...style,
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
</Provider>
|
||||
);
|
||||
})`
|
||||
> div {
|
||||
padding: 30px;
|
||||
padding: 24px 30px;
|
||||
height: calc(100% - 80px);
|
||||
overflow-y: auto;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> h3 {
|
||||
margin: 0;
|
||||
@ -178,3 +183,16 @@ export const Modal = styled((props) => {
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const ScrollableFlex = styled(Flex)`
|
||||
overflow: auto;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> div > div {
|
||||
/* This is required for the sticky table header in TargetsTable */
|
||||
overflow-x: visible;
|
||||
}
|
||||
`;
|
||||
|
Loading…
x
Reference in New Issue
Block a user