From bca467a634393a93560ec524a5e1727a63fdbed3 Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:27:59 -0700 Subject: [PATCH 01/62] Add coventry europe region support (#3956) * Add coventry europe region support, rename germany EU location to central europe * extract messages * extract messages again --- apps/frontend/src/locales/en-US/index.json | 6 +++--- .../src/components/billing/ServersPurchase1Region.vue | 2 +- packages/ui/src/locales/en-US/index.json | 9 ++++++--- packages/ui/src/utils/regions.ts | 10 +++++----- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index 21580977..828e3ffd 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -383,15 +383,15 @@ "layout.footer.about": { "message": "About" }, - "layout.footer.about.news": { - "message": "News" - }, "layout.footer.about.careers": { "message": "Careers" }, "layout.footer.about.changelog": { "message": "Changelog" }, + "layout.footer.about.news": { + "message": "News" + }, "layout.footer.about.rewards-program": { "message": "Rewards Program" }, diff --git a/packages/ui/src/components/billing/ServersPurchase1Region.vue b/packages/ui/src/components/billing/ServersPurchase1Region.vue index 3f2bdc59..4a1f2fc5 100644 --- a/packages/ui/src/components/billing/ServersPurchase1Region.vue +++ b/packages/ui/src/components/billing/ServersPurchase1Region.vue @@ -40,7 +40,7 @@ const selectedPrice = computed(() => { return amount ? amount / monthsInInterval[props.interval] : undefined }) -const regionOrder: string[] = ['us-vin', 'eu-lim'] +const regionOrder: string[] = ['us-vin', 'eu-cov', 'eu-lim'] const sortedRegions = computed(() => { return props.regions.slice().sort((a, b) => { diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json index e6088508..23e95048 100644 --- a/packages/ui/src/locales/en-US/index.json +++ b/packages/ui/src/locales/en-US/index.json @@ -512,12 +512,12 @@ "servers.purchase.step.review.title": { "defaultMessage": "Review" }, + "servers.region.central-europe": { + "defaultMessage": "Central Europe" + }, "servers.region.custom.prompt": { "defaultMessage": "How much RAM do you want your server to have?" }, - "servers.region.europe": { - "defaultMessage": "Europe" - }, "servers.region.north-america": { "defaultMessage": "North America" }, @@ -527,6 +527,9 @@ "servers.region.region-unsupported": { "defaultMessage": "Region not listed? Let us know where you'd like to see Modrinth Servers next!" }, + "servers.region.western-europe": { + "defaultMessage": "Western Europe" + }, "settings.account.title": { "defaultMessage": "Account and security" }, diff --git a/packages/ui/src/utils/regions.ts b/packages/ui/src/utils/regions.ts index 5167a291..4401734f 100644 --- a/packages/ui/src/utils/regions.ts +++ b/packages/ui/src/utils/regions.ts @@ -6,11 +6,11 @@ export const regionOverrides = { flag: 'https://flagcdn.com/us.svg', }, 'eu-lim': { - name: defineMessage({ id: 'servers.region.europe', defaultMessage: 'Europe' }), - flag: 'https://flagcdn.com/eu.svg', + name: defineMessage({ id: 'servers.region.central-europe', defaultMessage: 'Central Europe' }), + flag: 'https://flagcdn.com/de.svg', }, - 'de-fra': { - name: defineMessage({ id: 'servers.region.europe', defaultMessage: 'Europe' }), - flag: 'https://flagcdn.com/eu.svg', + 'eu-cov': { + name: defineMessage({ id: 'servers.region.western-europe', defaultMessage: 'Western Europe' }), + flag: 'https://flagcdn.com/gb.svg', }, } satisfies Record From 72284997371c5341bb1e100bdab5d9dab261f551 Mon Sep 17 00:00:00 2001 From: tippfehlr Date: Thu, 10 Jul 2025 00:30:11 +0200 Subject: [PATCH 02/62] fix(theseus-gui): fix sort/group by game version (#1250) * fix(theseus-gui): fix sort/group by game version In the Library, game version 1.8.9 is sorted/grouped after 1.20 because the default sorting sorts 2 < 8 therefore localeCompare(with numeric=true) is needed, it detects 8 < 20 and puts the versions in the correct order. * lint --------- Co-authored-by: Prospector --- apps/app-frontend/src/components/GridDisplay.vue | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/app-frontend/src/components/GridDisplay.vue b/apps/app-frontend/src/components/GridDisplay.vue index 6e5dac5d..2ced2956 100644 --- a/apps/app-frontend/src/components/GridDisplay.vue +++ b/apps/app-frontend/src/components/GridDisplay.vue @@ -136,7 +136,7 @@ const filteredResults = computed(() => { if (sortBy.value === 'Game version') { instances.sort((a, b) => { - return a.game_version.localeCompare(b.game_version) + return a.game_version.localeCompare(b.game_version, undefined, { numeric: true }) }) } @@ -213,6 +213,17 @@ const filteredResults = computed(() => { instanceMap.set(entry[0], entry[1]) }) } + // default sorting would do 1.20.4 < 1.8.9 because 2 < 8 + // localeCompare with numeric=true puts 1.8.9 < 1.20.4 because 8 < 20 + if (group.value === 'Game version') { + const sortedEntries = [...instanceMap.entries()].sort((a, b) => { + return a[0].localeCompare(b[0], undefined, { numeric: true }) + }) + instanceMap.clear() + sortedEntries.forEach((entry) => { + instanceMap.set(entry[0], entry[1]) + }) + } return instanceMap }) From fadf475f066a6b710cfa8ef13c2802e1db162a03 Mon Sep 17 00:00:00 2001 From: Erb3 <49862976+piprett@users.noreply.github.com> Date: Thu, 10 Jul 2025 00:51:46 +0200 Subject: [PATCH 03/62] docs(frontend): add security.txt (#2252) * feat: add security.txt Security.txt is a well-known (pun intended) file among security researchers, so they don't have to go scavenging for your security information. More information is available on [securitytxt.org](https://securitytxt.org/). I've set the following values: - The email to contact with issues, `jai@modrinth.com`. This is the email stated in the security policy. If you wish to not include it here due to spam, you should also not have it as a `mailto` link in the security policy. - Expiry is set to 2030. By this time Modrinth has become the biggest Minecraft mod distributor, and having expanded into other games. By this time they should also have updated this file. - English is the preferred language - The file is located at modrinth.com/.well-known/security.txt - The security policy is at https://modrinth.com/legal/security The following values have been left unset: - PGP key, not sure where this would be located, if there is one - Acknowledgments. Modrinth does currently not have a site for thanks - Hiring, as it wants security-related positions - CSAF, a Common Security Advisory Framework ? * fix(docs): reduce security.txt expiry This addresses a concern where the security.txt has a long expiration date. Someone could treat this as "use this until then", which we don't want since it's a long time. The specification recommends no longer than one year, as it is to mark as stale. From the RFC: > The "Expires" field indicates the date and time after which the data contained in the "security.txt" file is considered stale and should not be used (as per Section 5.3). The value of this field is formatted according to the Internet profiles of [ISO.8601-1] and [ISO.8601-2] as defined in [RFC3339]. It is RECOMMENDED that the value of this field be less than a year into the future to avoid staleness. Signed-off-by: Erb3 <49862976+Erb3@users.noreply.github.com> * fix(frontend): extend security.txt expiry It takes so long to merge the PR :( Signed-off-by: Erb3 <49862976+Erb3@users.noreply.github.com> * docs(frontend) careers link in security.txt Signed-off-by: Erb3 <49862976+Erb3@users.noreply.github.com> --------- Signed-off-by: Erb3 <49862976+Erb3@users.noreply.github.com> Co-authored-by: Erb3 <49862976+Erb3@users.noreply.github.com> --- apps/frontend/src/public/.well-known/security.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 apps/frontend/src/public/.well-known/security.txt diff --git a/apps/frontend/src/public/.well-known/security.txt b/apps/frontend/src/public/.well-known/security.txt new file mode 100644 index 00000000..1e1a1626 --- /dev/null +++ b/apps/frontend/src/public/.well-known/security.txt @@ -0,0 +1,6 @@ +Contact: mailto:jai@modrinth.com +Expires: 2025-12-31T00:00:00.000Z +Preferred-Languages: en +Canonical: https://modrinth.com/.well-known/security.txt +Policy: https://modrinth.com/legal/security +Hiring: https://careers.modrinth.com/ From cff3c72f9482e9a95a8990038d21c7e7c82b1ac7 Mon Sep 17 00:00:00 2001 From: ToBinio Date: Thu, 10 Jul 2025 00:59:59 +0200 Subject: [PATCH 04/62] feat(theseus): add snapPoints for memory sliders (#1275) * feat: add snapPoints for memory sliders * fix lint * Reapply changes * Hide snap point display when disabled * fix unused imports --------- Co-authored-by: Prospector --- .../ui/instance_settings/JavaSettings.vue | 6 ++++-- .../ui/settings/DefaultInstanceSettings.vue | 7 ++++--- .../src/composables/useMemorySlider.js | 21 +++++++++++++++++++ packages/ui/src/components/base/Slider.vue | 2 +- 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 apps/app-frontend/src/composables/useMemorySlider.js diff --git a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue index 7867791a..cd1b58d3 100644 --- a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue +++ b/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue @@ -6,9 +6,9 @@ import { edit, get_optimal_jre_key } from '@/helpers/profile' import { handleError } from '@/store/notifications' import { defineMessages, useVIntl } from '@vintl/vintl' import JavaSelector from '@/components/ui/JavaSelector.vue' -import { get_max_memory } from '@/helpers/jre' import { get } from '@/helpers/settings.ts' import type { InstanceSettingsTabProps, AppSettings, MemorySettings } from '../../../helpers/types' +import useMemorySlider from '@/composables/useMemorySlider' const { formatMessage } = useVIntl() @@ -34,7 +34,7 @@ const envVars = ref( const overrideMemorySettings = ref(!!props.instance.memory) const memory = ref(props.instance.memory ?? globalSettings.memory) -const maxMemory = Math.floor((await get_max_memory().catch(handleError)) / 1024) +const { maxMemory, snapPoints } = await useMemorySlider() const editProfileObject = computed(() => { const editProfile: { @@ -156,6 +156,8 @@ const messages = defineMessages({ :min="512" :max="maxMemory" :step="64" + :snap-points="snapPoints" + :snap-range="512" unit="MB" />

diff --git a/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue b/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue index ac43fb48..4b6a91bf 100644 --- a/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue +++ b/apps/app-frontend/src/components/ui/settings/DefaultInstanceSettings.vue @@ -1,9 +1,8 @@ + + diff --git a/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue b/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue new file mode 100644 index 00000000..ff5db66a --- /dev/null +++ b/apps/frontend/src/components/ui/moderation/ModpackPermissionsFlow.vue @@ -0,0 +1,424 @@ + + + + + diff --git a/apps/frontend/src/components/ui/moderation/NewModerationChecklist.vue b/apps/frontend/src/components/ui/moderation/NewModerationChecklist.vue new file mode 100644 index 00000000..c8ccab6f --- /dev/null +++ b/apps/frontend/src/components/ui/moderation/NewModerationChecklist.vue @@ -0,0 +1,1246 @@ + + + + + diff --git a/apps/frontend/src/composables/util.ts b/apps/frontend/src/composables/util.ts new file mode 100644 index 00000000..5bf1f4dd --- /dev/null +++ b/apps/frontend/src/composables/util.ts @@ -0,0 +1,12 @@ +export const useNotificationRightwards = () => { + const isVisible = useState("moderation-checklist-notifications", () => false); + + const setVisible = (visible: boolean) => { + isVisible.value = visible; + }; + + return { + isVisible: readonly(isVisible), + setVisible, + }; +}; diff --git a/apps/frontend/src/pages/[type]/[id].vue b/apps/frontend/src/pages/[type]/[id].vue index cf25969b..0b51f73b 100644 --- a/apps/frontend/src/pages/[type]/[id].vue +++ b/apps/frontend/src/pages/[type]/[id].vue @@ -470,10 +470,14 @@ class="new-page sidebar" :class="{ 'alt-layout': cosmetics.leftContentLayout, - 'ultimate-sidebar': + 'checklist-open': showModerationChecklist && !collapsedModerationChecklist && !flags.alwaysShowChecklistAsPopup, + 'checklist-collapsed': + showModerationChecklist && + collapsedModerationChecklist && + !flags.alwaysShowChecklistAsPopup, }" >
@@ -878,7 +882,8 @@ />
- +
+
+ +
\ No newline at end of file diff --git a/apps/app-frontend/src/helpers/update.js b/apps/app-frontend/src/helpers/update.js index cea6c6bd..f7033b7a 100644 --- a/apps/app-frontend/src/helpers/update.js +++ b/apps/app-frontend/src/helpers/update.js @@ -1,6 +1,6 @@ import { ref } from 'vue' import { getVersion } from '@tauri-apps/api/app' -import { getArtifact, getOS } from '@/helpers/utils.js' +import { initUpdateLauncher, getOS } from '@/helpers/utils.js' export const allowState = ref(false) export const installState = ref(false) @@ -52,7 +52,7 @@ export async function getRemote(isDownloadState) { installState.value = true; const builds = remoteData.assets; const fileName = getInstaller(getExtension(), builds); - result = fileName ? await getArtifact(fileName[1], fileName[0], currentOS.value, true) : false; + result = fileName ? await initUpdateLauncher(fileName[1], fileName[0], currentOS.value, true) : false; installState.value = false; } diff --git a/apps/app-frontend/src/helpers/utils.js b/apps/app-frontend/src/helpers/utils.js index ac950e17..99cbde38 100644 --- a/apps/app-frontend/src/helpers/utils.js +++ b/apps/app-frontend/src/helpers/utils.js @@ -11,9 +11,9 @@ export async function getOS() { } // [AR] Feature -export async function getArtifact(downloadurl, filename, ostype, autoupdatesupported) { +export async function initUpdateLauncher(downloadurl, filename, ostype, autoupdatesupported) { console.log('Downloading build', downloadurl, filename, ostype, autoupdatesupported) - return await invoke('plugin:utils|get_artifact', { downloadurl, filename, ostype, autoupdatesupported }) + return await invoke('plugin:utils|init_update_launcher', { downloadurl, filename, ostype, autoupdatesupported }) } // [AR] Patch fix @@ -21,6 +21,11 @@ export async function applyMigrationFix(eol) { return await invoke('plugin:utils|apply_migration_fix', { eol }) } +// [AR] Feature +export async function initAuthlibPatching(minecraftversion, ismojang) { + return await invoke('plugin:utils|init_authlib_patching', { minecraftversion, ismojang }) +} + export async function openPath(path) { return await invoke('plugin:utils|open_path', { path }) } diff --git a/apps/app/build.rs b/apps/app/build.rs index 4942497a..5a35c88d 100644 --- a/apps/app/build.rs +++ b/apps/app/build.rs @@ -218,8 +218,9 @@ fn main() { "utils", InlinedPlugin::new() .commands(&[ + "init_authlib_patching", "apply_migration_fix", - "get_artifact", + "init_update_launcher", "get_os", "should_disable_mouseover", "highlight_in_folder", diff --git a/apps/app/src/api/utils.rs b/apps/app/src/api/utils.rs index 45207915..951affa6 100644 --- a/apps/app/src/api/utils.rs +++ b/apps/app/src/api/utils.rs @@ -10,14 +10,15 @@ use crate::api::{Result, TheseusSerializableError}; use dashmap::DashMap; use std::path::{Path, PathBuf}; use theseus::prelude::canonicalize; -use url::Url; use theseus::util::utils; +use url::Url; pub fn init() -> tauri::plugin::TauriPlugin { tauri::plugin::Builder::new("utils") .invoke_handler(tauri::generate_handler![ + init_authlib_patching, apply_migration_fix, - get_artifact, + init_update_launcher, get_os, should_disable_mouseover, highlight_in_folder, @@ -29,6 +30,17 @@ pub fn init() -> tauri::plugin::TauriPlugin { .build() } +/// [AR] Feature +#[tauri::command] +pub async fn init_authlib_patching( + minecraftversion: &str, + ismojang: bool, +) -> Result { + let result = + utils::init_authlib_patching(minecraftversion, ismojang).await?; + Ok(result) +} + /// [AR] Patch fix #[tauri::command] pub async fn apply_migration_fix(eol: &str) -> Result { @@ -38,8 +50,19 @@ pub async fn apply_migration_fix(eol: &str) -> Result { /// [AR] Feature #[tauri::command] -pub async fn get_artifact(downloadurl: &str, filename: &str, ostype: &str, autoupdatesupported: bool) -> Result<()> { - let _ = utils::init_download(downloadurl, filename, ostype, autoupdatesupported).await; +pub async fn init_update_launcher( + downloadurl: &str, + filename: &str, + ostype: &str, + autoupdatesupported: bool, +) -> Result<()> { + let _ = utils::init_update_launcher( + downloadurl, + filename, + ostype, + autoupdatesupported, + ) + .await; Ok(()) } diff --git a/apps/app/tauri.conf.json b/apps/app/tauri.conf.json index 4ebb2aa5..cfc27156 100644 --- a/apps/app/tauri.conf.json +++ b/apps/app/tauri.conf.json @@ -41,7 +41,7 @@ ] }, "productName": "AstralRinth App", - "version": "0.10.303", + "version": "0.10.304", "mainBinaryName": "AstralRinth App", "identifier": "AstralRinthApp", "plugins": { diff --git a/packages/app-lib/src/error.rs b/packages/app-lib/src/error.rs index 75c144f5..360984ef 100644 --- a/packages/app-lib/src/error.rs +++ b/packages/app-lib/src/error.rs @@ -151,6 +151,41 @@ pub enum ErrorKind { "A skin texture must have a dimension of either 64x64 or 64x32 pixels" )] InvalidSkinTexture, + + #[error( + "[AR] Target minecraft {minecraft_version} version doesn't exist." + )] + InvalidMinecraftVersion { + minecraft_version: String, + }, + + #[error( + "[AR] Target metadata not found for minecraft version {minecraft_version}." + )] + MinecraftMetadataNotFound { + minecraft_version: String, + }, + + #[error( + "[AR] Network error: {error}" + )] + NetworkErrorOccurred { + error: String, + }, + + #[error( + "[AR] IO error: {error}" + )] + IOErrorOccurred { + error: String, + }, + + #[error( + "[AR] Parse error: {reason}" + )] + ParseError { + reason: String, + }, } #[derive(Debug)] diff --git a/packages/app-lib/src/launcher/mod.rs b/packages/app-lib/src/launcher/mod.rs index f1b5deb8..a7d0708e 100644 --- a/packages/app-lib/src/launcher/mod.rs +++ b/packages/app-lib/src/launcher/mod.rs @@ -633,6 +633,7 @@ pub async fn launch_minecraft( command.arg("--add-opens=jdk.internal/jdk.internal.misc=ALL-UNNAMED"); } + // FIXME: Fix ElyBy integration with this patch. // [AR] Patch if credentials.access_token == "null" && credentials.refresh_token == "null" { if version_jar == "1.16.4" || version_jar == "1.16.5" { diff --git a/packages/app-lib/src/util/utils.rs b/packages/app-lib/src/util/utils.rs index adebc3a6..e4d9a2ab 100644 --- a/packages/app-lib/src/util/utils.rs +++ b/packages/app-lib/src/util/utils.rs @@ -1,12 +1,12 @@ -/// -/// [AR] Feature -/// -use crate::Result; use crate::api::update; use crate::state::db; +/// +/// [AR] Feature Utils +/// +use crate::{Result, State}; use serde::{Deserialize, Serialize}; use std::process; -use tokio::io; +use tokio::{fs, io}; const PACKAGE_JSON_CONTENT: &str = // include_str!("../../../../apps/app-frontend/package.json"); @@ -17,13 +17,311 @@ pub struct Launcher { pub version: String, } -pub fn read_package_json() -> io::Result { - // Deserialize the content of package.json into a Launcher struct - let launcher: Launcher = serde_json::from_str(PACKAGE_JSON_CONTENT)?; +#[derive(Debug, Deserialize)] +struct Artifact { + path: Option, + sha1: Option, + url: Option, +} +#[derive(Debug, Deserialize)] +struct Downloads { + artifact: Option, +} + +#[derive(Debug, Deserialize)] +struct Library { + name: String, + downloads: Option, +} + +#[derive(Debug, Deserialize)] +struct VersionJson { + libraries: Vec, +} + +/// Deserialize the content of package.json into a Launcher struct +pub fn read_package_json() -> io::Result { + let launcher: Launcher = serde_json::from_str(PACKAGE_JSON_CONTENT)?; Ok(launcher) } +/// ### AR • Universal Write (IO) Function +/// Saves the downloaded bytes to the `libraries` directory using the given relative path. +async fn write_file_to_libraries( + relative_path: &str, + bytes: &bytes::Bytes, +) -> Result<()> { + let state = State::get().await?; + let output_path = state.directories.libraries_dir().join(relative_path); + + fs::write(&output_path, bytes).await.map_err(|e| { + tracing::error!("[AR] • Failed to save file: {:?}", e); + crate::ErrorKind::IOErrorOccurred { + error: format!("Failed to save file: {e}"), + } + .as_error() + }) +} + +/// ### AR • AuthLib (Ely By) +/// Initializes the AuthLib patching process. +/// +/// Returns `true` if the authlib patched successfully. +pub async fn init_authlib_patching( + minecraft_version: &str, + is_mojang: bool, +) -> Result { + let minecraft_library_metadata = get_minecraft_library_metadata(minecraft_version).await?; + // Parses the AuthLib version from string + // Example output: "com.mojang:authlib:6.0.58" -> "6.0.58" + let authlib_version = minecraft_library_metadata.name.split(':').nth(2).unwrap_or("unknown"); + + tracing::info!( + "[AR] • Attempting to download AuthLib {}.", + authlib_version + ); + + download_authlib( + &minecraft_library_metadata, + authlib_version, + minecraft_version, + is_mojang, + ) + .await +} + +/// ### AR • AuthLib (Ely By) +/// Downloads the AuthLib file from Mojang libraries or Git Astralium services. +async fn download_authlib( + minecraft_library_metadata: &Library, + authlib_version: &str, + minecraft_version: &str, + is_mojang: bool, +) -> Result { + let state = State::get().await?; + let (url, path) = extract_download_info(minecraft_library_metadata, minecraft_version)?; + let mut download_url = url.to_string(); + let full_path = state.directories.libraries_dir().join(path); + + if !is_mojang { + tracing::info!( + "[AR] • Attempting to download AuthLib from Git Astralium" + ); + download_url = extract_ely_authlib_url(authlib_version).await?; + } + tracing::info!("[AR] • Downloading AuthLib from URL: {}", download_url); + let bytes = fetch_bytes_from_url(&download_url).await?; + tracing::info!("[AR] • Will save to path: {}", full_path.to_str().unwrap()); + write_file_to_libraries(full_path.to_str().unwrap(), &bytes).await?; + tracing::info!("[AR] • Successfully saved AuthLib to {:?}", full_path); + Ok(true) +} + +/// ### AR • AuthLib (Ely By) +/// Parses the ElyIntegration release JSON and returns the download URL for the given AuthLib version. +async fn extract_ely_authlib_url(authlib_version: &str) -> Result { + let url = "https://git.astralium.su/api/v1/repos/didirus/ElyIntegration/releases/latest"; + + let response = reqwest::get(url).await.map_err(|e| { + tracing::error!( + "[AR] • Failed to fetch ElyIntegration release JSON: {:?}", + e + ); + crate::ErrorKind::NetworkErrorOccurred { + error: format!("Failed to fetch ElyIntegration release JSON: {}", e), + } + .as_error() + })?; + + let json: serde_json::Value = response.json().await.map_err(|e| { + tracing::error!("[AR] • Failed to parse ElyIntegration JSON: {:?}", e); + crate::ErrorKind::ParseError { + reason: format!("Failed to parse ElyIntegration JSON: {}", e), + } + .as_error() + })?; + + let assets = + json.get("assets") + .and_then(|v| v.as_array()) + .ok_or_else(|| { + crate::ErrorKind::ParseError { + reason: "Missing 'assets' array".into(), + } + .as_error() + })?; + + let asset = assets + .iter() + .find(|a| { + a.get("name") + .and_then(|n| n.as_str()) + .map(|n| n.contains(authlib_version)) + .unwrap_or(false) + }) + .ok_or_else(|| { + crate::ErrorKind::ParseError { + reason: format!( + "No matching asset for authlib-{}.jar", + authlib_version + ), + } + .as_error() + })?; + + let download_url = asset + .get("browser_download_url") + .and_then(|u| u.as_str()) + .ok_or_else(|| { + crate::ErrorKind::ParseError { + reason: "Missing 'browser_download_url'".into(), + } + .as_error() + })?; + + Ok(download_url.to_string()) +} + +/// ### AR • AuthLib (Ely By) +/// Extracts the artifact URL and Path from the library structure. +/// +/// Returns a tuple of references to the URL and path strings, +/// or an error if the required metadata is missing. +fn extract_download_info<'a>( + minecraft_library_metadata: &'a Library, + minecraft_version: &str, +) -> Result<(&'a str, &'a str)> { + let artifact = minecraft_library_metadata + .downloads + .as_ref() + .and_then(|d| d.artifact.as_ref()) + .ok_or_else(|| { + crate::ErrorKind::MinecraftMetadataNotFound { + minecraft_version: minecraft_version.to_string(), + } + .as_error() + })?; + + let url = artifact.url.as_deref().ok_or_else(|| { + crate::ErrorKind::MinecraftMetadataNotFound { + minecraft_version: minecraft_version.to_string(), + } + .as_error() + })?; + + let path = artifact.path.as_deref().ok_or_else(|| { + crate::ErrorKind::MinecraftMetadataNotFound { + minecraft_version: minecraft_version.to_string(), + } + .as_error() + })?; + + Ok((url, path)) +} + +/// ### AR • AuthLib (Ely By) +/// Downloads bytes from the provided URL with a 15 second timeout. +async fn fetch_bytes_from_url(url: &str) -> Result { + // Create client instance with request timeout. + let client = reqwest::Client::new(); + const TIMEOUT_SECONDS: u64 = 15; + + let response = tokio::time::timeout( + std::time::Duration::from_secs(TIMEOUT_SECONDS), + client.get(url).send(), + ) + .await + .map_err(|_| { + tracing::error!("[AR] • Download timed out after {} seconds", TIMEOUT_SECONDS); + crate::ErrorKind::NetworkErrorOccurred { + error: format!("Download timed out after {TIMEOUT_SECONDS} seconds").to_string(), + } + .as_error() + })? + .map_err(|e| { + tracing::error!("[AR] • Request error: {:?}", e); + crate::ErrorKind::NetworkErrorOccurred { + error: format!("Request error: {e}"), + } + .as_error() + })?; + + if !response.status().is_success() { + let status = response.status().to_string(); + tracing::error!("[AR] • Failed to download authlib: HTTP {}", status); + return Err(crate::ErrorKind::NetworkErrorOccurred { + error: format!("Failed to download authlib: HTTP {status}"), + } + .as_error()); + } + + response.bytes().await.map_err(|e| { + tracing::error!("[AR] • Failed to read response bytes: {:?}", e); + crate::ErrorKind::NetworkErrorOccurred { + error: format!("Failed to read response bytes: {e}"), + } + .as_error() + }) +} + +/// ### AR • AuthLib (Ely By) +/// Gets the Minecraft library metadata from the local libraries directory. +async fn get_minecraft_library_metadata(minecraft_version: &str) -> Result { + let state = State::get().await?; + + let path = state + .directories + .version_dir(minecraft_version) + .join(format!("{}.json", minecraft_version)); + if !path.exists() { + tracing::error!("[AR] • File not found: {:#?}", path); + return Err(crate::ErrorKind::InvalidMinecraftVersion { + minecraft_version: minecraft_version.to_string(), + } + .as_error()); + } + + let content = fs::read_to_string(&path).await?; + let version_data: VersionJson = serde_json::from_str(&content)?; + + for lib in version_data.libraries { + if lib.name.contains("com.mojang:authlib") { + if let Some(downloads) = &lib.downloads { + if let Some(artifact) = &downloads.artifact { + if artifact.path.is_some() + && artifact.url.is_some() + && artifact.sha1.is_some() + { + tracing::info!("[AR] • Found AuthLib: {}", lib.name); + tracing::info!( + "[AR] • Path: {}", + artifact.path.as_ref().unwrap() + ); + tracing::info!( + "[AR] • URL: {}", + artifact.url.as_ref().unwrap() + ); + tracing::info!( + "[AR] • SHA1: {}", + artifact.sha1.as_ref().unwrap() + ); + + return Ok(lib); + } + } + } + } + } + + Err(crate::ErrorKind::MinecraftMetadataNotFound { + minecraft_version: minecraft_version.to_string(), + } + .as_error()) +} + +/// ### AR • Migration +/// Applying migration fix for SQLite database. pub async fn apply_migration_fix(eol: &str) -> Result { tracing::info!("[AR] • Attempting to apply migration fix"); let patched = db::apply_migration_fix(eol).await?; @@ -35,14 +333,19 @@ pub async fn apply_migration_fix(eol: &str) -> Result { Ok(patched) } -pub async fn init_download( +/// ### AR • Updater +/// Initialize the update launcher. +pub async fn init_update_launcher( download_url: &str, local_filename: &str, os_type: &str, auto_update_supported: bool, ) -> Result<()> { - println!("[AR] • Initialize downloading from • {:?}", download_url); - println!("[AR] • Save local file name • {:?}", local_filename); + tracing::info!("[AR] • Initialize downloading from • {:?}", download_url); + tracing::info!("[AR] • Save local file name • {:?}", local_filename); + tracing::info!("[AR] • OS type • {}", os_type); + tracing::info!("[AR] • Auto update supported • {}", auto_update_supported); + if let Err(e) = update::get_resource( download_url, local_filename, From df9bbe3ba0f6b00ddf3198142b4d04f26a609946 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Wed, 16 Jul 2025 02:31:59 +0300 Subject: [PATCH 21/62] chore: add patch file to patches directory --- patches/elyby-integration.patch | 675 ++++++++++++++++++++++++++++++++ 1 file changed, 675 insertions(+) create mode 100644 patches/elyby-integration.patch diff --git a/patches/elyby-integration.patch b/patches/elyby-integration.patch new file mode 100644 index 00000000..252bcc11 --- /dev/null +++ b/patches/elyby-integration.patch @@ -0,0 +1,675 @@ +diff --git a/apps/app-frontend/src/components/ui/AccountsCard.vue b/apps/app-frontend/src/components/ui/AccountsCard.vue +index 7b03e1f39..69ee0e01e 100644 +--- a/apps/app-frontend/src/components/ui/AccountsCard.vue ++++ b/apps/app-frontend/src/components/ui/AccountsCard.vue +@@ -50,9 +50,8 @@ + color="primary" + @click="login()" + > +- ++ + +- + + diff --git a/apps/app-frontend/src/locales/en-US/index.json b/apps/app-frontend/src/locales/en-US/index.json index fa2563da..b2410efc 100644 --- a/apps/app-frontend/src/locales/en-US/index.json +++ b/apps/app-frontend/src/locales/en-US/index.json @@ -377,6 +377,12 @@ "instance.worlds.hardcore": { "message": "Hardcore mode" }, + "instance.worlds.incompatible_server": { + "message": "Server is incompatible" + }, + "instance.worlds.no_contact": { + "message": "Server couldn't be contacted" + }, "instance.worlds.no_quick_play": { "message": "You can only jump straight into worlds on Minecraft 1.20+" }, From eb595cdc3e4a6953cbde00c0e119e476ef767a52 Mon Sep 17 00:00:00 2001 From: Silcean <157026423+Silcean@users.noreply.github.com> Date: Wed, 16 Jul 2025 12:43:30 +0200 Subject: [PATCH 23/62] Feature/detect skin variant on fileinput (#3999) * chaged detection algorithm, and added skin variant deteciton on fileinput * Update skins.ts removed leftover logs * removed pnpm lock changes. Simplyfied the transparency check in skin variant detection * fully reverted lock.yaml. my bad. --------- Co-authored-by: Bronchiopator <70262842+Bronchiopator@users.noreply.github.com> --- .../src/components/ui/skin/EditSkinModal.vue | 3 ++- apps/app-frontend/src/helpers/skins.ts | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue index de0ae713..06b45fd1 100644 --- a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue +++ b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue @@ -118,6 +118,7 @@ import { type Cape, type SkinModel, get_normalized_skin_texture, + determineModelType, } from '@/helpers/skins.ts' import { handleError } from '@/store/notifications' import { @@ -253,7 +254,7 @@ async function showNew(e: MouseEvent, skinTextureUrl: string) { mode.value = 'new' currentSkin.value = null uploadedTextureUrl.value = skinTextureUrl - variant.value = 'CLASSIC' + variant.value = await determineModelType(skinTextureUrl) selectedCape.value = undefined visibleCapeList.value = [] initVisibleCapeList() diff --git a/apps/app-frontend/src/helpers/skins.ts b/apps/app-frontend/src/helpers/skins.ts index 28a29ba1..9b5953f5 100644 --- a/apps/app-frontend/src/helpers/skins.ts +++ b/apps/app-frontend/src/helpers/skins.ts @@ -62,16 +62,14 @@ export async function determineModelType(texture: string): Promise<'SLIM' | 'CLA context.drawImage(image, 0, 0) - const armX = 44 - const armY = 16 - const armWidth = 4 + const armX = 54 + const armY = 20 + const armWidth = 2 const armHeight = 12 - const imageData = context.getImageData(armX, armY, armWidth, armHeight).data - - for (let y = 0; y < armHeight; y++) { - const alphaIndex = (3 + y * armWidth) * 4 + 3 - if (imageData[alphaIndex] !== 0) { + for (let index = 1; index <= imageData.length; index++) { + //every fourth value in RGBA is the alpha channel + if (index % 4 == 0 && imageData[index - 1] !== 0) { resolve('CLASSIC') return } From 2d5d7472029efff0f05e4138000e80afc827db5d Mon Sep 17 00:00:00 2001 From: didirus4 Date: Wed, 16 Jul 2025 13:49:50 +0300 Subject: [PATCH 24/62] update readme markdown files, added RUS language --- README.md | 159 ++++++++++++++++++++++++++--------------- readme/ru_ru/README.md | 122 +++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 56 deletions(-) create mode 100644 readme/ru_ru/README.md diff --git a/README.md b/README.md index b23ac38b..a7be669b 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,123 @@ -# Navigation in this README -- [Install instructions](#install-instructions) -- [Features](#features) -- [Getting started](#getting-started) -- [Disclaimer](#disclaimer) -- [Donate](#support-our-project-crypto-wallets) +# 📘 Navigation + +- [🔧 Install Instructions](#install-instructions) +- [✨ Features](#features) +- [🚀 Getting Started](#getting-started) +- [⚠️ Disclaimer](#disclaimer) +- [💰 Donate](#support-our-project-crypto-wallets) + +## Other languages +> [Русский](readme/ru_ru/README.md) + +## Support channel +> [Telegram](https://me.astralium.su/ref/telegram_channel) + +--- # About Project -## AstralRinth • Empowering Your Minecraft Adventure -Welcome to AR • Fork of Modrinth, the ultimate game launcher designed to enhance your Minecraft experience through the Modrinth platform and their API. Whether you're a graphical interface enthusiast, or a developer integrating Modrinth projects, Theseus core is your gateway to a new level of Minecraft gaming. +## **AstralRinth • Empowering Your Minecraft Adventure** -## About Software -Introducing AstralRinth, a specialized variant of Theseus dedicated to implementing offline authorization for an even more flexible and user-centric Minecraft Modrinth experience. Roam the Minecraft realms without the constraints of online authentication, thanks to AstralRinth. +Welcome to **AstralRinth (AR)** — a powerful fork of Modrinth, reimagined to enhance your Minecraft journey. Whether you're a GUI enthusiast or a developer building with Modrinth’s API, **Theseus Core** is your launchpad into a new era of Minecraft gameplay. -## AR • Unlocking Minecraft's Boundless Horizon -Dive into the extraordinary world of AstralRinth, a fork of the original project with a unique focus on providing a free trial experience for Minecraft, all without the need for a license. Currently boasting: +- *Recently, improved integration with the Git Astralium API has been added.* -# Install instructions -- To install our application, you need to download a file for your operating system from our available releases or development builds • [Download variants here](https://git.astralium.su/didirus/AstralRinth/releases) -- After you have downloaded the required executable file or archive, then open it +## **About the Software** -### Downloadable file extensions -- `.msi` format for Windows OS system _(Supported popular latest versions of Microsoft Windows)_ -- `.dmg` format for MacOS system _(Works on Macos Ventura / Sonoma / Sequoia, but it should be works on older OS builds)_ -- `.deb` format for Linux OS systems _(Since there are quite a few distributions, we do not guarantee +**AstralRinth** is a dedicated branch of the Theseus project, focused on **offline authentication**, offering you more flexibility and control. Play Minecraft without the need for constant online verification — a user-first approach to modern modded gaming. -### Installation subjects -- Builds in releases that are signed with the following prefixes are not recommended for installation and may contain errors: - - `dev` - - `nightly` - - `dirty` - - `dirty-dev` - - `dirty-nightly` - - `dirty_dev` - - `dirty_nightly` -- Auto-updating takes place through parsing special versions from releases, so we also distribute clean types of `.msi, .dmg and .deb` +## **AR • Unlocking Minecraft's Boundless Horizon** + +This unique fork introduces a **free trial Minecraft experience**, bypassing license checks while maintaining rich functionality. Currently includes: + +--- + +# Install Instructions + +To install the launcher: + +1. Visit the [releases page](https://git.astralium.su/didirus/AstralRinth/releases) to download the correct version for your system. +2. Run the downloaded file or extract and launch it, depending on the format. + +### Downloadable File Extensions + +| Extension | OS | Notes | +| --------- | ------- | --------------------------------------------------------------------- | +| `.msi` | Windows | Supported on all recent Windows versions | +| `.dmg` | macOS | Works on Ventura, Sonoma, Sequoia _(may also support older versions)_ | +| `.deb` | Linux | Basic support; compatibility may vary by distribution | + +### Installation Warnings + +Avoid using builds with these prefixes — they may be unstable or experimental: + +- `dev` +- `nightly` +- `dirty` +- `dirty-dev` +- `dirty-nightly` +- `dirty_dev` +- `dirty_nightly` + +--- # Features -### Featured enhancement in AR -- AstralRinth offers a range of authorization options, giving users the flexibility to log in with valid licenses or even a pirate account without auth credentials breaks (_Unlike MultiMC Cracked and similar software_). Experience Minecraft on your terms, breaking free from traditional licensing constraints (_Popular in Russian Federation_). +> _The launcher provides an opportunity to use the well-known Modrinth, but with an improved user experience._ -### Easy to use -- Using the launcher is intuitive, any user can figure it out. +## Included exclusive features -### Update notifies -- We have implemented notifications about the release of new updates on our Git. The launcher can also download them for you and try to install them. +- No ads in the entire launcher. +- Custom `.svg` vector icons for a distinct UI. +- Improved compatibility with both licensed and pirate accounts. + - Use **official microsoft accounts** or **offline/pirate accounts** — login won't break. + - Supports license-free access for testing or personal use. + - No dependence on official authentication services. +- Discord Rich Presence integration: + - Dynamic status messages. + - In-game timer and AFK counter. +- Strict disabling of statistics and other Modrinth metrics. +- Optimized archive/package size. +- Integrated update fetcher for seamless version management. + - Built-in update alerts for new versions posted on Git Astralium. + - Automatic download and installation capabilities. +- Database migration fixes, when error occurred (Interactive Mode) (Modrinth issue) +- ElyBy skin system integration (AuthLib / Java) -### Enhancements -- Custom .SVG vectors for a personalized touch. -- Improved compatibility for both pirate and licensed accounts. -- Beautiful Discord RPC with random messages while playing, along with an in-game timer and AFK counter. -- Forced disabling of statistics collection (modrinch metrics) with a hard patch from AstralRinth, ensuring it remains deactivated regardless of the configuration setting. -- Removal of advertisements from all launcher views. -- Optimization of packages (archives). -- Integrated update fetching feature +--- # Getting Started -To begin your AstralRinth adventure, follow these steps: -1. **Download Your OS Version**: Head over to our [releases page](https://git.astralium.su/didirus/AstralRinth/releases/) to find the right file for your operating system. - - **Choosing the Correct File**: Ensure you select the file that matches your OS requirements. - - [**How select file**](#downloadable-file-extensions) - - [**How select release**](#installation-subjects) -2. **Authentication**: Log in with a valid license or, for testing, try using a pirate account to see AstralRinth in action. -3. **Launch Minecraft**: Start your journey by launching Minecraft through AstralRinth and enjoy the adventures that await. - - **Choosing java installation**: The launcher will try to automatically detect the recommended JVM version for running the game, but you can configure everything in the launcher settings. + +To begin using AstralRinth: + +1. **Download Your OS Version** + + - Go to the [releases page](https://git.astralium.su/didirus/AstralRinth/releases) + - [How to choose a file](#downloadable-file-extensions) + - [How to choose a release](#installation-warnings) + +2. **Log In** + + - Use your official Mojang/Microsoft account, or test using a non-licensed account. + +3. **Launch Minecraft** + - Start Minecraft from the launcher. + - The launcher will auto-detect the recommended JVM version. + - You can also configure Java manually in the settings. + +--- # Disclaimer -- AstralRinth is a project intended for experimentation and educational purposes only. It does not endorse or support piracy, and users are encouraged to obtain valid licenses for a fully-supported Minecraft experience. -- Users are reminded to respect licensing agreements and support the developers of Minecraft. -# Support our Project (Crypto Wallets) +- **AstralRinth** is intended **solely for educational and experimental use**. +- We **do not condone piracy** — users are encouraged to purchase a legitimate Minecraft license. +- Respect all relevant licensing agreements and support Minecraft developers. + +--- + +# Support Our Project (Crypto Wallets) + +If you'd like to support development, you can donate via the following crypto wallets: + - BTC (Telegram): 14g6asNYzcUoaQtB8B2QGKabgEvn55wfLj -- USDT TRC20 (Telegram): TMSmv1D5Fdf4fipUpwBCdh16WevrV45vGr -- TONCOIN (Telegram): UQAqUJ2_hVBI6k_gPyfp_jd-1K0OS61nIFPZuJWN9BwGAvKe \ No newline at end of file +- TONCOIN (Telegram): UQAqUJ2_hVBI6k_gPyfp_jd-1K0OS61nIFPZuJWN9BwGAvKe diff --git a/readme/ru_ru/README.md b/readme/ru_ru/README.md new file mode 100644 index 00000000..ebc252ce --- /dev/null +++ b/readme/ru_ru/README.md @@ -0,0 +1,122 @@ +# 📘 Навигация + +- [🔧 Установка](#установка) +- [✨ Возможности](#возможности) +- [🚀 Начало работы](#начало-работы) +- [⚠️ Отказ от ответственности](#отказ-от-ответственности) +- [💰 Поддержать](#поддержать-проект-крипто-кошельки) + +## Другие языки +> [English](../../README.md) + +## Канал поддержки +> [Telegram](https://me.astralium.su/ref/telegram_channel) + +--- + +# О проекте + +## **AstralRinth • Раскрой потенциал своих приключений в Minecraft** + +Добро пожаловать в **AstralRinth (AR)** — мощный форк Modrinth, переосмысленный для улучшения твоего опыта в Minecraft. Независимо от того, являешься ли ты поклонником GUI или разработчиком, использующим API Modrinth, **Theseus Core** — это твоя стартовая платформа для новой эры игрового процесса в Minecraft. + +- *С недавнего времени имеется улучшенная интеграция с Git Astralium API* + +## **О программе** + +**AstralRinth** — это специализированная ветка проекта Theseus, сосредоточенная на **офлайн-аутентификации**, предоставляя ещё большую гибкость и ориентированность на пользователя. Путешествуй по мирам Minecraft без необходимости онлайн-авторизации — благодаря AstralRinth. + +## **AR • Открой безграничные горизонты Minecraft** + +Уникальный форк с фокусом на предоставление **пробного игрового опыта Minecraft** — без необходимости лицензии. В настоящее время включает: + +--- + +# Установка + +Чтобы установить лаунчер: + +1. Перейдите на [страницу релизов](https://git.astralium.su/didirus/AstralRinth/releases), чтобы скачать нужную версию для вашей системы. +2. После загрузки нужного исполняемого файла или архива — откройте его. + +### Поддерживаемые расширения файлов + +| Расширение | ОС | Примечания | +| ---------- | ------- | --------------------------------------------------------------------- | +| `.msi` | Windows | Поддерживаются актуальные версии Microsoft Windows | +| `.dmg` | macOS | Работает на MacOS Ventura / Sonoma / Sequoia, возможно и на старых | +| `.deb` | Linux | Так как дистрибутивов много, совместимость не гарантируется полностью | + +### Особенности установки + +Сборки с префиксами ниже **не рекомендуются к установке** и могут содержать ошибки: + +- `dev` +- `nightly` +- `dirty` +- `dirty-dev` +- `dirty-nightly` +- `dirty_dev` +- `dirty_nightly` + +--- + +# Возможности + +> _Лаунчер предоставляет возможность использовать знакомый Modrinth с улучшенным пользовательским интерфейсом._ + +## Уникальные функции + +- Отсутствие рекламы во всём лаунчере. +- Кастомные `.svg` векторы для персонализированного интерфейса. +- Улучшенная совместимость с лицензионными и пиратскими аккаунтами. + - Используйте **официальные аккаунты Microsoft** или **пиратские аккаунты** — без сбоев в авторизации. + - Поддержка безлицензионного доступа для тестирования или личного использования. + - Нет зависимости от официальных сервисов авторизации. +- Интеграция Discord Rich Presence: + - Случайные статусные сообщения. + - Таймер игры и счётчик AFK. +- Жёсткое отключение сбора статистики (метрик Modrinth) через патч AstralRinth — работает независимо от конфигурации. +- Удаление рекламы из всех окон лаунчера. +- Оптимизация архивов (пакетов). +- Встроенная система получения обновлений: + - Уведомления о новых версиях на Git. + - Возможность автозагрузки и автоустановки. +- Исправления миграции базы данных при ошибках (интерактивный режим, проблема Modrinth). +- Интеграция системы скинов ElyBy (AuthLib / Java). + +--- + +# Начало работы + +Чтобы начать приключение с AstralRinth, выполните следующие шаги: + +1. **Скачайте нужную версию под вашу ОС** + + - Перейдите на [страницу релизов](https://git.astralium.su/didirus/AstralRinth/releases) + - [**Как выбрать файл**](#поддерживаемые-расширения-файлов) + - [**Как выбрать релиз**](#особенности-установки) + +2. **Авторизация** + + - Войдите с действующей лицензией или используйте пиратский аккаунт для теста AstralRinth. + +3. **Запуск Minecraft** + - Запустите Minecraft через AstralRinth и наслаждайтесь. + - Лаунчер попытается автоматически определить рекомендованную JVM для запуска игры, но вы можете всё настроить вручную в настройках. + +--- + +# Отказ от ответственности + +- **AstralRinth** предназначен только для экспериментов и образовательных целей. Мы не поддерживаем пиратство и рекомендуем приобретать официальную лицензию Minecraft для полноценного игрового опыта. +- Пользователям напоминается соблюдать лицензионные соглашения и поддерживать разработчиков Minecraft. + +--- + +# Поддержать проект (крипто-кошельки) + +Если вы хотите поддержать разработку, вы можете отправить донат на следующие кошельки: + +- BTC (Telegram): 14g6asNYzcUoaQtB8B2QGKabgEvn55wfLj +- TONCOIN (Telegram): UQAqUJ2_hVBI6k_gPyfp_jd-1K0OS61nIFPZuJWN9BwGAvKe From 5a10292add0a734b3ab25eb240c6054050961ca6 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Wed, 16 Jul 2025 20:33:58 +0300 Subject: [PATCH 25/62] feat: add support for multiple account types in database --- .../src/components/ui/AccountsCard.vue | 218 +++++++++++------- apps/app/tauri.conf.json | 2 +- ...a706cbc4a4f5190c9320d1ad6111b9711d63.json} | 10 +- ...34d3801bc38c23e1e02fbd8fa08ae51e8f08.json} | 10 +- ...8ffb21c4e22c7ff33459df5049ee441fa0467.json | 12 + ...1828ee58a724f06a91633b8a40b4e04d0b9a0.json | 12 - ...pdate_minecraft_users_add_account_type.sql | 5 + .../app-lib/src/state/legacy_converter.rs | 2 + packages/app-lib/src/state/minecraft_auth.rs | 42 +++- packages/assets/icons/elyby-icon.svg | 64 +++++ packages/assets/index.ts | 2 + 11 files changed, 274 insertions(+), 105 deletions(-) rename packages/app-lib/.sqlx/{query-bf7d47350092d87c478009adaab131168e87bb37aa65c2156ad2cb6198426d8c.json => query-57214178fb3a0ccd8f67457e9732a706cbc4a4f5190c9320d1ad6111b9711d63.json} (72%) rename packages/app-lib/.sqlx/{query-727e3e1bc8625bbcb833920059bb8cea926ac6c65d613904eff1d740df30acda.json => query-5c803f3d90c147210e8e7a7a6d7234d3801bc38c23e1e02fbd8fa08ae51e8f08.json} (74%) create mode 100644 packages/app-lib/.sqlx/query-8f7d4406ddae4a158eabb20fc6a8ffb21c4e22c7ff33459df5049ee441fa0467.json delete mode 100644 packages/app-lib/.sqlx/query-d719cf2f6f87c5ea7ea6ace2d6a1828ee58a724f06a91633b8a40b4e04d0b9a0.json create mode 100644 packages/app-lib/migrations/20250716135844_update_minecraft_users_add_account_type.sql create mode 100644 packages/assets/icons/elyby-icon.svg diff --git a/apps/app-frontend/src/components/ui/AccountsCard.vue b/apps/app-frontend/src/components/ui/AccountsCard.vue index 69ee0e01..f7a6326d 100644 --- a/apps/app-frontend/src/components/ui/AccountsCard.vue +++ b/apps/app-frontend/src/components/ui/AccountsCard.vue @@ -1,17 +1,9 @@ diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index e6a708f7..bf910c1e 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -533,6 +533,69 @@ "profile.user-id": { "message": "User ID: {id}" }, + "project-member-header.accept": { + "message": "Accept" + }, + "project-member-header.decline": { + "message": "Decline" + }, + "project-member-header.error": { + "message": "Error" + }, + "project-member-header.error-decline": { + "message": "Failed to decline team invitation" + }, + "project-member-header.error-join": { + "message": "Failed to accept team invitation" + }, + "project-member-header.invitation-no-role": { + "message": "You've been invited to join this project. Please accept or decline the invitation." + }, + "project-member-header.invitation-title": { + "message": "Invitation to join project" + }, + "project-member-header.invitation-with-role": { + "message": "You've been invited be a member of this project with the role of '{role}'." + }, + "project-member-header.publishing-checklist": { + "message": "Publishing checklist" + }, + "project-member-header.required": { + "message": "Required" + }, + "project-member-header.resubmit-for-review": { + "message": "Resubmit for review" + }, + "project-member-header.resubmit-for-review-desc": { + "message": "Your project has been {status} by Modrinth's staff. In most cases, you can resubmit for review after addressing the staff's message." + }, + "project-member-header.submit-checklist-tooltip": { + "message": "You must complete the required steps in the publishing checklist!" + }, + "project-member-header.submit-for-review": { + "message": "Submit for review" + }, + "project-member-header.submit-for-review-desc": { + "message": "Your project is only viewable by members of the project. It must be reviewed by moderators in order to be published." + }, + "project-member-header.success": { + "message": "Success" + }, + "project-member-header.success-decline": { + "message": "You have declined the team invitation" + }, + "project-member-header.success-join": { + "message": "You have joined the project team" + }, + "project-member-header.suggestion": { + "message": "Suggestion" + }, + "project-member-header.visit-moderation-page": { + "message": "Visit moderation page" + }, + "project-member-header.warning": { + "message": "Warning" + }, "project-type.collection.plural": { "message": "Collections" }, diff --git a/apps/frontend/src/pages/[type]/[id]/settings/description.vue b/apps/frontend/src/pages/[type]/[id]/settings/description.vue index 174d4bc9..45f0a8eb 100644 --- a/apps/frontend/src/pages/[type]/[id]/settings/description.vue +++ b/apps/frontend/src/pages/[type]/[id]/settings/description.vue @@ -22,6 +22,10 @@ " :on-image-upload="onUploadHandler" /> +
+ + {{ descriptionWarning }} +