diff --git a/src/components/DownloadDetailsPopup.tsx b/src/components/DownloadDetailsPopup.tsx
new file mode 100644
index 0000000..20f320f
--- /dev/null
+++ b/src/components/DownloadDetailsPopup.tsx
@@ -0,0 +1,113 @@
+import { createPortal } from 'react-dom'
+import { DownloadUrl } from '../types'
+
+export const DownloadDetailsPopup = ({
+ title,
+ url,
+ hash,
+ signatureKey,
+ malwareScanLink,
+ modVersion,
+ customNote,
+ mediaUrl,
+ handleClose
+}: DownloadUrl & {
+ handleClose: () => void
+}) => {
+ return createPortal(
+
+
+
+
+
+
+
{title || 'Authentication Details'}
+
+
+
+
+
+
+
+
+
+
+
+
+ {typeof mediaUrl !== 'undefined' && mediaUrl !== '' && (
+
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
,
+ document.body
+ )
+}
diff --git a/src/components/ModForm.tsx b/src/components/ModForm.tsx
index b9a476f..45c3985 100644
--- a/src/components/ModForm.tsx
+++ b/src/components/ModForm.tsx
@@ -457,12 +457,14 @@ export const ModForm = () => {
@@ -524,11 +526,13 @@ export const ModForm = () => {
type DownloadUrlFieldsProps = {
index: number
url: string
+ title?: string
hash: string
signatureKey: string
malwareScanLink: string
modVersion: string
customNote: string
+ mediaUrl?: string
onUrlChange: (index: number, field: keyof DownloadUrl, value: string) => void
onRemove: (index: number) => void
}
@@ -537,11 +541,13 @@ const DownloadUrlFields = React.memo(
({
index,
url,
+ title,
hash,
signatureKey,
malwareScanLink,
modVersion,
customNote,
+ mediaUrl,
onUrlChange,
onRemove
}: DownloadUrlFieldsProps) => {
@@ -579,6 +585,28 @@ const DownloadUrlFields = React.memo(
+
+
+
+
+ {
+ onUrlChange(index, 'mediaUrl', values[0])
+ }}
+ />
+
+
+
+
+
)
}
diff --git a/src/pages/mod/index.tsx b/src/pages/mod/index.tsx
index 5b97147..f5c4a14 100644
--- a/src/pages/mod/index.tsx
+++ b/src/pages/mod/index.tsx
@@ -41,6 +41,7 @@ import { RouterLoadingSpinner } from 'components/LoadingSpinner'
import { OriginalAuthor } from 'components/OriginalAuthor'
import { Viewer } from 'components/Markdown/Viewer'
import { PostWarnings } from 'components/PostWarning'
+import { DownloadDetailsPopup } from 'components/DownloadDetailsPopup'
const MOD_REPORT_REASONS = [
{ label: 'Actually CP', key: 'actuallyCP' },
@@ -70,25 +71,6 @@ export const ModPage = () => {
const [commentCount, setCommentCount] = useState(0)
- const oldDownloadListRef = useRef(null)
-
- const handleViewOldLinks = () => {
- if (oldDownloadListRef.current) {
- // Toggle styles
- if (oldDownloadListRef.current.style.height === '0px') {
- // Enable styles
- oldDownloadListRef.current.style.padding = ''
- oldDownloadListRef.current.style.height = ''
- oldDownloadListRef.current.style.border = ''
- } else {
- // Disable styles
- oldDownloadListRef.current.style.padding = '0'
- oldDownloadListRef.current.style.height = '0'
- oldDownloadListRef.current.style.border = 'unset'
- }
- }
- }
-
return (
<>
@@ -136,37 +118,16 @@ export const ModPage = () => {
)}
{mod.downloadUrls.length > 1 && (
- <>
-
-
-
-
- {mod.downloadUrls
- .slice(1)
- .map((download, index) => (
-
- ))}
-
- >
+
+ {mod.downloadUrls
+ .slice(1)
+ .map((download, index) => (
+
+ ))}
+
)}
@@ -606,14 +567,8 @@ const Body = ({
)
}
-const Download = ({
- url,
- hash,
- signatureKey,
- malwareScanLink,
- modVersion,
- customNote
-}: DownloadUrl) => {
+const Download = (props: DownloadUrl) => {
+ const { url, title, malwareScanLink } = props
const [showAuthDetails, setShowAuthDetails] = useState(false)
const [showNotice, setShowNotice] = useState(false)
const [showScanNotice, setShowCanNotice] = useState(false)
@@ -645,6 +600,9 @@ const Download = ({
return (
+ {typeof title !== 'undefined' && title !== '' && (
+
{title}
+ )}
diff --git a/src/pages/submitMod/action.ts b/src/pages/submitMod/action.ts
index 5e51df4..51c16ef 100644
--- a/src/pages/submitMod/action.ts
+++ b/src/pages/submitMod/action.ts
@@ -256,6 +256,19 @@ const validateState = async (
errors.downloadUrls![i] = 'Download url must be valid and reachable'
}
+
+ if (
+ downloadUrl.mediaUrl &&
+ downloadUrl.mediaUrl.trim() !== '' &&
+ (!isValidUrl(downloadUrl.mediaUrl) ||
+ !isValidImageUrl(downloadUrl.mediaUrl) ||
+ !(await isReachable(downloadUrl.mediaUrl)))
+ ) {
+ if (!errors.downloadUrls)
+ errors.downloadUrls = Array(formState.downloadUrls.length)
+
+ errors.downloadUrls![i] = 'Media URLs must be valid and reachable image'
+ }
}
}
diff --git a/src/styles/downloads.css b/src/styles/downloads.css
index 0ff3847..66c7db4 100644
--- a/src/styles/downloads.css
+++ b/src/styles/downloads.css
@@ -11,7 +11,7 @@
display: grid;
grid-template-columns: 1fr;
grid-gap: 15px;
- border: solid 1px rgba(255,255,255,0.05);
+ border: solid 1px rgba(255, 255, 255, 0.05);
overflow: auto;
max-height: 550px;
padding: 15px;
@@ -27,7 +27,7 @@
}
.IBMSMSMBSSDownloadsTitle {
- color: rgba(255,255,255,0.5);
+ color: rgba(255, 255, 255, 0.5);
}
.IBMSMSMBSSDownloadsElement {
@@ -36,11 +36,11 @@
display: grid;
grid-template-columns: 1fr;
grid-gap: 10px;
- border: solid 1px rgba(255,255,255,0);
- background: rgba(255,255,255,0.05);
+ border: solid 1px rgba(255, 255, 255, 0);
+ background: rgba(255, 255, 255, 0.05);
padding: 10px;
border-radius: 10px;
- box-shadow: 0 0 8px 0 rgb(0,0,0,0.1);
+ box-shadow: 0 0 8px 0 rgb(0, 0, 0, 0.1);
}
@media (max-width: 768px) {
@@ -50,7 +50,7 @@
}
.btnMain.IBMSMSMBSSDownloadsElementBtn {
- background: rgba(255,255,255,0.05);
+ background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
width: 100%;
}
@@ -62,8 +62,8 @@
}
.btnMain.IBMSMSMBSSDownloadsElementBtn:hover {
- background: rgba(255,255,255,0.1);
- box-shadow: 0 0 8px 0 rgb(0,0,0,0.1);
+ background: rgba(255, 255, 255, 0.1);
+ box-shadow: 0 0 8px 0 rgb(0, 0, 0, 0.1);
}
.IBMSMSMBSSDownloadsElementInside {
@@ -71,7 +71,7 @@
flex-direction: column;
justify-content: start;
align-items: start;
- color: rgba(255,255,255,0.5);
+ color: rgba(255, 255, 255, 0.5);
grid-gap: 10px;
}
@@ -97,27 +97,30 @@
justify-content: center;
align-items: center;
width: 100%;
- background: rgba(255,255,255,0);
+ background: rgba(255, 255, 255, 0);
overflow: hidden;
border-radius: 10px;
- border: solid 1px rgba(255,255,255,0.05);
+ border: solid 1px rgba(255, 255, 255, 0.05);
cursor: pointer;
}
.IBMSMSMBSSDEIReactionsElement:hover {
transition: ease 0.4s;
- background: rgba(255,255,255,0.05);
- color: rgba(255,255,255,0.75);
- border: solid 1px rgba(255,255,255,0);
+ background: rgba(255, 255, 255, 0.05);
+ color: rgba(255, 255, 255, 0.75);
+ border: solid 1px rgba(255, 255, 255, 0);
}
-.IBMSMSMBSSDEIReactionsElement:hover > .IBMSMSMBSSDEIReactionsElementIconWrapper {
+.IBMSMSMBSSDEIReactionsElement:hover
+ > .IBMSMSMBSSDEIReactionsElementIconWrapper {
transition: ease 0.4s;
- background: rgba(255,255,255,0.05);
- border-right: solid 1px rgba(255,255,255,0);
+ background: rgba(255, 255, 255, 0.05);
+ border-right: solid 1px rgba(255, 255, 255, 0);
}
-.IBMSMSMBSSDEIReactionsElement:hover > .IBMSMSMBSSDEIReactionsElementIconWrapper > .IBMSMSMBSSDEIReactionsElementIcon {
+.IBMSMSMBSSDEIReactionsElement:hover
+ > .IBMSMSMBSSDEIReactionsElementIconWrapper
+ > .IBMSMSMBSSDEIReactionsElementIcon {
transform: scale(1.1);
}
@@ -147,9 +150,9 @@
justify-content: center;
align-items: center;
height: 100%;
- background: rgba(255,255,255,0);
+ background: rgba(255, 255, 255, 0);
padding: 10px 5px;
- border-right: solid 1px rgba(255,255,255,0.05);
+ border-right: solid 1px rgba(255, 255, 255, 0.05);
}
.IBMSMSMBSSDownloadsElementInsideDetails {
@@ -160,17 +163,20 @@
}
.IBMSMSMBSSDEIReactionsElement.IBMSMSMBSSDEIReactionsElementActive {
- background: rgba(255,255,255,0.05);
- border: solid 1px rgba(255,255,255,0);
+ background: rgba(255, 255, 255, 0.05);
+ border: solid 1px rgba(255, 255, 255, 0);
}
-.IBMSMSMBSSDEIReactionsElement.IBMSMSMBSSDEIReactionsElementActive > .IBMSMSMBSSDEIReactionsElementIconWrapper {
- background: rgba(255,255,255,0.05);
- border-right: solid 1px rgba(255,255,255,0);
+.IBMSMSMBSSDEIReactionsElement.IBMSMSMBSSDEIReactionsElementActive
+ > .IBMSMSMBSSDEIReactionsElementIconWrapper {
+ background: rgba(255, 255, 255, 0.05);
+ border-right: solid 1px rgba(255, 255, 255, 0);
}
-.IBMSMSMBSSDEIReactionsElement.IBMSMSMBSSDEIReactionsElementActive > .IBMSMSMBSSDEIReactionsElementIconWrapper > .IBMSMSMBSSDEIReactionsElementIcon {
- color: rgba(255,255,255,0.75);
+.IBMSMSMBSSDEIReactionsElement.IBMSMSMBSSDEIReactionsElementActive
+ > .IBMSMSMBSSDEIReactionsElementIconWrapper
+ > .IBMSMSMBSSDEIReactionsElementIcon {
+ color: rgba(255, 255, 255, 0.75);
}
.IBMSMSMBSSDownloadsActions {
@@ -188,7 +194,7 @@
display: flex;
flex-direction: column;
border-radius: 10px;
- border: solid 1px rgba(255,255,255,0.1);
+ border: solid 1px rgba(255, 255, 255, 0.1);
overflow: auto;
grid-gap: 1px;
}
@@ -202,7 +208,7 @@
.IBMSMSMBSSDownloadsElementInsideAltTableRow:hover {
transition: ease 0.4s;
- background: rgba(255,255,255,0.05);
+ background: rgba(255, 255, 255, 0.05);
}
@media (max-width: 576px) {
@@ -216,12 +222,17 @@
text-align: start;
padding: 10px 15px;
}
+.IBMSMSMBSSDownloadsElementInsideAltTableRowCol_Img {
+ width: 100%;
+ max-width: 300px;
+ border-radius: 6px;
+}
.IBMSMSMBSSDownloadsElementInsideAltTableRowCol.IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst {
text-align: center;
font-weight: bold;
max-width: 200px;
- background: rgba(255,255,255,0.05);
+ background: rgba(255, 255, 255, 0.05);
display: flex;
justify-content: center;
align-items: center;
@@ -237,13 +248,12 @@
transition: ease 0.4s;
cursor: pointer;
font-weight: 400;
- color: rgba(255,255,255,0.25);
+ color: rgba(255, 255, 255, 0.25);
}
.IBMSMSMBSSDownloadsElementInsideAltText:hover {
transition: ease 0.4s;
cursor: pointer;
font-weight: 600;
- color: rgba(255,255,255,0.75);
+ color: rgba(255, 255, 255, 0.75);
}
-
diff --git a/src/types/mod.ts b/src/types/mod.ts
index a62fe5b..fdd9036 100644
--- a/src/types/mod.ts
+++ b/src/types/mod.ts
@@ -41,11 +41,13 @@ export interface ModFormState {
export interface DownloadUrl {
url: string
+ title?: string
hash: string
signatureKey: string
malwareScanLink: string
modVersion: string
customNote: string
+ mediaUrl?: string
}
export interface ModDetails extends Omit {