From f0a45320516e9a392d45f836059c4d27cdda3496 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Thu, 10 Jul 2025 15:53:26 +0300 Subject: [PATCH 01/13] ci: update astralrinth-build.yml --- .github/workflows/astralrinth-build.yml | 35 +++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/.github/workflows/astralrinth-build.yml b/.github/workflows/astralrinth-build.yml index b5ede000f..c0ca17290 100644 --- a/.github/workflows/astralrinth-build.yml +++ b/.github/workflows/astralrinth-build.yml @@ -16,6 +16,7 @@ on: - 'packages/assets/**' - 'packages/ui/**' - 'packages/utils/**' + workflow_dispatch: jobs: build: @@ -24,12 +25,12 @@ jobs: fail-fast: false matrix: # platform: [macos-latest, windows-latest, ubuntu-latest] - platform: [ubuntu-latest] + platform: [windows-latest, ubuntu-latest] include: # - platform: macos-latest # artifact-target-name: universal-apple-darwin - # - platform: windows-latest - # artifact-target-name: x86_64-pc-windows-msvc + - platform: windows-latest + artifact-target-name: x86_64-pc-windows-msvc - platform: ubuntu-latest artifact-target-name: x86_64-unknown-linux-gnu @@ -73,11 +74,11 @@ jobs: - name: 🧰 Install dependencies run: pnpm install - # - name: ✍️ Set up Windows code signing (jsign) - # if: matrix.platform == 'windows-latest' && env.SIGN_WINDOWS_BINARIES == 'true' - # shell: bash - # run: | - # choco install jsign --ignore-dependencies + - name: ✍️ Set up Windows code signing (jsign) + if: matrix.platform == 'windows-latest' && env.SIGN_WINDOWS_BINARIES == 'true' + shell: bash + run: | + choco install jsign --ignore-dependencies - name: πŸ—‘οΈ Clean up cached bundles shell: bash @@ -99,15 +100,15 @@ jobs: TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - # - name: πŸ”¨ Build Windows app - # if: matrix.platform == 'windows-latest' - # shell: pwsh - # run: | - # $env:JAVA_HOME = "$env:JAVA_HOME_11_X64" - # pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles 'nsis' - # env: - # TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - # TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + - name: πŸ”¨ Build Windows app + if: matrix.platform == 'windows-latest' + shell: pwsh + run: | + $env:JAVA_HOME = "$env:JAVA_HOME_11_X64" + pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles 'nsis' + env: + TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - name: πŸ“€ Upload app bundles uses: actions/upload-artifact@v3 From 1ec92b5f97badb55ebcae2dcec43b1da20c167b6 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Thu, 10 Jul 2025 15:59:17 +0300 Subject: [PATCH 02/13] ci: add steps with LF & CRLF checks --- .github/workflows/astralrinth-build.yml | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/astralrinth-build.yml b/.github/workflows/astralrinth-build.yml index c0ca17290..97f79b9ab 100644 --- a/.github/workflows/astralrinth-build.yml +++ b/.github/workflows/astralrinth-build.yml @@ -41,6 +41,37 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 2 + - name: πŸ” Validate Git config does not introduce CRLF + run: | + echo "πŸ” Checking Git config for CRLF settings..." + + autocrlf=$(git config --get core.autocrlf || echo "unset") + eol_setting=$(git config --get core.eol || echo "unset") + + echo "core.autocrlf = $autocrlf" + echo "core.eol = $eol_setting" + + if [ "$autocrlf" = "true" ]; then + echo "❌ ERROR: core.autocrlf is set to 'true'. Please set to 'input' or 'false'." + exit 1 + fi + + if [ "$eol_setting" = "crlf" ]; then + echo "❌ ERROR: core.eol is set to 'crlf'. Please unset it or set to 'lf'." + exit 1 + fi + + echo "βœ… Git config is safe (no forced CRLF)" + + - name: πŸ” Check migration files line endings (LF only) + run: | + echo "πŸ” Scanning migration SQL files for CR characters (\\r)..." + if grep -Iq $'\r' packages/app-lib/migrations/*.sql; then + echo "❌ ERROR: Some migration files contain CR (\\r) characters β€” expected only LF line endings." + exit 1 + fi + echo "βœ… All migration files use LF line endings" + - name: 🧰 Setup Rust toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 From 1ef96c447eb272e840264221a57b0a3e39855e7e Mon Sep 17 00:00:00 2001 From: didirus4 Date: Thu, 10 Jul 2025 16:30:04 +0300 Subject: [PATCH 03/13] ci: patch validating git config on windows runner --- .github/workflows/astralrinth-build.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/astralrinth-build.yml b/.github/workflows/astralrinth-build.yml index 97f79b9ab..c5a263d74 100644 --- a/.github/workflows/astralrinth-build.yml +++ b/.github/workflows/astralrinth-build.yml @@ -41,7 +41,9 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 2 + - name: πŸ” Validate Git config does not introduce CRLF + shell: bash run: | echo "πŸ” Checking Git config for CRLF settings..." @@ -52,18 +54,15 @@ jobs: echo "core.eol = $eol_setting" if [ "$autocrlf" = "true" ]; then - echo "❌ ERROR: core.autocrlf is set to 'true'. Please set to 'input' or 'false'." - exit 1 + echo "⚠️ WARNING: core.autocrlf is set to 'true'. Consider setting it to 'input' or 'false'." fi if [ "$eol_setting" = "crlf" ]; then - echo "❌ ERROR: core.eol is set to 'crlf'. Please unset it or set to 'lf'." - exit 1 + echo "⚠️ WARNING: core.eol is set to 'crlf'. Consider unsetting it or setting to 'lf'." fi - echo "βœ… Git config is safe (no forced CRLF)" - - name: πŸ” Check migration files line endings (LF only) + shell: bash run: | echo "πŸ” Scanning migration SQL files for CR characters (\\r)..." if grep -Iq $'\r' packages/app-lib/migrations/*.sql; then @@ -72,7 +71,6 @@ jobs: fi echo "βœ… All migration files use LF line endings" - - name: 🧰 Setup Rust toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 with: From 332a543f6656661200468de6fe4f3f3d44e38fca Mon Sep 17 00:00:00 2001 From: didirus4 Date: Thu, 10 Jul 2025 21:09:06 +0300 Subject: [PATCH 04/13] fix: added ability for regenerate checksums with issued mr migrations. --- apps/app-frontend/src/App.vue | 4 +- .../src/components/ui/ErrorModal.vue | 135 +++++++++++++ apps/app-frontend/src/helpers/utils.js | 6 + apps/app/build.rs | 1 + apps/app/src/api/utils.rs | 12 +- apps/app/tauri.conf.json | 2 +- packages/app-lib/src/api/download.rs | 55 ------ packages/app-lib/src/api/mod.rs | 2 +- packages/app-lib/src/api/update.rs | 42 ++++ packages/app-lib/src/lib.rs | 2 +- packages/app-lib/src/state/db.rs | 179 ++++++++++-------- packages/app-lib/src/util/utils.rs | 50 ++++- 12 files changed, 349 insertions(+), 141 deletions(-) delete mode 100644 packages/app-lib/src/api/download.rs create mode 100644 packages/app-lib/src/api/update.rs diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index a8a76db24..81107c4fe 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -161,11 +161,11 @@ async function setupApp() { initAnalytics() if (!telemetry) { - console.info("[AR] Telemetry disabled by default (Hard patched).") + console.info("[AR] β€’ Telemetry disabled by default (Hard patched).") optOutAnalytics() } if (!personalized_ads) { - console.info("[AR] Personalized ads disabled by default (Hard patched).") + console.info("[AR] β€’ Personalized ads disabled by default (Hard patched).") } if (dev) debugAnalytics() diff --git a/apps/app-frontend/src/components/ui/ErrorModal.vue b/apps/app-frontend/src/components/ui/ErrorModal.vue index bae919081..3df0cc114 100644 --- a/apps/app-frontend/src/components/ui/ErrorModal.vue +++ b/apps/app-frontend/src/components/ui/ErrorModal.vue @@ -18,11 +18,15 @@ import { cancel_directory_change } from '@/helpers/settings.ts' import { install } from '@/helpers/profile.js' import { trackEvent } from '@/helpers/analytics' import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue' +import { applyMigrationFix } from '@/helpers/utils.js' const errorModal = ref() const error = ref() const closable = ref(true) const errorCollapsed = ref(false) +const language = ref('en') +const migrationFixSuccess = ref(null) // null | true | false +const migrationFixCallbackModel = ref() const title = ref('An error occurred') const errorType = ref('unknown') @@ -148,6 +152,25 @@ async function copyToClipboard(text) { copied.value = false }, 3000) } + +function toggleLanguage() { + language.value = language.value === 'en' ? 'ru' : 'en' +} + +async function onApplyMigrationFix(eol) { + console.log(`[AR] β€’ Attempting to apply migration ${eol.toUpperCase()} fix`) + try { + const result = await applyMigrationFix(eol) + migrationFixSuccess.value = result === true + console.log(`[AR] β€’ Successfully applied migration ${eol.toUpperCase()} fix`, result) + } catch (err) { + console.error(`[AR] β€’ Failed to apply migration fix:`, err) + migrationFixSuccess.value = false + } finally { + migrationFixCallbackModel.value?.show?.() + } +} + \ No newline at end of file diff --git a/packages/assets/styles/neon-button.scss b/packages/assets/styles/neon-button.scss index 8fc133212..91e201f39 100644 --- a/packages/assets/styles/neon-button.scss +++ b/packages/assets/styles/neon-button.scss @@ -1,13 +1,8 @@ // [AR] Feature -.btn-wrapper.neon :deep(:is(button, a, .button-like):first-child), -.btn-wrapper.neon :slotted(:is(button, a, .button-like):first-child), -.btn-wrapper.neon :slotted(*) > :is(button, a, .button-like):first-child, -.btn-wrapper.neon :slotted(*) > *:first-child > :is(button, a, .button-like):first-child, -.btn-wrapper.neon - :slotted(*) - > *:first-child - > *:first-child - > :is(button, a, .button-like):first-child { +.neon-button.neon :deep(:is(button, a, .button-like)), +.neon-button.neon :slotted(:is(button, a, .button-like)), +.neon-button.neon :slotted(*) :is(button, a, .button-like) { + cursor: pointer; background-color: transparent; border: 1px solid #3e8cde; color: #3e8cde; @@ -22,20 +17,17 @@ box-shadow: 0 0 4px rgba(79, 173, 255, 0.5); } +.bordered { + border-radius: 12px; +} + /* Hover */ -.btn-wrapper.neon - :deep(:is(button, a, .button-like):first-child):hover:not([disabled]):not(.disabled), -.btn-wrapper.neon - :slotted(:is(button, a, .button-like):first-child):hover:not([disabled]):not(.disabled), -.btn-wrapper.neon - :slotted(*) > :is(button, a, .button-like):first-child:hover:not([disabled]):not(.disabled), -.btn-wrapper.neon - :slotted(*) > *:first-child > :is(button, a, .button-like):first-child:hover:not([disabled]):not(.disabled), -.btn-wrapper.neon - :slotted(*) - > *:first-child - > *:first-child - > :is(button, a, .button-like):first-child:hover:not([disabled]):not(.disabled) { +.neon-button.neon + :deep(:is(button, a, .button-like):hover):not([disabled]):not(.disabled), +.neon-button.neon + :slotted(:is(button, a, .button-like):hover):not([disabled]):not(.disabled), +.neon-button.neon + :slotted(*) :is(button, a, .button-like):hover:not([disabled]):not(.disabled) { color: #10fae5; transform: scale(1.02); box-shadow: diff --git a/packages/assets/styles/neon-icon.scss b/packages/assets/styles/neon-icon.scss new file mode 100644 index 000000000..a0e2fb62f --- /dev/null +++ b/packages/assets/styles/neon-icon.scss @@ -0,0 +1,37 @@ +// [AR] Feature +.neon-icon { + background-color: transparent; + color: #3e8cde; + text-shadow: + 0 0 4px rgba(79, 173, 255, 0.5), + 0 0 8px rgba(14, 98, 204, 0.5), + 0 0 12px rgba(122, 31, 199, 0.5); + transition: transform 0.25s ease, color 0.25s ease, text-shadow 0.25s ease; + cursor: pointer; + display: inline-block; +} + +/* Hover */ +.neon-icon:hover { + color: #10fae5; + transform: scale(1.05); + text-shadow: + 0 0 2px rgba(16, 250, 229, 0.4), + 0 0 4px rgba(16, 250, 229, 0.25); +} + +.neon-icon.pulse { + position: relative; + animation: neon-pulse 1s ease-in-out infinite; + filter: drop-shadow(0 0 6px #10fae5); + box-shadow: none; +} + +@keyframes neon-pulse { + 0%, 100% { + filter: drop-shadow(0 0 4px #10fae5); + } + 50% { + filter: drop-shadow(0 0 12px #10fae5); + } +} \ No newline at end of file diff --git a/packages/assets/styles/neon-text.scss b/packages/assets/styles/neon-text.scss new file mode 100644 index 000000000..1899f2b6c --- /dev/null +++ b/packages/assets/styles/neon-text.scss @@ -0,0 +1,28 @@ +// [AR] Feature +.neon-text { + background-color: transparent; + color: #3e8cde; + text-shadow: + 0 0 4px rgba(79, 173, 255, 0.5), + 0 0 8px rgba(14, 98, 204, 0.5), + 0 0 12px rgba(122, 31, 199, 0.5); + transition: + color 0.25s ease, + box-shadow 0.3s ease, + transform 0.15s ease; + + white-space: normal; + word-wrap: break-word; + overflow-wrap: break-word; + max-width: 100%; + display: inline-block; + padding: 4px 8px; +} + +/* Hover */ +.neon-text:hover:not([disabled]):not(.disabled) { + color: #10fae5; + text-shadow: + 0 0 2px rgba(16, 250, 229, 0.4), + 0 0 4px rgba(16, 250, 229, 0.25); +} From b71e4cc6f92c99c5897e7ff8288697a690457cee Mon Sep 17 00:00:00 2001 From: didirus4 Date: Fri, 11 Jul 2025 02:29:05 +0300 Subject: [PATCH 08/13] refactor: update checker moved to App.vue, added new animated icons --- apps/app-frontend/src/App.vue | 25 +++++++++++++++---- .../src/components/ui/RunningAppBar.vue | 3 --- .../components/ui/modal/AppSettingsModal.vue | 5 ++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index a8dd1cd80..60d1f8fb5 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -72,6 +72,9 @@ import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue' import { get_available_capes, get_available_skins } from './helpers/skins' import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer' +// [AR] Feature +import { getRemote, updateState } from '@/helpers/update.js' + const themeStore = useTheming() const news = ref([]) @@ -99,6 +102,7 @@ const isMaximized = ref(false) onMounted(async () => { await useCheckDisableMouseover() + await getRemote(false) // [AR] Check for updates document.querySelector('body').addEventListener('click', handleClick) document.querySelector('body').addEventListener('auxclick', handleAuxClick) @@ -465,12 +469,20 @@ function handleAuxClick(e) {
- + + + + +@import '../../../packages/assets/styles/neon-icon.scss'; +@import '../../../packages/assets/styles/neon-text.scss'; + .window-controls { z-index: 20; display: none; diff --git a/apps/app-frontend/src/components/ui/RunningAppBar.vue b/apps/app-frontend/src/components/ui/RunningAppBar.vue index b42d33209..f3a766b1c 100644 --- a/apps/app-frontend/src/components/ui/RunningAppBar.vue +++ b/apps/app-frontend/src/components/ui/RunningAppBar.vue @@ -84,9 +84,6 @@ import ProgressBar from '@/components/ui/ProgressBar.vue' import { handleError } from '@/store/notifications.js' import { get_many } from '@/helpers/profile.js' import { trackEvent } from '@/helpers/analytics' -import { getRemote } from '@/helpers/update.js' - -await getRemote(false) const router = useRouter() const card = ref(null) diff --git a/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue b/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue index 7869d2fdc..0ce1e6c69 100644 --- a/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue +++ b/apps/app-frontend/src/components/ui/modal/AppSettingsModal.vue @@ -173,13 +173,12 @@ function devModeCount() {
- From 4e69cd8bde5eae066b0f3c1ba394cb3cbc14d060 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Fri, 11 Jul 2025 02:38:23 +0300 Subject: [PATCH 09/13] feat: add auto application restart after migration successful fix attempt --- apps/app-frontend/src/App.vue | 2 +- apps/app-frontend/src/components/ui/ErrorModal.vue | 6 ++++++ apps/app/src/main.rs | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 60d1f8fb5..c837744c9 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -42,7 +42,7 @@ import ModrinthLoadingIndicator from '@/components/LoadingIndicatorBar.vue' import { handleError, useNotifications } from '@/store/notifications.js' import { command_listener, warning_listener } from '@/helpers/events.js' import { type } from '@tauri-apps/plugin-os' -import { getOS, isDev, restartApp } from '@/helpers/utils.js' +import { getOS, isDev } from '@/helpers/utils.js' import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics' import { getCurrentWindow } from '@tauri-apps/api/window' import { getVersion } from '@tauri-apps/api/app' diff --git a/apps/app-frontend/src/components/ui/ErrorModal.vue b/apps/app-frontend/src/components/ui/ErrorModal.vue index 37c531832..808a101e9 100644 --- a/apps/app-frontend/src/components/ui/ErrorModal.vue +++ b/apps/app-frontend/src/components/ui/ErrorModal.vue @@ -19,6 +19,7 @@ import { install } from '@/helpers/profile.js' import { trackEvent } from '@/helpers/analytics' import ModalWrapper from '@/components/ui/modal/ModalWrapper.vue' import { applyMigrationFix } from '@/helpers/utils.js' +import { restartApp } from '@/helpers/utils.js' const errorModal = ref() const error = ref() @@ -168,6 +169,11 @@ async function onApplyMigrationFix(eol) { migrationFixSuccess.value = false } finally { migrationFixCallbackModel.value?.show?.() + if (migrationFixSuccess.value === true) { + setTimeout(async () => { + await restartApp() + }, 3000) + } } } diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs index dc3ee39e8..94427776a 100644 --- a/apps/app/src/main.rs +++ b/apps/app/src/main.rs @@ -157,7 +157,7 @@ fn main() { */ let _log_guard = theseus::start_logger(); - tracing::info!("Initialized tracing subscriber. Loading Modrinth App!"); + tracing::info!("Initialized tracing subscriber. Loading AstralRinth App!"); let mut builder = tauri::Builder::default(); From d917bff6ef501f5723781024a2fb901866e7b447 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Fri, 11 Jul 2025 03:04:37 +0300 Subject: [PATCH 10/13] feat: add ability to auto exec downloaded installer on windows; minor changes --- apps/app-frontend/src/helpers/update.js | 2 +- packages/app-lib/src/api/update.rs | 127 +++++++++++++++++++----- packages/app-lib/src/state/db.rs | 10 +- packages/app-lib/src/util/utils.rs | 4 +- 4 files changed, 108 insertions(+), 35 deletions(-) diff --git a/apps/app-frontend/src/helpers/update.js b/apps/app-frontend/src/helpers/update.js index 6f3d87a13..cea6c6bd4 100644 --- a/apps/app-frontend/src/helpers/update.js +++ b/apps/app-frontend/src/helpers/update.js @@ -11,7 +11,7 @@ const releaseLink = `https://git.astralium.su/api/v1/repos/didirus/AstralRinth/r const failedFetch = [`Failed to fetch remote releases:`, `Failed to fetch remote commits:`] const osList = ['macos', 'windows', 'linux'] -const macExtensionList = ['.app', '.dmg'] +const macExtensionList = ['.dmg', '.pkg'] const windowsExtensionList = ['.exe', '.msi'] const blacklistPrefixes = [ diff --git a/packages/app-lib/src/api/update.rs b/packages/app-lib/src/api/update.rs index b1943dece..fe24ec019 100644 --- a/packages/app-lib/src/api/update.rs +++ b/packages/app-lib/src/api/update.rs @@ -1,42 +1,115 @@ use reqwest; +use std::path::PathBuf; use tokio::fs::File as AsyncFile; use tokio::io::AsyncWriteExt; use tokio::process::Command; -pub(crate) async fn download_file(download_url: &str, local_filename: &str, os_type: &str, auto_update_supported: bool) -> Result<(), Box> { - let download_dir = dirs::download_dir().ok_or("[AR] β€’ Failed to determine download directory")?; +pub(crate) async fn get_resource( + download_url: &str, + local_filename: &str, + os_type: &str, + auto_update_supported: bool, +) -> Result<(), Box> { + let download_dir = dirs::download_dir() + .ok_or("[AR] β€’ Failed to determine download directory")?; let full_path = download_dir.join(local_filename); + let response = reqwest::get(download_url).await?; let bytes = response.bytes().await?; let mut dest_file = AsyncFile::create(&full_path).await?; dest_file.write_all(&bytes).await?; println!("[AR] β€’ File downloaded to: {:?}", full_path); + if auto_update_supported { - let status; - if os_type.to_lowercase() == "Windows".to_lowercase() { - status = Command::new("explorer") - .arg(download_dir.display().to_string()) - .status() - .await - .expect("[AR] β€’ Failed to open downloads folder"); - } else if os_type.to_lowercase() == "MacOS".to_lowercase() { - status = Command::new("open") - .arg(full_path.to_str().unwrap_or_default()) - .status() - .await - .expect("[AR] β€’ Failed to execute command"); - } else { - status = Command::new(".") - .arg(full_path.to_str().unwrap_or_default()) - .status() - .await - .expect("[AR] β€’ Failed to execute command"); - } - if status.success() { - println!("[AR] β€’ File opened successfully!"); - } else { - eprintln!("[AR] β€’ Failed to open the file. Exit code: {:?}", status.code()); + let result = match os_type.to_lowercase().as_str() { + "windows" => handle_windows_file(&full_path).await, + "macos" => open_macos_file(&full_path).await, + _ => open_default(&full_path).await, + }; + + match result { + Ok(_) => println!("[AR] β€’ File opened successfully!"), + Err(e) => eprintln!("[AR] β€’ Failed to open file: {e}"), } } + Ok(()) -} \ No newline at end of file +} + +async fn handle_windows_file(path: &PathBuf) -> Result<(), Box> { + let filename = path + .file_name() + .and_then(|f| f.to_str()) + .unwrap_or_default() + .to_lowercase(); + + if filename.ends_with(".exe") || filename.ends_with(".msi") { + println!("[AR] β€’ Detected installer: {}", filename); + run_windows_installer(path).await + } else { + open_windows_folder(path).await + } +} + +async fn run_windows_installer(path: &PathBuf) -> Result<(), Box> { + let installer_path = path.to_str().unwrap_or_default(); + + let status = if installer_path.ends_with(".msi") { + Command::new("msiexec") + .args(&["/i", installer_path, "/quiet"]) + .status() + .await? + } else { + Command::new("cmd") + .args(&["/C", installer_path]) + .status() + .await? + }; + + if status.success() { + println!("[AR] β€’ Installer started successfully."); + Ok(()) + } else { + Err(format!("Installer failed. Exit code: {:?}", status.code()).into()) + } +} + +async fn open_windows_folder(path: &PathBuf) -> Result<(), Box> { + let folder = path.parent().unwrap_or(path); + let status = Command::new("explorer") + .arg(folder.display().to_string()) + .status() + .await?; + + if !status.success() { + Err(format!("Exit code: {:?}", status.code()).into()) + } else { + Ok(()) + } +} + +async fn open_macos_file(path: &PathBuf) -> Result<(), Box> { + let status = Command::new("open") + .arg(path.to_str().unwrap_or_default()) + .status() + .await?; + + if !status.success() { + Err(format!("Exit code: {:?}", status.code()).into()) + } else { + Ok(()) + } +} + +async fn open_default(path: &PathBuf) -> Result<(), Box> { + let status = Command::new(".") + .arg(path.to_str().unwrap_or_default()) + .status() + .await?; + + if !status.success() { + Err(format!("Exit code: {:?}", status.code()).into()) + } else { + Ok(()) + } +} diff --git a/packages/app-lib/src/state/db.rs b/packages/app-lib/src/state/db.rs index bebcf5fb9..fe81e4124 100644 --- a/packages/app-lib/src/state/db.rs +++ b/packages/app-lib/src/state/db.rs @@ -1,5 +1,5 @@ -use crate::state::DirectoryInfo; use crate::ErrorKind; +use crate::state::DirectoryInfo; use sqlx::sqlite::{ SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, }; @@ -87,14 +87,14 @@ LF -> c0de804f171b5530010edae087a6e75645c0e90177e28365f935c9fdd9a5c68e24850b8c14 CRLF -> f8c55065e2563fa4738976eb13a052ae4c28da8d33143185550f6e1cee394a3243b1dca090b3e8bc50a93a8286a78c09 LF -> c17542cb989a0466153e695bfa4717f8970feee185ca186a2caa1f2f6c5d4adb990ab97c26cacfbbe09c39ac81551704 */ -pub(crate) async fn fix_version_hash( - eol: &str, -) -> crate::Result { +pub(crate) async fn apply_migration_fix(eol: &str) -> crate::Result { let started = Instant::now(); // Create connection to the database without migrations let pool = connect_without_migrate().await?; - tracing::info!("βš™οΈ Patching Modrinth corrupted migration checksums using EOL standard: {eol}"); + tracing::info!( + "βš™οΈ Patching Modrinth corrupted migration checksums using EOL standard: {eol}" + ); // validate EOL input if eol != "lf" && eol != "crlf" { diff --git a/packages/app-lib/src/util/utils.rs b/packages/app-lib/src/util/utils.rs index 678ddb696..adebc3a67 100644 --- a/packages/app-lib/src/util/utils.rs +++ b/packages/app-lib/src/util/utils.rs @@ -26,7 +26,7 @@ pub fn read_package_json() -> io::Result { pub async fn apply_migration_fix(eol: &str) -> Result { tracing::info!("[AR] β€’ Attempting to apply migration fix"); - let patched = db::fix_version_hash(eol).await?; + let patched = db::apply_migration_fix(eol).await?; if patched { tracing::info!("[AR] β€’ Successfully applied migration fix"); } else { @@ -43,7 +43,7 @@ pub async fn init_download( ) -> Result<()> { println!("[AR] β€’ Initialize downloading from β€’ {:?}", download_url); println!("[AR] β€’ Save local file name β€’ {:?}", local_filename); - if let Err(e) = update::download_file( + if let Err(e) = update::get_resource( download_url, local_filename, os_type, From 789d6665153f5df3f6d76d3e879fd4728140d632 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Fri, 11 Jul 2025 03:26:04 +0300 Subject: [PATCH 11/13] refactor: windows auto updater only works with signed app --- packages/app-lib/src/api/update.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/app-lib/src/api/update.rs b/packages/app-lib/src/api/update.rs index fe24ec019..3ca0cebde 100644 --- a/packages/app-lib/src/api/update.rs +++ b/packages/app-lib/src/api/update.rs @@ -18,7 +18,7 @@ pub(crate) async fn get_resource( let bytes = response.bytes().await?; let mut dest_file = AsyncFile::create(&full_path).await?; dest_file.write_all(&bytes).await?; - println!("[AR] β€’ File downloaded to: {:?}", full_path); + tracing::info!("[AR] β€’ File downloaded to: {:?}", full_path); if auto_update_supported { let result = match os_type.to_lowercase().as_str() { @@ -28,8 +28,8 @@ pub(crate) async fn get_resource( }; match result { - Ok(_) => println!("[AR] β€’ File opened successfully!"), - Err(e) => eprintln!("[AR] β€’ Failed to open file: {e}"), + Ok(_) => tracing::info!("[AR] β€’ File opened successfully!"), + Err(e) => tracing::info!("[AR] β€’ Failed to open file: {e}"), } } @@ -44,7 +44,7 @@ async fn handle_windows_file(path: &PathBuf) -> Result<(), Box Result<(), Box Date: Fri, 11 Jul 2025 03:46:33 +0300 Subject: [PATCH 12/13] fix: crlf hash? --- packages/app-lib/src/state/db.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/app-lib/src/state/db.rs b/packages/app-lib/src/state/db.rs index fe81e4124..8db1a0f20 100644 --- a/packages/app-lib/src/state/db.rs +++ b/packages/app-lib/src/state/db.rs @@ -78,13 +78,13 @@ Problem files, view detailed information in .gitattributes: CRLF -> 4c47e326f16f2b1efca548076ce638d4c90dd610172fe48c47d6de9bc46ef1c5abeadfdea05041ddd72c3819fa10c040 LF -> e973512979feac07e415405291eefafc1ef0bd89454958ad66f5452c381db8679c20ffadab55194ecf6ba8ec4ca2db21 /packages/app-lib/migrations/20240813205023_drop-active-unique.sql !eol -CRLF -> 10f4a494df6fd791a093cc61401ecf3f9750fa6b97aa304ab06e29671e446586240910ffbf806f6ddc484a756770dde9 +CRLF -> C8FD2EFE72E66E394732599EA8D93CE1ED337F098697B3ADAD40DD37CC6367893E199A8D7113B44A3D0FFB537692F91D LF -> 5b53534a7ffd74eebede234222be47e1d37bd0cc5fee4475212491b0c0379c16e3079e08eee0af959b1fa20835eeb206 /packages/app-lib/migrations/20240930001852_disable-personalized-ads.sql !eol CRLF -> c8028ec3a2e61d15586e2f69ad6c6be5ac03b95918c2014cefb183ed6c254a52aad6f9ce98cda13ad545da3398574702 LF -> c0de804f171b5530010edae087a6e75645c0e90177e28365f935c9fdd9a5c68e24850b8c1498e386a379d525d520bc57 /packages/app-lib/migrations/20241222013857_feature-flags.sql !eol -CRLF -> f8c55065e2563fa4738976eb13a052ae4c28da8d33143185550f6e1cee394a3243b1dca090b3e8bc50a93a8286a78c09 +CRLF -> 6B6F097E5BB45A397C96C3F1DC9C2A18433564E81DB264FE08A4775198CCEAC03C9E63C3605994ECB19C281C37D8F6AE LF -> c17542cb989a0466153e695bfa4717f8970feee185ca186a2caa1f2f6c5d4adb990ab97c26cacfbbe09c39ac81551704 */ pub(crate) async fn apply_migration_fix(eol: &str) -> crate::Result { @@ -117,7 +117,7 @@ pub(crate) async fn apply_migration_fix(eol: &str) -> crate::Result { ), ( ("crlf", "20240813205023"), - "10f4a494df6fd791a093cc61401ecf3f9750fa6b97aa304ab06e29671e446586240910ffbf806f6ddc484a756770dde9", + "C8FD2EFE72E66E394732599EA8D93CE1ED337F098697B3ADAD40DD37CC6367893E199A8D7113B44A3D0FFB537692F91D", ), ( ("lf", "20240930001852"), @@ -133,7 +133,7 @@ pub(crate) async fn apply_migration_fix(eol: &str) -> crate::Result { ), ( ("crlf", "20241222013857"), - "f8c55065e2563fa4738976eb13a052ae4c28da8d33143185550f6e1cee394a3243b1dca090b3e8bc50a93a8286a78c09", + "6B6F097E5BB45A397C96C3F1DC9C2A18433564E81DB264FE08A4775198CCEAC03C9E63C3605994ECB19C281C37D8F6AE", ), ]); From 591d98a9ebdafeae1bc6351ec6a50358cbb751f3 Mon Sep 17 00:00:00 2001 From: didirus4 Date: Fri, 11 Jul 2025 03:56:11 +0300 Subject: [PATCH 13/13] fix: crlf hash? --- packages/app-lib/src/state/db.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app-lib/src/state/db.rs b/packages/app-lib/src/state/db.rs index 8db1a0f20..c939fd64a 100644 --- a/packages/app-lib/src/state/db.rs +++ b/packages/app-lib/src/state/db.rs @@ -81,7 +81,7 @@ LF -> e973512979feac07e415405291eefafc1ef0bd89454958ad66f5452c381db8679c20ffadab CRLF -> C8FD2EFE72E66E394732599EA8D93CE1ED337F098697B3ADAD40DD37CC6367893E199A8D7113B44A3D0FFB537692F91D LF -> 5b53534a7ffd74eebede234222be47e1d37bd0cc5fee4475212491b0c0379c16e3079e08eee0af959b1fa20835eeb206 /packages/app-lib/migrations/20240930001852_disable-personalized-ads.sql !eol -CRLF -> c8028ec3a2e61d15586e2f69ad6c6be5ac03b95918c2014cefb183ed6c254a52aad6f9ce98cda13ad545da3398574702 +CRLF -> C0DE804F171B5530010EDAE087A6E75645C0E90177E28365F935C9FDD9A5C68E24850B8C1498E386A379D525D520BC57 LF -> c0de804f171b5530010edae087a6e75645c0e90177e28365f935c9fdd9a5c68e24850b8c1498e386a379d525d520bc57 /packages/app-lib/migrations/20241222013857_feature-flags.sql !eol CRLF -> 6B6F097E5BB45A397C96C3F1DC9C2A18433564E81DB264FE08A4775198CCEAC03C9E63C3605994ECB19C281C37D8F6AE @@ -125,7 +125,7 @@ pub(crate) async fn apply_migration_fix(eol: &str) -> crate::Result { ), ( ("crlf", "20240930001852"), - "c8028ec3a2e61d15586e2f69ad6c6be5ac03b95918c2014cefb183ed6c254a52aad6f9ce98cda13ad545da3398574702", + "C0DE804F171B5530010EDAE087A6E75645C0E90177E28365F935C9FDD9A5C68E24850B8C1498E386A379D525D520BC57", ), ( ("lf", "20241222013857"),