Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a9fc2be30 | ||
|
|
3442baa356 | ||
|
|
d6e92e0434 | ||
|
|
c908065585 | ||
|
|
f9125d4060 | ||
|
|
153a46e9c1 | ||
|
|
eb9ec074de | ||
|
|
ab215c0bda | ||
|
|
01664f8cba | ||
|
|
6a99ea5808 | ||
|
|
fa6d55cd35 | ||
|
|
a7b40a0aa7 | ||
|
|
60b5605438 |
No files matched your search
@@ -21,7 +21,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [macos-latest, windows-latest, ubuntu-22.04]
|
platform: [macos-latest, self-hosted, ubuntu-22.04]
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
|
||||||
@@ -127,6 +127,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
|
DIGICERT_PASSWORD: ${{ secrets.DIGICERT_PASSWORD }}
|
||||||
|
|
||||||
- name: upload ${{ matrix.platform }}
|
- name: upload ${{ matrix.platform }}
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|||||||
Generated
+3
-3
@@ -8870,7 +8870,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "theseus"
|
name = "theseus"
|
||||||
version = "0.9.3"
|
version = "0.9.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
"async-tungstenite",
|
"async-tungstenite",
|
||||||
@@ -8921,7 +8921,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "theseus_gui"
|
name = "theseus_gui"
|
||||||
version = "0.9.3"
|
version = "0.9.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"cocoa 0.25.0",
|
"cocoa 0.25.0",
|
||||||
@@ -10780,7 +10780,7 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "wry"
|
name = "wry"
|
||||||
version = "0.47.2"
|
version = "0.47.2"
|
||||||
source = "git+https://github.com/modrinth/wry?rev=51907c6#51907c61541f2e389856f07773a32bac04f9a843"
|
source = "git+https://github.com/modrinth/wry?rev=cdbf938#cdbf9384263db4e692e22dcf9bf6085e334a10f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"block2",
|
"block2",
|
||||||
|
|||||||
+1
-1
@@ -21,4 +21,4 @@ strip = true # Remove debug symbols
|
|||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
wry = { git = "https://github.com/modrinth/wry", rev = "51907c6" }
|
wry = { git = "https://github.com/modrinth/wry", rev ="cdbf938" }
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@modrinth/app-frontend",
|
"name": "@modrinth/app-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.9.3",
|
"version": "0.9.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -20,9 +20,6 @@
|
|||||||
"app.settings.tabs.resource-management": {
|
"app.settings.tabs.resource-management": {
|
||||||
"message": "Resource management"
|
"message": "Resource management"
|
||||||
},
|
},
|
||||||
"instance.filter.disabled": {
|
|
||||||
"message": "Disabled projects"
|
|
||||||
},
|
|
||||||
"instance.filter.updates-available": {
|
"instance.filter.updates-available": {
|
||||||
"message": "Updates available"
|
"message": "Updates available"
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "theseus_gui"
|
name = "theseus_gui"
|
||||||
version = "0.9.3"
|
version = "0.9.2"
|
||||||
description = "The Modrinth App is a desktop application for managing your Minecraft mods"
|
description = "The Modrinth App is a desktop application for managing your Minecraft mods"
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
repository = "https://github.com/modrinth/code/apps/app/"
|
repository = "https://github.com/modrinth/code/apps/app/"
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"createUpdaterArtifacts": "v1Compatible"
|
"createUpdaterArtifacts": "v1Compatible",
|
||||||
|
"windows": {
|
||||||
|
"certificateThumbprint": "6007d6ed9b1ba057aa29144d58ca3ed89ac4ef94",
|
||||||
|
"signCommand": "bash -c \"jsign.bat --storetype ETOKEN --alg SHA-256 --storepass $DIGICERT_PASSWORD --tsurl https://timestamp.digicert.com %1\""
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"features": ["updater"]
|
"features": ["updater"]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"productName": "Modrinth App",
|
"productName": "Modrinth App",
|
||||||
"version": "0.9.3",
|
"version": "0.9.2",
|
||||||
"mainBinaryName": "Modrinth App",
|
"mainBinaryName": "Modrinth App",
|
||||||
"identifier": "ModrinthApp",
|
"identifier": "ModrinthApp",
|
||||||
"plugins": {
|
"plugins": {
|
||||||
|
|||||||
@@ -485,81 +485,6 @@
|
|||||||
"project.versions.title": {
|
"project.versions.title": {
|
||||||
"message": "Versions"
|
"message": "Versions"
|
||||||
},
|
},
|
||||||
"report.already-reported": {
|
|
||||||
"message": "You've already reported {title}"
|
|
||||||
},
|
|
||||||
"report.already-reported-description": {
|
|
||||||
"message": "You have an open report for this {item} already. You can add more details to your report if you have more information to add."
|
|
||||||
},
|
|
||||||
"report.back-to-item": {
|
|
||||||
"message": "Back to {item}"
|
|
||||||
},
|
|
||||||
"report.body.description": {
|
|
||||||
"message": "Include links and images if possible and relevant. Empty or insufficient reports will be closed and ignored."
|
|
||||||
},
|
|
||||||
"report.body.title": {
|
|
||||||
"message": "Please provide additional context about your report"
|
|
||||||
},
|
|
||||||
"report.checking": {
|
|
||||||
"message": "Checking {item}..."
|
|
||||||
},
|
|
||||||
"report.could-not-find": {
|
|
||||||
"message": "Could not find {item}"
|
|
||||||
},
|
|
||||||
"report.for.violation": {
|
|
||||||
"message": "Violation of Modrinth <rules-link>Rules</rules-link> or <terms-link>Terms of Use</terms-link>"
|
|
||||||
},
|
|
||||||
"report.for.violation.description": {
|
|
||||||
"message": "Examples include malicious, spam, offensive, deceptive, misleading, and illegal content."
|
|
||||||
},
|
|
||||||
"report.form-not-for": {
|
|
||||||
"message": "This form is not for:"
|
|
||||||
},
|
|
||||||
"report.go-to-report": {
|
|
||||||
"message": "Go to report"
|
|
||||||
},
|
|
||||||
"report.not-for.bug-reports": {
|
|
||||||
"message": "Bug reports"
|
|
||||||
},
|
|
||||||
"report.not-for.dmca": {
|
|
||||||
"message": "DMCA takedowns"
|
|
||||||
},
|
|
||||||
"report.not-for.dmca.description": {
|
|
||||||
"message": "See our <policy-link>Copyright Policy</policy-link>."
|
|
||||||
},
|
|
||||||
"report.note.copyright.1": {
|
|
||||||
"message": "Please note that you are *not* submitting a DMCA takedown request, but rather a report of reuploaded content."
|
|
||||||
},
|
|
||||||
"report.note.copyright.2": {
|
|
||||||
"message": "If you meant to file a DMCA takedown request (which is a legal action) instead, please see our <copyright-policy-link>Copyright Policy</copyright-policy-link>."
|
|
||||||
},
|
|
||||||
"report.note.malicious.1": {
|
|
||||||
"message": "Reports for malicious or deceptive content must include substantial evidence of the behavior, such as code samples."
|
|
||||||
},
|
|
||||||
"report.note.malicious.2": {
|
|
||||||
"message": "Summaries from Microsoft Defender, VirusTotal, or AI malware detection are not sufficient forms of evidence and will not be accepted."
|
|
||||||
},
|
|
||||||
"report.please-report": {
|
|
||||||
"message": "Please report:"
|
|
||||||
},
|
|
||||||
"report.question.content-id": {
|
|
||||||
"message": "What is the ID of the {item}?"
|
|
||||||
},
|
|
||||||
"report.question.content-type": {
|
|
||||||
"message": "What type of content are you reporting?"
|
|
||||||
},
|
|
||||||
"report.question.report-reason": {
|
|
||||||
"message": "Which of Modrinth's rules is this {item} violating?"
|
|
||||||
},
|
|
||||||
"report.report-content": {
|
|
||||||
"message": "Report content to moderators"
|
|
||||||
},
|
|
||||||
"report.report-item": {
|
|
||||||
"message": "Report {title} to moderators"
|
|
||||||
},
|
|
||||||
"report.submit": {
|
|
||||||
"message": "Submit report"
|
|
||||||
},
|
|
||||||
"revenue.transfers.total": {
|
"revenue.transfers.total": {
|
||||||
"message": "You have withdrawn {amount} in total."
|
"message": "You have withdrawn {amount} in total."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -631,7 +631,7 @@
|
|||||||
auth.user ? reportProject(project.id) : navigateTo('/auth/sign-in'),
|
auth.user ? reportProject(project.id) : navigateTo('/auth/sign-in'),
|
||||||
color: 'red',
|
color: 'red',
|
||||||
hoverOnly: true,
|
hoverOnly: true,
|
||||||
shown: !isMember,
|
shown: !currentMember,
|
||||||
},
|
},
|
||||||
{ id: 'copy-id', action: () => copyId() },
|
{ id: 'copy-id', action: () => copyId() },
|
||||||
]"
|
]"
|
||||||
@@ -1204,10 +1204,6 @@ const members = computed(() => {
|
|||||||
return owner ? [owner, ...rest] : rest;
|
return owner ? [owner, ...rest] : rest;
|
||||||
});
|
});
|
||||||
|
|
||||||
const isMember = computed(
|
|
||||||
() => auth.value.user && allMembers.value.some((x) => x.user.id === auth.value.user.id),
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentMember = computed(() => {
|
const currentMember = computed(() => {
|
||||||
let val = auth.value.user ? allMembers.value.find((x) => x.user.id === auth.value.user.id) : null;
|
let val = auth.value.user ? allMembers.value.find((x) => x.user.id === auth.value.user.id) : null;
|
||||||
|
|
||||||
|
|||||||
+145
-438
@@ -1,256 +1,99 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<div class="experimental-styles-within flex flex-col gap-2">
|
<Card>
|
||||||
<RadialHeader class="top-box mb-2 text-center" color="orange">
|
<div class="content">
|
||||||
<ScaleIcon class="h-12 w-12 text-brand-orange" />
|
<div>
|
||||||
<h1 class="m-3 gap-2 text-3xl font-extrabold">
|
<h1 class="card-title-adjustments">Submit a Report</h1>
|
||||||
{{
|
<div>
|
||||||
prefilled && itemName
|
<p>
|
||||||
? existingReport
|
Modding should be safe for everyone, so we take abuse and malicious intent seriously
|
||||||
? formatMessage(messages.alreadyReportedItem, { title: itemName })
|
at Modrinth. If you encounter content that violates our
|
||||||
: formatMessage(messages.reportItem, { title: itemName })
|
<nuxt-link class="text-link" to="/legal/terms">Terms of Service</nuxt-link> or our
|
||||||
: formatMessage(messages.reportContent)
|
<nuxt-link class="text-link" to="/legal/rules">Rules</nuxt-link>, please report it to
|
||||||
}}
|
us here.
|
||||||
</h1>
|
</p>
|
||||||
</RadialHeader>
|
<p>
|
||||||
<div
|
This form is intended exclusively for reporting abuse or harmful content to Modrinth
|
||||||
v-if="prefilled && itemName && existingReport"
|
staff. For bugs related to specific projects, please use the project's designated
|
||||||
class="mx-auto flex max-w-[35rem] flex-col items-center gap-4 text-center"
|
Issues link or Discord channel.
|
||||||
>
|
</p>
|
||||||
{{ formatMessage(messages.alreadyReportedDescription, { item: reportItem || "content" }) }}
|
<p>
|
||||||
<div class="flex gap-2">
|
Your privacy is important to us; rest assured that your identifying information will
|
||||||
<ButtonStyled v-if="itemLink">
|
be kept confidential.
|
||||||
<nuxt-link :to="itemLink">
|
</p>
|
||||||
<LeftArrowIcon />
|
</div>
|
||||||
{{ formatMessage(messages.backToItem, { item: reportItem || "content" }) }}
|
</div>
|
||||||
</nuxt-link>
|
<div class="report-info-section">
|
||||||
</ButtonStyled>
|
<div class="report-info-item">
|
||||||
<ButtonStyled color="brand">
|
<label for="report-item">Item type to report</label>
|
||||||
<nuxt-link :to="`/dashboard/report/${existingReport.id}`">
|
<DropdownSelect
|
||||||
{{ formatMessage(messages.goToReport) }} <RightArrowIcon />
|
id="report-item"
|
||||||
</nuxt-link>
|
v-model="reportItem"
|
||||||
</ButtonStyled>
|
name="report-item"
|
||||||
|
:options="reportItems"
|
||||||
|
:display-name="capitalizeString"
|
||||||
|
:multiple="false"
|
||||||
|
:searchable="false"
|
||||||
|
:show-no-results="false"
|
||||||
|
:show-labels="false"
|
||||||
|
placeholder="Choose report item"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="report-info-item">
|
||||||
|
<label for="report-item-id">Item ID</label>
|
||||||
|
<input
|
||||||
|
id="report-item-id"
|
||||||
|
v-model="reportItemID"
|
||||||
|
type="text"
|
||||||
|
placeholder="ex. project ID"
|
||||||
|
autocomplete="off"
|
||||||
|
:disabled="reportItem === ''"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="report-info-item">
|
||||||
|
<label for="report-type">Reason for report</label>
|
||||||
|
<DropdownSelect
|
||||||
|
id="report-type"
|
||||||
|
v-model="reportType"
|
||||||
|
name="report-type"
|
||||||
|
:options="reportTypes"
|
||||||
|
:multiple="false"
|
||||||
|
:searchable="false"
|
||||||
|
:show-no-results="false"
|
||||||
|
:show-labels="false"
|
||||||
|
:display-name="capitalizeString"
|
||||||
|
placeholder="Choose report type"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="report-submission-section">
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
Please provide additional context about your report. Include links and images if
|
||||||
|
possible. <strong>Empty reports will be closed.</strong>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<MarkdownEditor v-model="reportBody" placeholder="" :on-image-upload="onImageUpload" />
|
||||||
|
</div>
|
||||||
|
<div class="submit-button">
|
||||||
|
<Button
|
||||||
|
id="submit-button"
|
||||||
|
color="primary"
|
||||||
|
:disabled="submitLoading || !canSubmit"
|
||||||
|
@click="submitReport"
|
||||||
|
>
|
||||||
|
<SaveIcon aria-hidden="true" />
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
</Card>
|
||||||
<div class="mb-3 grid grid-cols-1 gap-4 px-6 md:grid-cols-2">
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<h2 class="m-0 text-lg font-extrabold">{{ formatMessage(messages.pleaseReport) }}</h2>
|
|
||||||
<div class="text-md flex items-center gap-2 font-semibold text-contrast">
|
|
||||||
<CheckCircleIcon class="h-8 w-8 shrink-0 text-brand-green" />
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<span>
|
|
||||||
<IntlFormatted :message-id="messages.violation">
|
|
||||||
<template #rules-link="{ children }">
|
|
||||||
<nuxt-link class="text-link" :to="`/legal/rules`">
|
|
||||||
<component :is="() => children" />
|
|
||||||
</nuxt-link>
|
|
||||||
</template>
|
|
||||||
<template #terms-link="{ children }">
|
|
||||||
<nuxt-link class="text-link" :to="`/legal/terms`">
|
|
||||||
<component :is="() => children" />
|
|
||||||
</nuxt-link>
|
|
||||||
</template>
|
|
||||||
</IntlFormatted>
|
|
||||||
</span>
|
|
||||||
<span class="text-sm font-medium text-secondary">
|
|
||||||
{{ formatMessage(messages.violationDescription) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<h2 class="m-0 text-lg font-extrabold">{{ formatMessage(messages.formNotFor) }}</h2>
|
|
||||||
<div class="text-md flex items-center gap-2 font-semibold text-contrast">
|
|
||||||
<XCircleIcon class="h-8 w-8 shrink-0 text-brand-red" />
|
|
||||||
<span>{{ formatMessage(messages.bugReports) }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="text-md flex items-center gap-2 font-semibold text-contrast">
|
|
||||||
<XCircleIcon class="h-8 w-8 shrink-0 text-brand-red" />
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<span>{{ formatMessage(messages.dmcaTakedown) }}</span>
|
|
||||||
<span class="text-sm font-medium text-secondary">
|
|
||||||
<IntlFormatted :message-id="messages.dmcaTakedownDescription">
|
|
||||||
<template #policy-link="{ children }">
|
|
||||||
<nuxt-link class="text-link" :to="`/legal/copyright`">
|
|
||||||
<component :is="() => children" />
|
|
||||||
</nuxt-link>
|
|
||||||
</template>
|
|
||||||
</IntlFormatted>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col gap-4 rounded-xl bg-bg-raised p-6">
|
|
||||||
<template v-if="!prefilled || !currentItemValid">
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<span class="text-lg font-bold text-contrast">
|
|
||||||
{{ formatMessage(messages.whatContentType) }}
|
|
||||||
</span>
|
|
||||||
<RadioButtons
|
|
||||||
v-slot="{ item }"
|
|
||||||
v-model="reportItem"
|
|
||||||
:items="reportItems"
|
|
||||||
@update:model-value="
|
|
||||||
() => {
|
|
||||||
prefilled = false;
|
|
||||||
fetchItem();
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ capitalizeString(item) }}
|
|
||||||
</RadioButtons>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col gap-2" :class="{ hidden: !reportItem }">
|
|
||||||
<span class="text-lg font-bold text-contrast">
|
|
||||||
{{ formatMessage(messages.whatContentId, { item: reportItem || "content" }) }}
|
|
||||||
</span>
|
|
||||||
<div class="flex gap-4">
|
|
||||||
<input
|
|
||||||
id="report-item-id"
|
|
||||||
v-model="reportItemID"
|
|
||||||
type="text"
|
|
||||||
placeholder="ex: Dc7EYhxG"
|
|
||||||
autocomplete="off"
|
|
||||||
:disabled="reportItem === ''"
|
|
||||||
class="w-40"
|
|
||||||
@blur="
|
|
||||||
() => {
|
|
||||||
prefilled = false;
|
|
||||||
reportItemID = reportItemID.trim();
|
|
||||||
fetchItem();
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<div v-if="checkingId || checkedId" class="flex items-center gap-1">
|
|
||||||
<template v-if="checkingId">
|
|
||||||
<SpinnerIcon class="animate-spin" />
|
|
||||||
{{ formatMessage(messages.checking, { item: reportItem }) }}...
|
|
||||||
</template>
|
|
||||||
<template v-else-if="checkedId && itemName">
|
|
||||||
<AutoLink
|
|
||||||
:to="itemLink"
|
|
||||||
target="_blank"
|
|
||||||
class="flex items-center gap-1 font-bold text-contrast hover:underline"
|
|
||||||
>
|
|
||||||
<Avatar
|
|
||||||
v-if="typeof itemIcon === 'string'"
|
|
||||||
:src="itemIcon"
|
|
||||||
:alt="itemName"
|
|
||||||
size="24px"
|
|
||||||
:circle="reportItem === 'user'"
|
|
||||||
/>
|
|
||||||
<component :is="itemIcon" v-else-if="itemIcon" />
|
|
||||||
<span>{{ itemName }}</span>
|
|
||||||
</AutoLink>
|
|
||||||
<CheckIcon class="text-brand-green" />
|
|
||||||
</template>
|
|
||||||
<span v-else-if="checkedId" class="contents text-brand-red">
|
|
||||||
<IssuesIcon />
|
|
||||||
{{ formatMessage(messages.couldNotFind, { item: reportItem }) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-if="existingReport">
|
|
||||||
{{
|
|
||||||
formatMessage(messages.alreadyReportedDescription, { item: reportItem || "content" })
|
|
||||||
}}
|
|
||||||
<ButtonStyled color="brand">
|
|
||||||
<nuxt-link :to="`/dashboard/report/${existingReport.id}`" class="w-fit">
|
|
||||||
{{ formatMessage(messages.goToReport) }} <RightArrowIcon />
|
|
||||||
</nuxt-link>
|
|
||||||
</ButtonStyled>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div class="flex flex-col gap-2" :class="{ hidden: !reportItemID }">
|
|
||||||
<span class="text-lg font-bold text-contrast">
|
|
||||||
{{ formatMessage(messages.whatReportReason, { item: reportItem || "content" }) }}
|
|
||||||
</span>
|
|
||||||
<RadioButtons v-slot="{ item }" v-model="reportType" :items="reportTypes">
|
|
||||||
{{ item === "copyright" ? "Reuploaded work" : capitalizeString(item) }}
|
|
||||||
</RadioButtons>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="warnings[reportType]"
|
|
||||||
class="flex gap-2 rounded-xl border-2 border-solid border-brand-orange bg-highlight-orange p-4 text-contrast"
|
|
||||||
>
|
|
||||||
<IssuesIcon class="h-5 w-5 shrink-0 text-orange" />
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<p
|
|
||||||
v-for="(warning, index) in warnings[reportType]"
|
|
||||||
:key="`warning-${reportType}-${index}`"
|
|
||||||
class="m-0 leading-tight"
|
|
||||||
>
|
|
||||||
<IntlFormatted :message-id="warning">
|
|
||||||
<template #copyright-policy-link="{ children }">
|
|
||||||
<nuxt-link class="text-link" :to="`/legal/copyright`">
|
|
||||||
<component :is="() => children" />
|
|
||||||
</nuxt-link>
|
|
||||||
</template>
|
|
||||||
</IntlFormatted>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div :class="{ hidden: !reportType }">
|
|
||||||
<span class="text-lg font-bold text-contrast">
|
|
||||||
{{ formatMessage(messages.reportBodyTitle) }}
|
|
||||||
</span>
|
|
||||||
<p class="m-0 leading-tight text-secondary">
|
|
||||||
{{ formatMessage(messages.reportBodyDescription) }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div :class="{ hidden: !reportType }">
|
|
||||||
<MarkdownEditor
|
|
||||||
v-model="reportBody"
|
|
||||||
placeholder=""
|
|
||||||
:on-image-upload="onImageUpload"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div :class="{ hidden: !reportType }">
|
|
||||||
<ButtonStyled color="brand">
|
|
||||||
<button
|
|
||||||
id="submit-button"
|
|
||||||
:disabled="submitLoading || !canSubmit"
|
|
||||||
@click="submitReport"
|
|
||||||
>
|
|
||||||
<SendIcon aria-hidden="true" />
|
|
||||||
{{ formatMessage(messages.submitReport) }}
|
|
||||||
</button>
|
|
||||||
</ButtonStyled>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { Card, Button, MarkdownEditor, DropdownSelect } from "@modrinth/ui";
|
||||||
MarkdownEditor,
|
import { SaveIcon } from "@modrinth/assets";
|
||||||
RadialHeader,
|
|
||||||
RadioButtons,
|
|
||||||
ButtonStyled,
|
|
||||||
Avatar,
|
|
||||||
AutoLink,
|
|
||||||
} from "@modrinth/ui";
|
|
||||||
import {
|
|
||||||
LeftArrowIcon,
|
|
||||||
RightArrowIcon,
|
|
||||||
CheckIcon,
|
|
||||||
SpinnerIcon,
|
|
||||||
SendIcon,
|
|
||||||
IssuesIcon,
|
|
||||||
CheckCircleIcon,
|
|
||||||
XCircleIcon,
|
|
||||||
ScaleIcon,
|
|
||||||
VersionIcon,
|
|
||||||
} from "@modrinth/assets";
|
|
||||||
import type { User, Version, Report } from "@modrinth/utils";
|
|
||||||
import { useVIntl, defineMessages, type MessageDescriptor } from "@vintl/vintl";
|
|
||||||
import { useImageUpload } from "~/composables/image-upload.ts";
|
import { useImageUpload } from "~/composables/image-upload.ts";
|
||||||
|
|
||||||
const tags = useTags();
|
const tags = useTags();
|
||||||
@@ -258,7 +101,6 @@ const route = useNativeRoute();
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const auth = await useAuth();
|
const auth = await useAuth();
|
||||||
const { formatMessage } = useVIntl();
|
|
||||||
|
|
||||||
if (!auth.value.user) {
|
if (!auth.value.user) {
|
||||||
router.push("/auth/sign-in?redirect=" + encodeURIComponent(route.fullPath));
|
router.push("/auth/sign-in?redirect=" + encodeURIComponent(route.fullPath));
|
||||||
@@ -277,80 +119,6 @@ const reportItem = ref<string>(accessQuery("item"));
|
|||||||
const reportItemID = ref<string>(accessQuery("itemID"));
|
const reportItemID = ref<string>(accessQuery("itemID"));
|
||||||
const reportType = ref<string>("");
|
const reportType = ref<string>("");
|
||||||
|
|
||||||
const prefilled = ref<boolean>(!!reportItem.value && !!reportItemID.value);
|
|
||||||
const checkedId = ref<boolean>(false);
|
|
||||||
const checkingId = ref<boolean>(false);
|
|
||||||
|
|
||||||
const currentProject = ref<Project | null>(null);
|
|
||||||
const currentVersion = ref<Version | null>(null);
|
|
||||||
const currentUser = ref<User | null>(null);
|
|
||||||
|
|
||||||
const itemIcon = ref<string | Component | undefined>();
|
|
||||||
const itemName = ref<string | undefined>();
|
|
||||||
const itemLink = ref<string | undefined>();
|
|
||||||
const itemId = ref<string | undefined>();
|
|
||||||
|
|
||||||
const reports = ref<Report[]>([]);
|
|
||||||
const existingReport = computed(() =>
|
|
||||||
reports.value.find(
|
|
||||||
(x) =>
|
|
||||||
(x.item_id === reportItemID.value || x.item_id === itemId.value) &&
|
|
||||||
x.item_type === reportItem.value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await fetchItem();
|
|
||||||
await fetchExistingReports();
|
|
||||||
|
|
||||||
const currentItemValid = computed(
|
|
||||||
() => !!currentProject.value || !!currentVersion.value || !!currentUser.value,
|
|
||||||
);
|
|
||||||
|
|
||||||
async function fetchExistingReports() {
|
|
||||||
reports.value = ((await useBaseFetch("report?count=1000")) as Report[]).filter(
|
|
||||||
(x) => x.reporter === auth.value.user?.id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchItem() {
|
|
||||||
if (reportItem.value && reportItemID.value) {
|
|
||||||
checkingId.value = true;
|
|
||||||
itemIcon.value = undefined;
|
|
||||||
itemName.value = undefined;
|
|
||||||
itemLink.value = undefined;
|
|
||||||
itemId.value = undefined;
|
|
||||||
try {
|
|
||||||
if (reportItem.value === "project") {
|
|
||||||
const project = (await useBaseFetch(`project/${reportItemID.value}`)) as Project;
|
|
||||||
currentProject.value = project;
|
|
||||||
|
|
||||||
itemIcon.value = project.icon_url;
|
|
||||||
itemName.value = project.title;
|
|
||||||
itemLink.value = `/project/${project.id}`;
|
|
||||||
itemId.value = project.id;
|
|
||||||
} else if (reportItem.value === "version") {
|
|
||||||
const version = (await useBaseFetch(`version/${reportItemID.value}`)) as Version;
|
|
||||||
currentVersion.value = version;
|
|
||||||
|
|
||||||
itemIcon.value = VersionIcon;
|
|
||||||
itemName.value = version.version_number;
|
|
||||||
itemLink.value = `project/${version.project_id}/version/${version.id}`;
|
|
||||||
itemId.value = version.id;
|
|
||||||
} else if (reportItem.value === "user") {
|
|
||||||
const user = (await useBaseFetch(`user/${reportItemID.value}`)) as User;
|
|
||||||
currentUser.value = user;
|
|
||||||
|
|
||||||
itemIcon.value = user.avatar_url;
|
|
||||||
itemName.value = user.username;
|
|
||||||
itemLink.value = `/user/${user.username}`;
|
|
||||||
itemId.value = user.id;
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
checkedId.value = true;
|
|
||||||
checkingId.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const reportItems = ["project", "version", "user"];
|
const reportItems = ["project", "version", "user"];
|
||||||
const reportTypes = computed(() => tags.value.reportTypes);
|
const reportTypes = computed(() => tags.value.reportTypes);
|
||||||
|
|
||||||
@@ -464,131 +232,70 @@ const onImageUpload = async (file: File) => {
|
|||||||
uploadedImageIDs.value.push(item.id);
|
uploadedImageIDs.value.push(item.id);
|
||||||
return item.url;
|
return item.url;
|
||||||
};
|
};
|
||||||
|
|
||||||
const warnings: Record<string, MessageDescriptor[]> = {
|
|
||||||
copyright: [
|
|
||||||
defineMessage({
|
|
||||||
id: "report.note.copyright.1",
|
|
||||||
defaultMessage:
|
|
||||||
"Please note that you are *not* submitting a DMCA takedown request, but rather a report of reuploaded content.",
|
|
||||||
}),
|
|
||||||
defineMessage({
|
|
||||||
id: "report.note.copyright.2",
|
|
||||||
defaultMessage:
|
|
||||||
"If you meant to file a DMCA takedown request (which is a legal action) instead, please see our <copyright-policy-link>Copyright Policy</copyright-policy-link>.",
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
malicious: [
|
|
||||||
defineMessage({
|
|
||||||
id: "report.note.malicious.1",
|
|
||||||
defaultMessage:
|
|
||||||
"Reports for malicious or deceptive content must include substantial evidence of the behavior, such as code samples.",
|
|
||||||
}),
|
|
||||||
defineMessage({
|
|
||||||
id: "report.note.malicious.2",
|
|
||||||
defaultMessage:
|
|
||||||
"Summaries from Microsoft Defender, VirusTotal, or AI malware detection are not sufficient forms of evidence and will not be accepted.",
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
reportContent: {
|
|
||||||
id: "report.report-content",
|
|
||||||
defaultMessage: "Report content to moderators",
|
|
||||||
},
|
|
||||||
reportItem: {
|
|
||||||
id: "report.report-item",
|
|
||||||
defaultMessage: "Report {title} to moderators",
|
|
||||||
},
|
|
||||||
alreadyReportedItem: {
|
|
||||||
id: "report.already-reported",
|
|
||||||
defaultMessage: "You've already reported {title}",
|
|
||||||
},
|
|
||||||
alreadyReportedDescription: {
|
|
||||||
id: "report.already-reported-description",
|
|
||||||
defaultMessage:
|
|
||||||
"You have an open report for this {item} already. You can add more details to your report if you have more information to add.",
|
|
||||||
},
|
|
||||||
backToItem: {
|
|
||||||
id: "report.back-to-item",
|
|
||||||
defaultMessage: "Back to {item}",
|
|
||||||
},
|
|
||||||
goToReport: {
|
|
||||||
id: "report.go-to-report",
|
|
||||||
defaultMessage: "Go to report",
|
|
||||||
},
|
|
||||||
pleaseReport: {
|
|
||||||
id: "report.please-report",
|
|
||||||
defaultMessage: "Please report:",
|
|
||||||
},
|
|
||||||
formNotFor: {
|
|
||||||
id: "report.form-not-for",
|
|
||||||
defaultMessage: "This form is not for:",
|
|
||||||
},
|
|
||||||
violation: {
|
|
||||||
id: "report.for.violation",
|
|
||||||
defaultMessage:
|
|
||||||
"Violation of Modrinth <rules-link>Rules</rules-link> or <terms-link>Terms of Use</terms-link>",
|
|
||||||
},
|
|
||||||
violationDescription: {
|
|
||||||
id: "report.for.violation.description",
|
|
||||||
defaultMessage:
|
|
||||||
"Examples include malicious, spam, offensive, deceptive, misleading, and illegal content.",
|
|
||||||
},
|
|
||||||
bugReports: {
|
|
||||||
id: "report.not-for.bug-reports",
|
|
||||||
defaultMessage: "Bug reports",
|
|
||||||
},
|
|
||||||
dmcaTakedown: {
|
|
||||||
id: "report.not-for.dmca",
|
|
||||||
defaultMessage: "DMCA takedowns",
|
|
||||||
},
|
|
||||||
dmcaTakedownDescription: {
|
|
||||||
id: "report.not-for.dmca.description",
|
|
||||||
defaultMessage: "See our <policy-link>Copyright Policy</policy-link>.",
|
|
||||||
},
|
|
||||||
whatContentType: {
|
|
||||||
id: "report.question.content-type",
|
|
||||||
defaultMessage: "What type of content are you reporting?",
|
|
||||||
},
|
|
||||||
whatContentId: {
|
|
||||||
id: "report.question.content-id",
|
|
||||||
defaultMessage: "What is the ID of the {item}?",
|
|
||||||
},
|
|
||||||
whatReportReason: {
|
|
||||||
id: "report.question.report-reason",
|
|
||||||
defaultMessage: "Which of Modrinth's rules is this {item} violating?",
|
|
||||||
},
|
|
||||||
checking: {
|
|
||||||
id: "report.checking",
|
|
||||||
defaultMessage: "Checking {item}...",
|
|
||||||
},
|
|
||||||
couldNotFind: {
|
|
||||||
id: "report.could-not-find",
|
|
||||||
defaultMessage: "Could not find {item}",
|
|
||||||
},
|
|
||||||
reportBodyTitle: {
|
|
||||||
id: "report.body.title",
|
|
||||||
defaultMessage: "Please provide additional context about your report",
|
|
||||||
},
|
|
||||||
reportBodyDescription: {
|
|
||||||
id: "report.body.description",
|
|
||||||
defaultMessage:
|
|
||||||
"Include links and images if possible and relevant. Empty or insufficient reports will be closed and ignored.",
|
|
||||||
},
|
|
||||||
submitReport: {
|
|
||||||
id: "report.submit",
|
|
||||||
defaultMessage: "Submit report",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.submit-button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
margin-top: var(--spacing-card-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title-adjustments {
|
||||||
|
margin-block: var(--spacing-card-md) var(--spacing-card-sm);
|
||||||
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
max-width: 56rem;
|
max-width: 56rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
// TODO: Get rid of this hack when removing global styles from the website.
|
||||||
|
// Overflow decides the behavior of md editor but also clips the border.
|
||||||
|
// In the future, we should use ring instead of block-shadow for the
|
||||||
|
// green ring around the md editor
|
||||||
|
padding-inline: var(--gap-md);
|
||||||
|
padding-bottom: var(--gap-md);
|
||||||
|
margin-inline: calc(var(--gap-md) * -1);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
// Disable horizontal stretch
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-info-section {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
gap: var(--gap-md);
|
||||||
|
|
||||||
|
:global(.animated-dropdown) {
|
||||||
|
& > .selected {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-info-item {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: var(--gap-sm);
|
||||||
|
color: var(--color-text-dark);
|
||||||
|
font-size: var(--font-size-md);
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
margin-block: var(--spacing-card-md) var(--spacing-card-sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Modrinth App Ad</title>
|
<title>Modrinth App Ad</title>
|
||||||
<script src="/inmobi.js"></script>
|
<script src="/inmobi.js"></script>
|
||||||
<script src="https://cadmus.script.ac/d14pdm1b7fi5kh/script.js"></script>
|
|
||||||
<script src="https://dn0qt3r0xannq.cloudfront.net/modrinth-7JfmkEIXEp/modrinth-longform/prebid-load.js"></script>
|
<script src="https://dn0qt3r0xannq.cloudfront.net/modrinth-7JfmkEIXEp/modrinth-longform/prebid-load.js"></script>
|
||||||
<link rel="preload" href="https://www.googletagservices.com/tag/js/gpt.js" as="script" />
|
<link rel="preload" href="https://www.googletagservices.com/tag/js/gpt.js" as="script" />
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "theseus"
|
name = "theseus"
|
||||||
version = "0.9.3"
|
version = "0.9.2"
|
||||||
authors = ["Jai A <jaiagr+gpg@pm.me>"]
|
authors = ["Jai A <jaiagr+gpg@pm.me>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
|||||||
@@ -300,8 +300,8 @@ import Chips from './Chips.vue'
|
|||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
modelValue: string
|
modelValue: string
|
||||||
disabled?: boolean
|
disabled: boolean
|
||||||
headingButtons?: boolean
|
headingButtons: boolean
|
||||||
/**
|
/**
|
||||||
* @param file The file to upload
|
* @param file The file to upload
|
||||||
* @throws If the file is invalid or the upload fails
|
* @throws If the file is invalid or the upload fails
|
||||||
@@ -948,8 +948,4 @@ function openVideoModal() {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.cm-content) {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="colorClasses" class="radial-header relative pb-1" v-bind="$attrs">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
<div class="radial-header-divider" />
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
inheritAttrs: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
color?: 'brand' | 'red' | 'orange' | 'green' | 'blue' | 'purple' | 'gray'
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
color: 'brand',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const colorClasses = computed(
|
|
||||||
() =>
|
|
||||||
`--_radial-bg: var(--color-${props.color}-highlight);--_radial-border: var(--color-${props.color});`,
|
|
||||||
)
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.radial-header {
|
|
||||||
background-image: radial-gradient(50% 100% at 50% 100%, var(--_radial-bg) 10%, #ffffff00 100%);
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
#ffffff00 0%,
|
|
||||||
var(--_radial-border) 50%,
|
|
||||||
#ffffff00 100%
|
|
||||||
);
|
|
||||||
width: 100%;
|
|
||||||
height: 1px;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex flex-wrap gap-2">
|
|
||||||
<button
|
|
||||||
v-for="(item, index) in items"
|
|
||||||
:key="`radio-button-${index}`"
|
|
||||||
class="p-0 py-2 px-2 border-0 flex gap-2 transition-all items-center cursor-pointer active:scale-95 hover:bg-button-bg rounded-xl"
|
|
||||||
:class="{
|
|
||||||
'text-contrast font-medium bg-button-bg': selected === item,
|
|
||||||
'text-primary bg-transparent': selected !== item,
|
|
||||||
}"
|
|
||||||
@click="selected = item"
|
|
||||||
>
|
|
||||||
<RadioButtonChecked v-if="selected === item" class="text-brand h-5 w-5" />
|
|
||||||
<RadioButtonIcon v-else class="h-5 w-5" />
|
|
||||||
<slot :item="item" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts" generic="T">
|
|
||||||
import { RadioButtonIcon, RadioButtonChecked } from '@modrinth/assets'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
modelValue: T
|
|
||||||
items: T[]
|
|
||||||
forceSelection?: boolean
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
forceSelection: false,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
|
||||||
|
|
||||||
const selected = computed({
|
|
||||||
get() {
|
|
||||||
return props.modelValue
|
|
||||||
},
|
|
||||||
set(value) {
|
|
||||||
emit('update:modelValue', value)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
if (props.items.length > 0 && props.forceSelection && !props.modelValue) {
|
|
||||||
selected.value = props.items[0]
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -25,8 +25,6 @@ export { default as Pagination } from './base/Pagination.vue'
|
|||||||
export { default as PopoutMenu } from './base/PopoutMenu.vue'
|
export { default as PopoutMenu } from './base/PopoutMenu.vue'
|
||||||
export { default as PreviewSelectButton } from './base/PreviewSelectButton.vue'
|
export { default as PreviewSelectButton } from './base/PreviewSelectButton.vue'
|
||||||
export { default as ProjectCard } from './base/ProjectCard.vue'
|
export { default as ProjectCard } from './base/ProjectCard.vue'
|
||||||
export { default as RadialHeader } from './base/RadialHeader.vue'
|
|
||||||
export { default as RadioButtons } from './base/RadioButtons.vue'
|
|
||||||
export { default as ScrollablePanel } from './base/ScrollablePanel.vue'
|
export { default as ScrollablePanel } from './base/ScrollablePanel.vue'
|
||||||
export { default as SimpleBadge } from './base/SimpleBadge.vue'
|
export { default as SimpleBadge } from './base/SimpleBadge.vue'
|
||||||
export { default as Slider } from './base/Slider.vue'
|
export { default as Slider } from './base/Slider.vue'
|
||||||
|
|||||||
+1
-13
@@ -1,7 +1,7 @@
|
|||||||
export const BASE62_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
export const BASE62_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||||
export type Base62Char = (typeof BASE62_CHARS)[number]
|
export type Base62Char = (typeof BASE62_CHARS)[number]
|
||||||
|
|
||||||
export type ModrinthId = string
|
export type ModrinthId = `${Base62Char}`[]
|
||||||
|
|
||||||
export type Environment = 'required' | 'optional' | 'unsupported' | 'unknown'
|
export type Environment = 'required' | 'optional' | 'unsupported' | 'unknown'
|
||||||
|
|
||||||
@@ -241,15 +241,3 @@ export interface TeamMember {
|
|||||||
payouts_split: number
|
payouts_split: number
|
||||||
ordering: number
|
ordering: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Report = {
|
|
||||||
id: ModrinthId
|
|
||||||
item_id: ModrinthId
|
|
||||||
item_type: 'project' | 'version' | 'user'
|
|
||||||
report_type: string
|
|
||||||
reporter: ModrinthId
|
|
||||||
thread_id: ModrinthId
|
|
||||||
closed: boolean
|
|
||||||
created: string
|
|
||||||
body: string
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user