Skip to content

Commit be13e11

Browse files
authored
Merge pull request #716 from ModWorkshop/main
3.7.1
2 parents 0a936f1 + e1feef8 commit be13e11

11 files changed

Lines changed: 64 additions & 47 deletions

File tree

backend/app/Http/Controllers/FileController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ public function getVersions(Request $request) {
376376
*/
377377
public function registerDownload(Request $request, File $file)
378378
{
379-
ModService::registerDownload($file);
379+
return ModService::registerDownload($file);
380380
}
381381

382382
/**

backend/app/Http/Controllers/TagController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public function index(FilteredRequest $request, Game $game=null)
3333
'global' => 'boolean|nullable'
3434
]);
3535

36+
$val['limit'] ??= 50; // TODO: utilize m-select with fetch more for tags
37+
3638
$cache = [
3739
'key' => 'tags:'.($game ? 'game:'.$game->name : ''),
3840
'ttl' => 120

backend/app/Services/ModService.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,13 @@ public static function registerDownload(File|Link $downloadable)
396396
* @var Builder
397397
*/
398398
$downloads = $downloadable->downloadsRelation();
399-
$alreadyDownloadedFile = $downloads->when(isset($user), fn($q) => $q->where('user_id', $user->id))
400-
->orWhere('ip_address', $ip)
401-
->exists();
399+
$alreadyDownloadedFile = $downloads->where(function($q) use ($user, $ip) {
400+
$q->when(isset($user), fn($q) => $q->where('user_id', $user->id))
401+
->orWhere('ip_address', $ip);
402+
})->exists();
402403

403404
if ($alreadyDownloadedFile) {
404-
return response()->noContent(201);
405+
return response()->noContent(200);
405406
}
406407

407408
// Create download for file or link
@@ -420,7 +421,7 @@ public static function registerDownload(File|Link $downloadable)
420421
})->where('mod_id', $mod->id)->exists();
421422

422423
if ($alreadyDownloadedMod) {
423-
return response()->noContent(201);
424+
return response()->noContent(200);
424425
}
425426

