Skip to content

Commit 83e45d7

Browse files
authored
refactor: update modpack export modal, exclude /mods/.connector (#6032)
* refactor: update modpack export modal, exclude /mods/.connector * Add slash suffix to folders * prepr * preprr
1 parent 77b30b2 commit 83e45d7

4 files changed

Lines changed: 89 additions & 172 deletions

File tree

Lines changed: 78 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup>
2-
import { PlusIcon, XIcon } from '@modrinth/assets'
2+
import { WrenchIcon,XIcon } from '@modrinth/assets'
33
import {
4+
Accordion,
45
ButtonStyled,
56
Checkbox,
67
commonMessages,
@@ -9,7 +10,7 @@ import {
910
StyledInput,
1011
useVIntl,
1112
} from '@modrinth/ui'
12-
import { open } from '@tauri-apps/plugin-dialog'
13+
import { save } from '@tauri-apps/plugin-dialog'
1314
import { ref } from 'vue'
1415
1516
import { PackageIcon, VersionIcon } from '@/assets/icons'
@@ -40,9 +41,10 @@ const messages = defineMessages({
4041
},
4142
selectFilesLabel: {
4243
id: 'app.export-modal.select-files-label',
43-
defaultMessage: 'Select files and folders to include in pack',
44+
defaultMessage: 'Configure which files are included in this export',
4445
},
4546
exportButton: { id: 'app.export-modal.export-button', defaultMessage: 'Export' },
47+
includeFile: { id: 'app.export-modal.include-file-accessibility-label', defaultMessage: 'Include "{file}"?' },
4648
})
4749
4850
const props = defineProps({
@@ -65,7 +67,6 @@ const exportDescription = ref('')
6567
const versionInput = ref('1.0.0')
6668
const files = ref([])
6769
const folders = ref([])
68-
const showingFiles = ref(false)
6970
7071
const initFiles = async () => {
7172
const newFolders = new Map()
@@ -87,7 +88,12 @@ const initFiles = async () => {
8788
folder.startsWith('modrinth_logs') ||
8889
folder.startsWith('.fabric'),
8990
}))
90-
.filter((pathData) => !pathData.path.includes('.DS_Store'))
91+
.filter(
92+
(pathData) =>
93+
!pathData.path.includes('.DS_Store') &&
94+
pathData.path !== 'mods/.connector' &&
95+
!pathData.path.startsWith('mods/.connector/'),
96+
)
9197
.forEach((pathData) => {
9298
const parent = pathData.path.split(sep).slice(0, -1).join(sep)
9399
if (parent !== '') {
@@ -121,15 +127,20 @@ const exportPack = async () => {
121127
}
122128
})
123129
})
124-
const outputPath = await open({
125-
directory: true,
126-
multiple: false,
130+
const outputPath = await save({
131+
defaultPath: `${nameInput.value} ${versionInput.value}.mrpack`,
132+
filters: [
133+
{
134+
name: 'Modrinth Modpack',
135+
extensions: ['mrpack'],
136+
},
137+
],
127138
})
128139
129140
if (outputPath) {
130141
export_profile_mrpack(
131142
props.instance.path,
132-
outputPath + `/${nameInput.value} ${versionInput.value}.mrpack`,
143+
outputPath,
133144
filesToExport,
134145
versionInput.value,
135146
exportDescription.value,
@@ -142,97 +153,81 @@ const exportPack = async () => {
142153

143154
<template>
144155
<ModalWrapper ref="exportModal" :header="formatMessage(messages.header)">
145-
<div class="modal-body">
146-
<div class="labeled_input">
147-
<p>{{ formatMessage(messages.modpackNameLabel) }}</p>
148-
<StyledInput
149-
v-model="nameInput"
150-
:icon="PackageIcon"
151-
type="text"
152-
:placeholder="formatMessage(messages.modpackNamePlaceholder)"
153-
clearable
154-
/>
155-
</div>
156-
<div class="labeled_input">
157-
<p>{{ formatMessage(messages.versionNumberLabel) }}</p>
158-
<StyledInput
159-
v-model="versionInput"
160-
:icon="VersionIcon"
161-
type="text"
162-
:placeholder="formatMessage(messages.versionNumberPlaceholder)"
163-
clearable
164-
/>
165-
</div>
166-
<div class="adjacent-input">
156+
<div class="flex flex-col gap-4 w-[40rem]">
157+
<div class="grid grid-cols-2 gap-4">
167158
<div class="labeled_input">
168-
<p>{{ formatMessage(commonMessages.descriptionLabel) }}</p>
169-
159+
<p>{{ formatMessage(messages.modpackNameLabel) }}</p>
170160
<StyledInput
171-
v-model="exportDescription"
172-
multiline
173-
:placeholder="formatMessage(messages.descriptionPlaceholder)"
161+
v-model="nameInput"
162+
:icon="PackageIcon"
163+
type="text"
164+
:placeholder="formatMessage(messages.modpackNamePlaceholder)"
165+
clearable
174166
/>
175167
</div>
176-
</div>
177-
178-
<div class="table">
179-
<div class="table-head">
180-
<div class="table-cell row-wise">
181-
{{ formatMessage(messages.selectFilesLabel) }}
182-
<ButtonStyled circular>
183-
<button @click="() => (showingFiles = !showingFiles)">
184-
<PlusIcon v-if="!showingFiles" />
185-
<XIcon v-else />
186-
</button>
187-
</ButtonStyled>
188-
</div>
168+
<div class="labeled_input">
169+
<p>{{ formatMessage(messages.versionNumberLabel) }}</p>
170+
<StyledInput
171+
v-model="versionInput"
172+
:icon="VersionIcon"
173+
type="text"
174+
:placeholder="formatMessage(messages.versionNumberPlaceholder)"
175+
clearable
176+
/>
189177
</div>
190-
<div v-if="showingFiles" class="table-content">
191-
<div v-for="[path, children] in folders" :key="path.name" class="table-row">
192-
<div class="table-cell file-entry">
193-
<div class="file-primary">
178+
</div>
179+
<div class="flex flex-col gap-2">
180+
<p class="m-0">{{ formatMessage(commonMessages.descriptionLabel) }}</p>
181+
<StyledInput
182+
v-model="exportDescription"
183+
multiline
184+
:placeholder="formatMessage(messages.descriptionPlaceholder)"
185+
/>
186+
</div>
187+
<Accordion class="w-full bg-surface-4 border border-solid border-surface-5 rounded-2xl overflow-clip" button-class="p-4 w-full border-b border-solid border-b-surface-5 bg-surface-2 -mb-px hover:brightness-[--hover-brightness] group">
188+
<template #title>
189+
<span class="flex items-center gap-3 text-contrast group-active:scale-[0.98]">
190+
<WrenchIcon aria-hidden="true" class="size-5 text-secondary" />
191+
Configure which files are included in this export
192+
</span>
193+
</template>
194+
<div class="flex flex-col [&>*:nth-child(even)]:bg-surface-3">
195+
<div v-for="[path, children] in folders" :key="path.name" class="flex flex-col">
196+
<Accordion class="flex flex-col" button-class="flex gap-3 pr-4 hover:bg-surface-5 group">
197+
<template #title>
194198
<Checkbox
195199
:model-value="children.every((child) => child.selected)"
196-
:label="path.name"
197-
class="select-checkbox"
200+
:indeterminate="!children.every((child) => child.selected) && children.some((child) => child.selected)"
201+
:description="formatMessage(messages.includeFile, { file: path.name })"
202+
class="pl-4 py-2"
198203
:disabled="children.every((x) => x.disabled)"
199204
@update:model-value="
200205
(newValue) => children.forEach((child) => (child.selected = newValue))
201206
"
207+
@click.stop
202208
/>
209+
<span class="ml-2 group-active:scale-95">{{ path.name }}/</span>
210+
</template>
211+
<div v-for="child in children" :key="child.path">
203212
<Checkbox
204-
v-model="path.showingMore"
205-
class="select-checkbox dropdown"
206-
collapsing-toggle-style
213+
v-model="child.selected"
214+
:label="child.name"
215+
class="w-full px-8 py-2 hover:bg-surface-4 text-primary"
216+
:disabled="child.disabled"
207217
/>
208218
</div>
209-
<div v-if="path.showingMore" class="file-secondary">
210-
<div v-for="child in children" :key="child.path" class="file-secondary-row">
211-
<Checkbox
212-
v-model="child.selected"
213-
:label="child.name"
214-
class="select-checkbox"
215-
:disabled="child.disabled"
216-
/>
217-
</div>
218-
</div>
219-
</div>
220-
</div>
221-
<div v-for="file in files" :key="file.path" class="table-row">
222-
<div class="table-cell file-entry">
223-
<div class="file-primary">
224-
<Checkbox
225-
v-model="file.selected"
226-
:label="file.name"
227-
:disabled="file.disabled"
228-
class="select-checkbox"
229-
/>
230-
</div>
231-
</div>
219+
</Accordion>
232220
</div>
221+
<Checkbox
222+
v-for="file in files" :key="file.path"
223+
v-model="file.selected"
224+
:label="file.name"
225+
:disabled="file.disabled"
226+
class="w-full px-4 py-2 hover:bg-surface-4 text-primary"
227+
/>
233228
</div>
234-
</div>
235-
<div class="button-row push-right">
229+
</Accordion>
230+
<div class="flex items-center justify-end gap-2">
236231
<ButtonStyled type="outlined">
237232
<button @click="exportModal.hide">
238233
<XIcon />
@@ -249,83 +244,3 @@ const exportPack = async () => {
249244
</div>
250245
</ModalWrapper>
251246
</template>
252-
253-
<style scoped lang="scss">
254-
.modal-body {
255-
display: flex;
256-
flex-direction: column;
257-
gap: var(--gap-md);
258-
}
259-
260-
.labeled_input {
261-
display: flex;
262-
flex-direction: column;
263-
gap: var(--gap-sm);
264-
265-
p {
266-
margin: 0;
267-
}
268-
}
269-
270-
.select-checkbox {
271-
gap: var(--gap-sm);
272-
273-
button.checkbox {
274-
border: none;
275-
}
276-
277-
&.dropdown {
278-
margin-left: auto;
279-
}
280-
}
281-
282-
.table-content {
283-
max-height: 18rem;
284-
overflow-y: auto;
285-
}
286-
287-
.table {
288-
border: 1px solid var(--color-bg);
289-
}
290-
291-
.file-entry {
292-
display: flex;
293-
flex-direction: column;
294-
gap: var(--gap-sm);
295-
}
296-
297-
.file-primary {
298-
display: flex;
299-
align-items: center;
300-
gap: var(--gap-sm);
301-
}
302-
303-
.file-secondary {
304-
margin-left: var(--gap-xl);
305-
display: flex;
306-
flex-direction: column;
307-
gap: var(--gap-sm);
308-
height: 100%;
309-
vertical-align: center;
310-
}
311-
312-
.file-secondary-row {
313-
display: flex;
314-
align-items: center;
315-
gap: var(--gap-sm);
316-
}
317-
318-
.button-row {
319-
display: flex;
320-
gap: var(--gap-sm);
321-
align-items: center;
322-
}
323-
324-
.row-wise {
325-
display: flex;
326-
flex-direction: row;
327-
justify-content: space-between;
328-
align-items: center;
329-
gap: 1rem;
330-
}
331-
</style>

apps/app-frontend/src/locales/en-US/index.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,17 @@
164164
"app.export-modal.header": {
165165
"message": "Export modpack"
166166
},
167+
"app.export-modal.include-file-accessibility-label": {
168+
"message": "Include \"{file}\"?"
169+
},
167170
"app.export-modal.modpack-name-label": {
168171
"message": "Modpack Name"
169172
},
170173
"app.export-modal.modpack-name-placeholder": {
171174
"message": "Modpack name"
172175
},
173176
"app.export-modal.select-files-label": {
174-
"message": "Select files and folders to include in pack"
177+
"message": "Configure which files are included in this export"
175178
},
176179
"app.export-modal.version-number-label": {
177180
"message": "Version number"

packages/assets/generated-icons.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import type { FunctionalComponent, SVGAttributes } from 'vue'
55

6+
export type IconComponent = FunctionalComponent<SVGAttributes>
7+
68
import _AffiliateIcon from './icons/affiliate.svg?component'
79
import _AlignLeftIcon from './icons/align-left.svg?component'
810
import _ArchiveIcon from './icons/archive.svg?component'
@@ -395,8 +397,6 @@ import _XCircleIcon from './icons/x-circle.svg?component'
395397
import _ZoomInIcon from './icons/zoom-in.svg?component'
396398
import _ZoomOutIcon from './icons/zoom-out.svg?component'
397399

398-
export type IconComponent = FunctionalComponent<SVGAttributes>
399-
400400
export const AffiliateIcon = _AffiliateIcon
401401
export const AlignLeftIcon = _AlignLeftIcon
402402
export const ArchiveIcon = _ArchiveIcon

packages/ui/src/components/base/Checkbox.vue

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
>
1515
<span
1616
class="w-5 h-5 rounded-md flex items-center justify-center border-[1px] border-solid"
17-
:class="
18-
(modelValue
19-
? 'bg-brand border-button-border text-brand-inverted'
20-
: 'bg-surface-2 border-surface-5') +
21-
(disabled ? '' : ' checkbox-shadow group-active:scale-95')
22-
"
17+
:class="{
18+
'bg-brand border-button-border text-brand-inverted': modelValue,
19+
'bg-surface-2 border-surface-5 text-primary': !modelValue,
20+
'checkbox-shadow group-active:scale-95': disabled,
21+
}"
2322
>
2423
<MinusIcon v-if="indeterminate" aria-hidden="true" stroke-width="3" />
2524
<CheckIcon v-else-if="modelValue" aria-hidden="true" stroke-width="3" />

0 commit comments

Comments
 (0)