Compare commits

..

1 Commits

Author SHA1 Message Date
Alejandro González
bc17b4b526 feat(labrinth): allow editing loader fields in bulk in v3 project PATCH 2025-08-08 02:05:57 +02:00
5 changed files with 71 additions and 67 deletions

View File

@@ -4,7 +4,7 @@ root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
@@ -13,3 +13,6 @@ max_line_length = 100
[*.md]
max_line_length = off
trim_trailing_whitespace = false
[*.{rs,java,kts}]
indent_size = 4

View File

@@ -1,67 +1,41 @@
; https://nsis.sourceforge.io/ShellExecWait
!macro ShellExecWait verb app param workdir show exitoutvar ;only app and show must be != "", every thing else is optional
#define SEE_MASK_NOCLOSEPROCESS 0x40
System::Store S
!if "${NSIS_PTR_SIZE}" > 4
!define /ReDef /math SYSSIZEOF_SHELLEXECUTEINFO 14 * ${NSIS_PTR_SIZE}
!else ifndef SYSSIZEOF_SHELLEXECUTEINFO
!define SYSSIZEOF_SHELLEXECUTEINFO 60
!endif
System::Call '*(&i${SYSSIZEOF_SHELLEXECUTEINFO})i.r0'
System::Call '*$0(i ${SYSSIZEOF_SHELLEXECUTEINFO},i 0x40,p $hwndparent,t "${verb}",t $\'${app}$\',t $\'${param}$\',t "${workdir}",i ${show})p.r0'
System::Call 'shell32::ShellExecuteEx(t)(pr0)i.r1 ?e' ; (t) to trigger A/W selection
${If} $1 <> 0
System::Call '*$0(is,i,p,p,p,p,p,p,p,p,p,p,p,p,p.r1)' ;stack value not really used, just a fancy pop ;)
System::Call 'kernel32::WaitForSingleObject(pr1,i-1)'
System::Call 'kernel32::GetExitCodeProcess(pr1,*i.s)'
System::Call 'kernel32::CloseHandle(pr1)'
${EndIf}
System::Free $0
!if "${exitoutvar}" == ""
pop $0
!endif
System::Store L
!if "${exitoutvar}" != ""
pop ${exitoutvar}
!endif
!macroend
; --------------------------------------------------------------------------------
Var /GLOBAL OldInstallDir
!macro NSIS_HOOK_PREINSTALL
SetShellVarContext all
${If} ${FileExists} "$SMPROGRAMS\${PRODUCTNAME}.lnk"
UserInfo::GetAccountType
Pop $0
${If} $0 != "Admin"
MessageBox MB_ICONINFORMATION|MB_OK "An old installation of the Modrinth App was detected that requires administrator permission to update from. You will be prompted with an admin prompt shortly."
${EndIf}
ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
ReadRegStr $OldInstallDir SHCTX "${UNINSTKEY}" "InstallLocation"
StrCpy $OldInstallDir $OldInstallDir "" 1
StrCpy $OldInstallDir $OldInstallDir -1 ""
DetailPrint "Executing $R1"
!insertmacro ShellExecWait "runas" '$R1' '/P _?=$4' "" ${SW_SHOW} $3
${If} $3 <> 0
SetErrorLevel $3
MessageBox MB_ICONEXCLAMATION|MB_OK "Failed to uninstall old global installation"
Abort
${EndIf}
${EndIf}
SetShellVarContext current
!macroend
!macro NSIS_HOOK_POSTINSTALL
!insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$OldInstallDir\${MAINBINARYNAME}.exe"
Pop $0
${If} $0 = 1
!insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
Return
${EndIf}
SetShellVarContext current
IfFileExists "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe" file_found file_not_found
file_found:
Delete "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
Delete "$LOCALAPPDATA${PRODUCTNAME}\uninstall.exe"
RMDir "$LOCALAPPDATA${PRODUCTNAME}"
!insertmacro DeleteAppUserModelId
; Remove start menu shortcut
!insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder
!insertmacro IsShortcutTarget "$SMPROGRAMS$AppStartMenuFolder${PRODUCTNAME}.lnk" "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$SMPROGRAMS$AppStartMenuFolder${PRODUCTNAME}.lnk"
Delete "$SMPROGRAMS$AppStartMenuFolder${PRODUCTNAME}.lnk"
RMDir "$SMPROGRAMS$AppStartMenuFolder"
${EndIf}
!insertmacro IsShortcutTarget "$SMPROGRAMS${PRODUCTNAME}.lnk" "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$SMPROGRAMS${PRODUCTNAME}.lnk"
Delete "$SMPROGRAMS${PRODUCTNAME}.lnk"
${EndIf}
!insertmacro IsShortcutTarget "$DESKTOP${PRODUCTNAME}.lnk" "$LOCALAPPDATA${PRODUCTNAME}\theseus_gui.exe"
Pop $0
${If} $0 = 1
!insertmacro UnpinShortcut "$DESKTOP${PRODUCTNAME}.lnk"
Delete "$DESKTOP${PRODUCTNAME}.lnk"
${EndIf}
DeleteRegKey HKCU "${UNINSTKEY}"
goto end_of_test ;<== important for not continuing on the else branch
file_not_found:
end_of_test:
!macroend

View File

@@ -15,6 +15,7 @@
"icon": ["icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"],
"windows": {
"nsis": {
"installMode": "perMachine",
"installerHooks": "./nsis/hooks.nsi"
}
},

View File

@@ -512,6 +512,7 @@ pub async fn project_edit(
moderation_message_body: v2_new_project.moderation_message_body,
monetization_status: v2_new_project.monetization_status,
side_types_migration_review_status: None, // Not to be exposed in v2
loader_fields: HashMap::new(), // Loader fields are not a thing in v2
};
// This returns 204 or failure so we don't need to do anything with it

View File

@@ -11,7 +11,7 @@ use crate::database::redis::RedisPool;
use crate::database::{self, models as db_models};
use crate::file_hosting::{FileHost, FileHostPublicity};
use crate::models;
use crate::models::ids::ProjectId;
use crate::models::ids::{ProjectId, VersionId};
use crate::models::images::ImageContext;
use crate::models::notifications::NotificationBody;
use crate::models::pats::Scopes;
@@ -250,6 +250,8 @@ pub struct EditProject {
pub monetization_status: Option<MonetizationStatus>,
pub side_types_migration_review_status:
Option<SideTypesMigrationReviewStatus>,
#[serde(flatten)]
pub loader_fields: HashMap<String, serde_json::Value>,
}
#[allow(clippy::too_many_arguments)]
@@ -870,6 +872,29 @@ pub async fn project_edit(
.await?;
}
if !new_project.loader_fields.is_empty() {
for version in db_models::DBVersion::get_many(
&project_item.versions,
&**pool,
&redis,
)
.await?
{
super::versions::version_edit_helper(
req.clone(),
(VersionId::from(version.inner.id),),
pool.clone(),
redis.clone(),
super::versions::EditVersion {
fields: new_project.loader_fields.clone(),
..Default::default()
},
session_queue.clone(),
)
.await?;
}
}
// check new description and body for links to associated images
// if they no longer exist in the description or body, delete them
let checkable_strings: Vec<&str> =