426427
$download = new ModDownload([

frontend/app/components/site/a-user.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:disabled="!showMiniProfile || static"
88
>
99
<m-flex inline :column="column" class="items-center" :gap="neededGap">
10-
<NuxtLink v-if="avatar" class="inline-flex" :to="link">
10+
<NuxtLink v-if="avatar" class="flex shrink-0" :to="link">
1111
<m-avatar :size="avatarSize" :src="user?.avatar" :use-thumb="useThumb" :style="{ opacity: isBanned ? 0.6 : 1 }"/>
1212
</NuxtLink>
1313

frontend/app/components/site/the-comments.vue

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@
5151
</m-flex>
5252
<m-dropdown v-model:open="showMentions" :style="{ left: `${mentionPos[0]}px`, top: `${mentionPos[1]+16}px`, position: 'fixed' }">
5353
<template #content>
54-
<m-flex v-if="users" column class="p-3" style="max-width: 300px; word-break: normal; overflow: hidden;">
55-
<template v-if="users.data.length">
56-
<a-user v-for="u in users.data" :key="u.id" :user="u" avatar static show-at class="cursor-pointer whitespace-pre" @click="e => onClickMention(e, u)"/>
57-
</template>
58-
<div v-else>{{ $t('no_users_found') }}</div>
59-
</m-flex>
54+
<template v-if="users?.data.length">
55+
<m-dropdown-item v-for="u in users.data" :key="u.id">
56+
<a-user :user="u" avatar static show-at @click="e => onClickMention(e, u)"/>
57+
</m-dropdown-item>
58+
</template>
59+
<m-loading v-else-if="usersLoading"/>
60+
<div v-else>{{ $t('no_users_found') }}</div>
6061
</template>
6162
</m-dropdown>
6263
<transition>
@@ -91,7 +92,6 @@
9192

9293
<script setup lang="ts">
9394
import type { Comment, Game, User } from '~/types/models';
94-
import { Paginator } from '~/types/paginator';
9595
import { vIntersectionObserver } from '@vueuse/components';
9696
import { useStore } from '~/store';
9797
import { remove } from '@antfu/utils';
@@ -142,7 +142,6 @@ const editingComment = ref<Comment>();
142142
const mentionPos = ref([0, 0]);
143143
const showMentions = ref(false);
144144
const mentionRange = ref([-1, -1]);
145-
const users = ref<Paginator<User>>();
146145
const usersCache: Record<string, User> = {};
147146
148147
const posting = ref(false);
@@ -162,21 +161,30 @@ const { data: comments, execute: loadComments } = await useFetchMany<Comment>(pr
162161
163162
watch(comments, () => isLoaded.value = !!comments.value, { immediate: true });
164163
165-
let lastTimeout: NodeJS.Timeout;
166-
watch([commentContent, mentionRange], async () => {
167-
if (lastTimeout) {
168-
clearTimeout(lastTimeout);
164+
const query = ref('');
165+
const queryDebounced = refDebounced(query, 200);
166+
const firstTime = ref(true);
167+
const { data: users, loading: usersLoading, refresh } = await useFetchMany<User>('users', {
168+
query: { query: queryDebounced },
169+
watch: [queryDebounced],
170+
immediate: false
171+
});
172+
173+
watch(users, () => {
174+
if (users.value) {
175+
for (const user of users.value.data) {
176+
usersCache[user.unique_name] = user;
177+
}
169178
}
170-
if (showMentions.value) {
171-
const query = commentContent.value.substring(mentionRange.value[0], mentionRange.value[1]);
172-
173-
lastTimeout = setTimeout(async () => {
174-
users.value = undefined;
175-
users.value = await getRequest<Paginator<User>>('users', { query: { query } });
176-
for (const user of users.value.data) {
177-
usersCache[user.unique_name] = user;
178-
}
179-
}, 150);
179+
});
180+
181+
watch([commentContent, mentionRange], async () => {
182+
if (mentionRange.value?.[0] !== undefined) {
183+
query.value = commentContent.value.substring(mentionRange.value[0], mentionRange.value[1]);
184+
if (firstTime.value) {
185+
refresh();
186+
}
187+
firstTime.value = false;
180188
}
181189
});
182190

frontend/app/components/ui/layout/m-nav.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div class="nav">
3-
<m-flex v-if="side" class="items-center hidden max-lg:block" @click="menuOpen = !menuOpen">
3+
<m-flex v-if="side" class="items-center lg:hidden" @click="menuOpen = !menuOpen">
44
<m-link class="collapse-button">
55
<i-mdi-menu/>
66
</m-link>

frontend/app/components/ui/layout/m-tabs.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ if (query) {
181181
border-radius: var(--content-border-radius);
182182
background-color: var(--secondary-content-bg-color);
183183
align-self: start;
184+
width: 100%;
184185
}
185186
186187
.alt-background.tab-menu-bg {

frontend/app/i18n/locales/es.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -641,15 +641,15 @@
641641
"edit_mod_tip_2": "Una vez que estés satisfecho con el mod, puedes publicarlo y permitir que las personas puedan verlo y descargarlo.",
642642
"edit_mod_warn_1": "En algunos casos, los mods (como los de música) requieren aprobación. Si tu mod contiene música, envíalo para su aprobación (más abajo)",
643643
"edit_mod_warn_2": "Debes estar familiarizado con nuestras reglas. Puedes encontrarlas {here}",
644-
"edit_mod_warn_new_user": "As a new user, your first upload must be approved by a moderator. Afterwards you should be able to upload freely.",
644+
"edit_mod_warn_new_user": "Como usuario nuevo, tu primera subida debe ser aprobada por un moderador. Después podrás subir contenido libremente.",
645645
"auto_subscribe_to_mod": "Suscribirse automáticamente a los comentarios de los mods",
646646
"auto_subscribe_to_thread": "Suscribirse automáticamente a los hilos",
647647
"mark_as_answer": "Marcar como respuesta",
648648
"unmark_as_answer": "Desmarcar como respuesta",
649649
"thread_answer": "Este comentario fue elegido como respuesta para la publicación",
650650
"login_required": "Es necesario iniciar sesión",
651651
"manager_site_url": "Enlace del sitio",
652-
"manager_site_url_desc": "Los enlaces al sitio web del Administrador de Mods o al lugar donde se puede conseguir",
652+
"manager_site_url_desc": "Enlace al sitio web del Administrador de Mods o al lugar donde conseguirlo",
653653
"manager_download_url": "Enlace de descarga",
654654
"manager_download_url_desc": "Un enlace para manejar la descarga e instalación de los archivos de los mods. Parámetros disponibles actualmente: :mod_id, :file_id, :game_id, :manager_name y :game_short_name.",
655655
"status": "Estado",
@@ -675,8 +675,8 @@
675675
"unignore": "Dejar de ignorar",
676676
"ignored_games": "Juegos ignorados",
677677
"ignored_mods": "Mods ignorados",
678-
"ignored_categories": "Ignored Categories",
679-
"ignore_category": "Ignore Category",
678+
"ignored_categories": "Categorías ignoradas",
679+
"ignore_category": "Ignorar categoría",
680680
"audit_log": "Registro de auditoría",
681681
"copy_link": "Copiar enlace",
682682
"repository": "Repositorio",
@@ -686,11 +686,11 @@
686686
"hidden_tags_desc": "Oculta las etiquetas globales para que los usuarios no puedan seleccionarlas en los mods o hilos. Si algún mod ya usa estas etiquetas, será necesario actualizarlas manualmente.",
687687
"install_with": "Instalar con {modManager}",
688688
"mod_manager_not_installed": "¿No tienes {modManager}?",
689-
"leave_members": "Leave Members",
690-
"sessions": "Sessions",
691-
"ip_address": "IP Address",
692-
"ip_ban": "IP Ban",
693-
"ip_ban_help": "Bans the user and their IP. Note: this shouldn't really be relied on too much, users can easily change IPs, this is more of a bandage solution.",
694-
"pinned_mods": "Pinned Mods",
695-
"pinned_mods_desc": "Pinned mods appear on top of your regular mod list. You may choose up to 5 mods you own or a mod you are a member of (except viewer)."
689+
"leave_members": "Dejar de ser miembro",
690+
"sessions": "Sesiones",
691+
"ip_address": "Dirección IP",
692+
"ip_ban": "Veto por IP",
693+
"ip_ban_help": "Aplica un veto al usuario y a su IP. Nota: no es un método muy fiable, ya que los usuarios pueden cambiar de IP fácilmente; es más bien una solución temporal.",
694+
"pinned_mods": "Mods fijados",
695+
"pinned_mods_desc": "Los mods fijados aparecen al principio de tu lista de mods. Puedes fijar hasta 5 mods que poseas o de los que seas miembro (excepto como Espectador)."
696696
}

frontend/app/pages/user-settings/index.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<m-avatar size="md" :src="src"/>
1616
</template>
1717
</m-img-uploader>
18-
<m-flex flex>
18+
<m-flex flex wrap gap="3">
1919
<m-input v-model="userForm.name" :label="$t('display_name')" maxlength="30"/>
2020
<m-input v-model="userForm.custom_color" :disabled="!user.has_supporter_perks" :label="true" :desc="$t('custom_color_desc')" type="color">
2121
<template #label>
@@ -77,11 +77,11 @@
7777
</m-input>
7878

7979
<m-select v-model="userForm.show_tag" :options="showTagOptions" :label="$t('show_tag')" :desc="$t('show_tag_desc')"/>
80-
<m-flex>
80+
<m-flex wrap gap="3">
8181
<m-input v-model="userForm.donation_url" :validity="donationValid" :label="$t('donation')" :desc="$t('donation_desc')"/>
8282
<m-input v-model="userForm.custom_title" :label="$t('custom_title')"/>
8383
</m-flex>
84-
<m-flex>
84+
<m-flex wrap gap="3">
8585
<m-input v-model="userForm.private_profile" :label="$t('private_profile')" :desc="$t('private_profile_desc')" type="checkbox"/>
8686
<m-input v-model="userForm.invisible" :label="$t('invisible')" :desc="$t('invisible_desc')" type="checkbox"/>
8787
</m-flex>

frontend/app/utils/mod-helpers.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ export function canSuperUpdate(mod: Mod) {
3434
return (mod.user_id === user.id && hasPermission('create-mods', mod.game)) || hasPermission('manage-mods', mod.game);
3535
}
3636

37-
export function registerDownload(downlaod_type: 'file' | 'link', download: File | Link) {
38-
postRequest(`${downlaod_type}s/${download.id}/register-download`, null);
37+
export function registerDownload(downloadType: 'file' | 'link', download: File | Link) {
38+
const { $mwsAPI } = useNuxtApp();
39+
40+
$mwsAPI(`${downloadType}s/${download.id}/register-download`, {
41+
method: 'POST',
42+
keepalive: true
43+
});
3944
}
4045

4146
// Bare minimum fields required for a list mod to function for optimization purposes.

0 commit comments

Comments
 (0)