Compare commits

...
Author SHA1 Message Date
François-X. T. 881f1c88ba Fix command 2026-01-30 12:19:48 -05:00
François-X. T. e71c9b1085 Fix workflow file 2026-01-30 12:11:34 -05:00
François-X. T. 1bbd2a0d8d Run theseus build 2026-01-30 12:09:22 -05:00
François-X. T. 37c7cf846b Merge branch 'main' into fetch/alternative-app-installation-locations 2026-01-30 12:04:32 -05:00
François-X. T 200c1b6d2d Merge branch 'main' into fetch/alternative-app-installation-locations 2025-10-05 00:53:37 +02:00
François-X. T b8838192c4 Merge branch 'main' into fetch/alternative-app-installation-locations 2025-10-03 15:04:01 +02:00
François-X. T 07320d4300 Merge branch 'main' into fetch/alternative-app-installation-locations 2025-10-01 15:14:44 +02:00
0967e4509f Update .github/workflows/theseus-build.yml
Co-authored-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com>
Signed-off-by: François-Xavier Talbot <108630700+fetchfern@users.noreply.github.com>
2025-10-01 09:13:07 -04:00
François-X. T 0c11565843 Update artifact globs, enable dev linux builds 2025-10-01 15:12:31 +02:00
François-Xavier TalbotandFrançois-X. T c0c8a31805 Only skip attaching payment method when using ctoken (#4460) 2025-10-01 15:00:03 +02:00
ProspectorandFrançois-X. T b8f1db394d prospector/russia-blogpost (#4459)
* Add blog post

* Add 451 handling

* lint
2025-10-01 15:00:03 +02:00
a8606cd38f Update MOTD Parser package (#4455)
* chore(package): replace motd parser package with maintained version 

Signed-off-by: Kevin Zheng <dev@sfirew.com>

* changelog

* fix import

---------

Signed-off-by: Kevin Zheng <dev@sfirew.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-10-01 15:00:03 +02:00
JerozgenandFrançois-X. T 8a05101c98 App update fixes (#4450) 2025-10-01 15:00:03 +02:00
François-Xavier TalbotandFrançois-X. T ec305830b9 Skip synchronizing transactions to Anrok if missing payment intent ID (#4446)
* Skip succeeded txns with no payment platform ID

* chore: query cache, clippy, fmt
2025-10-01 15:00:03 +02:00
Alejandro GonzálezandFrançois-X. T 6f7618db14 fix(labrinth): hide hidden orgs from user profiles (#4452)
This is a follow-up to PR #4426. I initially didn't consider the
organizations an user belongs to as worth hiding, but given that user
profiles can be public, I suppose there technically is a way to exploit
them for SEO abuse. Overall, it also seems more consistent to hide them
here too.
2025-10-01 15:00:03 +02:00
François-Xavier TalbotandFrançois-X. T 0e14ff974a Tweaks and fixes to background tasks (#4447)
* adjustments

* chore: query cache, clippy, fmt
2025-10-01 15:00:03 +02:00
ProspectorandFrançois-X. T db738ffba5 changelog 2025-10-01 15:00:03 +02:00
Alejandro GonzálezandFrançois-X. T a1aaa57683 chore: cleanup unintended .sqlx folder at root of repository (#4445)
`cargo sqlx prepare` should be run in the directory of the crate that
contains the database queries instead, as that's what we're documenting
and have standarized on.
2025-10-01 15:00:03 +02:00
Josiah GlossonandFrançois-X. T 5e3abf6969 Readd MODRINTH_EXTERNAL_UPDATE_PROVIDER (#4444) 2025-10-01 15:00:03 +02:00
Emma AlexiaandFrançois-X. T 456a5f36bb Fix user deletion with new notification_deliveries table (#4437) 2025-10-01 15:00:03 +02:00
ProspectorandFrançois-X. T c768ca41e6 update time 2025-10-01 15:00:03 +02:00
ProspectorandFrançois-X. T b0341616f9 Update changelog 2025-10-01 15:00:03 +02:00
f729bd4ff1 Reworked app update flow (#3960)
* Make theseus capable of logging messages from the `log` crate

* Move update checking entirely into JS and open a modal if an update is available

* Fix formatjs on Windows and run formatjs

* Add in the buttons and body

* Fix lint

* Show update size in modal

* Fix update not being rechecked if the update modal was directly dismissed

* Slight UI tweaks

* Fix lint

* Implement skipping the update

* Implement the Update Now button

* Implement updating at next exit

* Turn download progress into an error bar on failure

* Restore 5 minute update check instead of 30 seconds

* Fix PendingUpdateData being seen as a unit struct

* Fix lint

* Make CI also lint updater code

* feat: create AppearingProgressBar component

* feat: polish update available modal

* feat: add error handling

* Open changelog with tauri-plugin-opener

* Run intl:extract

* Update completion toasts (#3978)

* Use single LAUNCHER_USER_AGENT constant for all user agents

* Fix build on Mac

* Request the update size with HEAD instead of GET

* UI tweaks

* lint

* Fix lint

* fix: hide modal header & add "Hide update reminder" button w/ tooltip

* Run intl:extract

* fix: lint issues

* fix: merge issues

* notifications.js no longer exists

* Add metered network checking

* Add a timeout to macOS is_network_metered

* Fix tauri.conf.json

* vibe debugging

* Set a dispatch queue

* Have a popup that asks you if you'd like to disable automatic file downloads if you're on a metered network

* Move UpdateModal to modal package

* Fix lint

* Add a toggle for automatic downloads

* Fix type

Co-authored-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com>
Signed-off-by: Josiah Glosson <soujournme@gmail.com>

* Redo updating UI and experience

* lint

* fix unlistener issue

* remove unneeded translation keys

* Fix expose issue

* temp disable cranelift, tweak some messages

* change version back

* Clean up App.vue

* move toast to top right

* update reload icon

* Fixed the bug!!!!!!!!!!!!

* improve messages

* intl:extract

* Add liquid glass icon file

* not you!

* use dependency injection

* lint on apple icon

* Fix imports, move download size to button

* change update check back to 5 mins

* lint + move to providers

* intl:extract

---------

Signed-off-by: Cal H. <hendersoncal117@gmail.com>
Signed-off-by: Josiah Glosson <soujournme@gmail.com>
Co-authored-by: Calum <calum@modrinth.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
Co-authored-by: Cal H. <hendersoncal117@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com>
2025-10-01 15:00:03 +02:00
JerozgenandFrançois-X. T 7a9caf3de8 "Create" modal i18n capitalization (#4441) 2025-10-01 14:59:55 +02:00
ProspectorandFrançois-X. T 91d16e814d fix withdraw button looking disabled (#4440) 2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T d221a03d50 Tax fixes (#4435)
* Only update the PaymentMethod ID if not using placeholder ID

* comment

* Create Anrok transactions for all charges

* Fix comment

* Prefer using payment method's address rather than customer address

* chore: query cache, clippy, fmt

* Retrieve stripe address from PM

* chore: query cache, clippy, fmt

* fmt

* bring back the query cache

* Better address retrieval for updating tax amounts, always update tax_last_updated

* chore: query cache, clippy, fmt

* Don't set PM in ctoken interactive session for new PIs
2025-10-01 14:59:55 +02:00
Calum H.andFrançois-X. T 723ad3e372 feat: create modal limit alerting (#4429)
* draft: layout for alert

* feat: simplify

* feat: remove dummy data

* fix: lint and widths

* feat: use chips rather than dropdown select

* feat: remove gap from admonition header v body

* Revert "feat: remove gap from admonition header v body"

This reverts commit 46cce52799.

* fix: niche fixes

* feat: update for new backend structure

* fix: i18n
2025-10-01 14:59:55 +02:00
aecsocketandFrançois-X. T 435b2d238b Hard caps on creating projects/orgs/collections (#4430)
* implement backend limits on project creation

* implement collection, org creation hard caps

* Fix limit api

* Fix clippy

* Fix limits

* Update sqlx queries

* Address PR comments on user limit structure

* sqlx prepare and clippy

* fix test maybe
2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T e9a837de02 More billing fixes (#4431)
* Only update the PaymentMethod ID if not using placeholder ID

* comment

* Create Anrok transactions for all charges

* Fix comment

* Prefer using payment method's address rather than customer address

* chore: query cache, clippy, fmt

* Retrieve stripe address from PM

* chore: query cache, clippy, fmt

* fmt

* bring back the query cache
2025-10-01 14:59:55 +02:00
290c9fc196 feat(labrinth): hide orgs without a purpose, re-enable organization creation (#4426)
* chore(labrinth): set `DELPHI_URL` to a valid default in `.env.local`

* feat(labrinth): make orgs not publicly visible until they meet some conditions

* Revert "Org disabled frontend (#4424)"

This reverts commit 2492b11ec0.

* changelog: update for re-enabling organization creation

* chore: run `sqlx prepare`

* chore(labrinth): tweak tests to work with new org changes

* tweak: apply @triphora's suggestion

Co-authored-by: Emma Alexia <emma@modrinth.com>
Signed-off-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com>

* tweak: document `is_visible_organization` relationship with `Project#is_searchable`

---------

Signed-off-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com>
Co-authored-by: Emma Alexia <emma@modrinth.com>
2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T 4a6380a84b Billing fixes (#4422)
* Only update the PaymentMethod ID if not using placeholder ID

* comment

* Create Anrok transactions for all charges

* Fix comment

* Prefer using payment method's address rather than customer address

* chore: query cache, clippy, fmt
2025-10-01 14:59:55 +02:00
ProspectorandFrançois-X. T 9b81e26a60 update changelog 2025-10-01 14:59:55 +02:00
ProspectorandFrançois-X. T 0ac4b11aca Org disabled frontend (#4424) 2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T 9eaa39f0cd Charge tax on products (#4361)
* Initial Anrok integration

* Query cache, fmt, clippy

* Fmt

* Use payment intent function in edit_subscription

* Attach Anrok client, use payments in index_billing

* Integrate Anrok with refunds

* Bug fixes

* More bugfixes

* Fix resubscriptions

* Medal promotion bugfixes

* Use stripe metadata constants everywhere

* Pre-fill values in products_tax_identifiers

* Cleanup billing route module

* Cleanup

* Email notification for tax charge

* Don't charge tax on users which haven't been notified of tax change

* Fix taxnotification.amount templates

* Update .env.docker-compose

* Update .env.local

* Clippy

* Fmt

* Query cache

* Periodically update tax amount on upcoming charges

* Fix queries

* Skip indexing tax amount on charges if no charges to process

* chore: query cache, clippy, fmt

* Fix a lot of things

* Remove test code

* chore: query cache, clippy, fmt

* Fix money formatting

* Fix conflicts

* Extra documentation, handle tax association properly

* Track loss in tax drift

* chore: query cache, clippy, fmt

* Add subscription.id variable

* chore: query cache, clippy, fmt

* chore: query cache, clippy, fmt
2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T e853e8bdcc Tax compliance adjustments (#4414)
* tax compliance adjustments

* chore: query cache, clippy, fmt
2025-10-01 14:59:55 +02:00
98c770338b "Submit for review" button translation (#4381)
* "Submit for review" button translation

* Fix invitation message in the code

* Run web:fix

* Run intl:extract

---------

Co-authored-by: Calum H. <contact@cal.engineer>
2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T d08c39175b Fill variables for subject line (#4415) 2025-10-01 14:59:55 +02:00
JerozgenandFrançois-X. T 93b992d5ef Add IntelliJ project icon (#4412) 2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T 0f467f1f6f Fix version upload for popular projects (#4410)
* Only notify users that exist

* chore: query cache, clippy, fmt
2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T 516de6fade Less emails per transactinos (#4406) 2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T a2460b5732 Fix track1099 (#4405)
* don't parse datetime

* fix import

* update comments
2025-10-01 14:59:55 +02:00
aecsocketandFrançois-X. T 0bcfface0b Allow users to manage their own affiliate codes (#4392)
* Allow users to manage their own affiliate codes

* Add a badge to restrict access to affiliate codes

* sqlx prepare and clippy
2025-10-01 14:59:55 +02:00
François-Xavier TalbotandFrançois-X. T 7df06d7eab more loggging (#4404) 2025-10-01 14:59:55 +02:00
Calum H.andFrançois-X. T b980681912 feat: email template for subscription price changes due to tax (#4386)
* feat: subscription tax change email

* feat: wording

* feat: subscription id var for support & finalize tax change email script
2025-10-01 14:59:55 +02:00
Modrinth BotandFrançois-X. T 438254f4f8 New translations from Crowdin (main) (#4401) 2025-10-01 14:59:55 +02:00
JerozgenandFrançois-X. T 2174fc8b2d "Create a server" tooltip i18n fixes (#4402) 2025-10-01 14:59:55 +02:00
ProspectorandFrançois-X. T cdabdebeaf Changelog 2025-10-01 14:59:54 +02:00
ac1e0886ab feat: temporary tax compliance impl (#4393)
* feat: temporary tax compliance impl

* fix: lint & intl

* Update banner, reload page on submit, and fix withdraw button disabled state

---------

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2025-10-01 14:59:54 +02:00
Calum H.andFrançois-X. T 7eff66f47b fix: hide versions checkbox depending on what game versions are avail (#4396)
* fix: hide versions checkbox depending on what game versions are avail

* refactor: use set instead of map
2025-10-01 14:59:54 +02:00
teaSummerandFrançois-X. T c22dc2086e fix(app): properly show all versions and notify loaders (#4395)
* fix(app): properly show all versions and notify loaders

* fix lint
2025-10-01 14:59:54 +02:00
François-Xavier TalbotandGitHub 9cac99a12f Merge branch 'main' into fetch/alternative-app-installation-locations 2025-09-19 13:40:14 +01:00
fetch a2e9eb0c3a Tweak build 2025-09-18 16:55:39 +01:00
fetch 85a0378cd0 Force bash 2025-09-17 19:48:00 +01:00
fetch cc4023a114 Fix updater buidls 2025-09-17 19:29:45 +01:00
fetch ba4112947e Fix initial setup 2025-09-17 19:18:52 +01:00
fetch 210862c27a Fix identifier use 2025-09-17 18:42:14 +01:00
fetch e1208ef8a1 Don't hardcode ModrinthApp as app identifier 2025-09-17 18:10:20 +01:00
fetch b1a2a84434 Fix theseus build 2025-09-17 17:01:24 +01:00
fetch 719e001a8f Fix MacOS builds 2025-09-16 00:38:22 +01:00
fetch d880952135 Correct paths 2025-09-16 00:17:09 +01:00
fetch 7a758c1f46 Fix json 2025-09-16 00:13:33 +01:00
fetch 7ddb2c0561 Select branches 2025-09-16 00:07:55 +01:00
fetch da47b5d741 Try patching tauri config 2025-09-16 00:05:47 +01:00
10 changed files with 168 additions and 43 deletions
+23 -3
View File
@@ -60,6 +60,21 @@ jobs:
node-version-file: .nvmrc
cache: pnpm
- name: 📄 Generate tauri-dev.conf.json
shell: bash
run: |
GIT_HASH=$(git rev-parse --short HEAD)
cat > apps/app/tauri-dev.conf.json <<EOF
{
"productName": "Modrinth App (dev-${GIT_HASH})",
"mainBinaryName": "Modrinth App (dev-${GIT_HASH})",
"identifier": "ModrinthApp-dev-${GIT_HASH}",
"bundle": {
"fileAssociations": []
}
}
EOF
- name: 🧰 Install Linux build dependencies
if: startsWith(matrix.platform, 'ubuntu')
run: |
@@ -103,7 +118,7 @@ jobs:
fi
- name: 🔨 Build macOS app
run: pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json
run: ${{ github.ref == 'refs/heads/main' && 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --target universal-apple-darwin --config tauri-dev.conf.json' }}
if: startsWith(matrix.platform, 'macos')
env:
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
@@ -117,7 +132,7 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
- name: 🔨 Build Linux app
run: pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json
run: ${{ github.ref == 'refs/heads/main' && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json' }}
if: startsWith(matrix.platform, 'ubuntu')
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
@@ -128,7 +143,7 @@ jobs:
[System.Convert]::FromBase64String("$env:DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_BASE64") | Set-Content -Path signer-client-cert.p12 -AsByteStream
$env:DIGICERT_ONE_SIGNER_CREDENTIALS = "$env:DIGICERT_ONE_SIGNER_API_KEY|$PWD\signer-client-cert.p12|$env:DIGICERT_ONE_SIGNER_CLIENT_CERTIFICATE_PASSWORD"
$env:JAVA_HOME = "$env:JAVA_HOME_17_X64"
pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles 'nsis,updater'
${{ github.ref == 'refs/heads/main' && 'pnpm --filter=@modrinth/app run tauri build --config tauri-release.conf.json --verbose --bundles "nsis,updater"' || 'pnpm --filter=@modrinth/app run tauri build --config tauri-dev.conf.json --verbose --bundles "nsis,updater"' }}
Remove-Item -Path signer-client-cert.p12 -ErrorAction SilentlyContinue
if: startsWith(matrix.platform, 'windows')
env:
@@ -146,7 +161,12 @@ jobs:
target/release/bundle/appimage/Modrinth App_*.AppImage*
target/release/bundle/deb/Modrinth App_*.deb*
target/release/bundle/rpm/Modrinth App-*.rpm*
target/release/bundle/appimage/Modrinth App (dev-*)_*.AppImage*
target/release/bundle/deb/Modrinth App (dev-*)_*.deb*
target/release/bundle/rpm/Modrinth App (dev-*)-*.rpm*
target/universal-apple-darwin/release/bundle/macos/Modrinth App.app.tar.gz*
target/universal-apple-darwin/release/bundle/macos/Modrinth App (dev-*)*.app.tar.gz
target/universal-apple-darwin/release/bundle/dmg/Modrinth App (dev-*)*.dmg
target/universal-apple-darwin/release/bundle/dmg/Modrinth App_*.dmg*
target/release/bundle/nsis/Modrinth App_*-setup.exe*
target/release/bundle/nsis/Modrinth App_*-setup.nsis.zip*
+2 -2
View File
@@ -38,10 +38,10 @@ pub async fn authenticate_run() -> theseus::Result<Credentials> {
async fn main() -> theseus::Result<()> {
println!("Starting.");
let _log_guard = theseus::start_logger();
let _log_guard = theseus::start_logger("ModrinthApp");
// Initialize state
State::init().await?;
State::init("ModrinthApp".to_owned()).await?;
let worlds = get_recent_worlds(4, EnumSet::all()).await?;
for world in worlds {
+5 -2
View File
@@ -1,4 +1,5 @@
use crate::api::Result;
use tauri::Runtime;
use theseus::prelude::*;
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
@@ -28,7 +29,9 @@ pub async fn settings_set(settings: Settings) -> Result<()> {
}
#[tauri::command]
pub async fn cancel_directory_change() -> Result<()> {
settings::cancel_directory_change().await?;
pub async fn cancel_directory_change<R: Runtime>(
handle: tauri::AppHandle<R>,
) -> Result<()> {
settings::cancel_directory_change(&handle.config().identifier).await?;
Ok(())
}
+6 -4
View File
@@ -107,10 +107,12 @@ pub async fn open_path<R: Runtime>(app: tauri::AppHandle<R>, path: PathBuf) {
#[tauri::command]
pub async fn show_launcher_logs_folder<R: Runtime>(app: tauri::AppHandle<R>) {
let path = DirectoryInfo::launcher_logs_dir().unwrap_or_default();
// failure to get folder just opens filesystem
// (ie: if in debug mode only and launcher_logs never created)
open_path(app, path).await;
if let Some(d) = DirectoryInfo::global_handle_if_ready() {
let path = d.launcher_logs_dir().unwrap_or_default();
// failure to get folder just opens filesystem
// (ie: if in debug mode only and launcher_logs never created)
open_path(app, path).await;
}
}
// Get opening command
+75 -4
View File
@@ -27,9 +27,77 @@ async fn initialize_state(app: tauri::AppHandle) -> api::Result<()> {
tracing::info!("Initializing app event state...");
theseus::EventState::init(app.clone()).await?;
tracing::info!("Initializing app state...");
State::init().await?;
let app_identifier = app.config().identifier.clone();
#[cfg(feature = "updater")]
'updater: {
if env::var("MODRINTH_EXTERNAL_UPDATE_PROVIDER").is_ok() {
State::init(app_identifier).await?;
break 'updater;
}
use tauri_plugin_updater::UpdaterExt;
let updater = app.updater_builder().build()?;
let update_fut = updater.check();
tracing::info!("Initializing app state...");
State::init(app_identifier).await?;
let check_bar = theseus::init_loading(
theseus::LoadingBarType::CheckingForUpdates,
1.0,
"Checking for updates...",
)
.await?;
tracing::info!("Checking for updates...");
let update = update_fut.await;
drop(check_bar);
if let Some(update) = update.ok().flatten() {
tracing::info!("Update found: {:?}", update.download_url);
let loader_bar_id = theseus::init_loading(
theseus::LoadingBarType::LauncherUpdate {
version: update.version.clone(),
current_version: update.current_version.clone(),
},
1.0,
"Updating Modrinth App...",
)
.await?;
// 100 MiB
const DEFAULT_CONTENT_LENGTH: u64 = 1024 * 1024 * 100;
update
.download_and_install(
|chunk_length, content_length| {
let _ = theseus::emit_loading(
&loader_bar_id,
(chunk_length as f64)
/ (content_length
.unwrap_or(DEFAULT_CONTENT_LENGTH)
as f64),
None,
);
},
|| {},
)
.await?;
app.restart();
}
}
#[cfg(not(feature = "updater"))]
{
State::init(app_identifier).await?;
}
tracing::info!("Finished checking for updates!");
let state = State::get().await?;
app.asset_protocol_scope()
.allow_directory(state.directories.caches_dir(), true)?;
@@ -110,7 +178,10 @@ fn main() {
RUST_LOG="theseus=trace" {run command}
*/
let _log_guard = theseus::start_logger();
let tauri_context = tauri::generate_context!();
let _log_guard = theseus::start_logger(&tauri_context.config().identifier);
tracing::info!("Initialized tracing subscriber. Loading Modrinth App!");
@@ -243,7 +314,7 @@ fn main() {
]);
tracing::info!("Initializing app...");
let app = builder.build(tauri::generate_context!());
let app = builder.build(tauri_context);
match app {
Ok(app) => {
+4 -2
View File
@@ -23,10 +23,12 @@ pub async fn set(settings: Settings) -> crate::Result<()> {
}
#[tracing::instrument]
pub async fn cancel_directory_change() -> crate::Result<()> {
pub async fn cancel_directory_change(
app_identifier: &str,
) -> crate::Result<()> {
// This is called to handle state initialization errors due to folder migrations
// failing, so fetching a DB connection pool from `State::get` is not reliable here
let pool = crate::state::db::connect().await?;
let pool = crate::state::db::connect(app_identifier).await?;
let mut settings = Settings::get(&pool).await?;
if let Some(prev_custom_dir) = settings.prev_custom_dir {
+5 -3
View File
@@ -18,7 +18,7 @@
// Handling for the live development logging
// This will log to the console, and will not log to a file
#[cfg(debug_assertions)]
pub fn start_logger() -> Option<()> {
pub fn start_logger(_app_identifier: &str) -> Option<()> {
use tracing_subscriber::prelude::*;
let filter = tracing_subscriber::EnvFilter::try_from_default_env()
@@ -36,7 +36,7 @@ pub fn start_logger() -> Option<()> {
// Handling for the live production logging
// This will log to a file in the logs directory, and will not show any logs in the console
#[cfg(not(debug_assertions))]
pub fn start_logger() -> Option<()> {
pub fn start_logger(app_identifier: &str) -> Option<()> {
use crate::prelude::DirectoryInfo;
use chrono::Local;
use std::fs::OpenOptions;
@@ -44,7 +44,9 @@ pub fn start_logger() -> Option<()> {
use tracing_subscriber::prelude::*;
// Initialize and get logs directory path
let logs_dir = if let Some(d) = DirectoryInfo::launcher_logs_dir() {
let logs_dir = if let Some(d) =
DirectoryInfo::launcher_logs_dir_path(app_identifier)
{
d
} else {
eprintln!("Could not start logger");
+6 -5
View File
@@ -6,12 +6,13 @@ use sqlx::{Pool, Sqlite};
use std::str::FromStr;
use std::time::Duration;
pub(crate) async fn connect() -> crate::Result<Pool<Sqlite>> {
let settings_dir = DirectoryInfo::get_initial_settings_dir().ok_or(
crate::ErrorKind::FSError(
pub(crate) async fn connect(
app_identifier: &str,
) -> crate::Result<Pool<Sqlite>> {
let settings_dir = DirectoryInfo::initial_settings_dir_path(app_identifier)
.ok_or(crate::ErrorKind::FSError(
"Could not find valid config dir".to_string(),
),
)?;
))?;
if !settings_dir.exists() {
crate::util::io::create_dir_all(&settings_dir).await?;
+32 -13
View File
@@ -1,6 +1,7 @@
//! Theseus directory information
use crate::LoadingBarType;
use crate::event::emit::{emit_loading, init_loading};
use crate::state::LAUNCHER_STATE;
use crate::state::{JavaVersion, Profile, Settings};
use crate::util::fetch::IoSemaphore;
use dashmap::DashSet;
@@ -17,24 +18,35 @@ pub const METADATA_FOLDER_NAME: &str = "meta";
pub struct DirectoryInfo {
pub settings_dir: PathBuf, // Base settings directory- app database
pub config_dir: PathBuf, // Base config directory- instances, minecraft downloads, etc. Changeable as a setting.
pub app_identifier: String,
}
impl DirectoryInfo {
pub fn global_handle_if_ready() -> Option<&'static Self> {
LAUNCHER_STATE.get().map(|x| &x.directories)
}
pub fn get_initial_settings_dir(&self) -> Option<PathBuf> {
Self::initial_settings_dir_path(&self.app_identifier)
}
// Get the settings directory
// init() is not needed for this function
pub fn get_initial_settings_dir() -> Option<PathBuf> {
pub fn initial_settings_dir_path(app_identifier: &str) -> Option<PathBuf> {
Self::env_path("THESEUS_CONFIG_DIR")
.or_else(|| Some(dirs::data_dir()?.join("ModrinthApp")))
.or_else(|| Some(dirs::data_dir()?.join(app_identifier)))
}
/// Get all paths needed for Theseus to operate properly
#[tracing::instrument]
pub async fn init(config_dir: Option<String>) -> crate::Result<Self> {
let settings_dir = Self::get_initial_settings_dir().ok_or(
crate::ErrorKind::FSError(
pub async fn init(
config_dir: Option<String>,
app_identifier: &str,
) -> crate::Result<Self> {
let settings_dir = Self::initial_settings_dir_path(app_identifier)
.ok_or(crate::ErrorKind::FSError(
"Could not find valid settings dir".to_string(),
),
)?;
))?;
fs::create_dir_all(&settings_dir).await.map_err(|err| {
crate::ErrorKind::FSError(format!(
@@ -48,6 +60,7 @@ impl DirectoryInfo {
Ok(Self {
settings_dir,
config_dir,
app_identifier: app_identifier.to_owned(),
})
}
@@ -154,8 +167,14 @@ impl DirectoryInfo {
}
#[inline]
pub fn launcher_logs_dir() -> Option<PathBuf> {
Self::get_initial_settings_dir()
pub fn launcher_logs_dir(&self) -> Option<PathBuf> {
self.get_initial_settings_dir()
.map(|d| d.join(LAUNCHER_LOGS_FOLDER_NAME))
}
#[inline]
pub fn launcher_logs_dir_path(app_identifier: &str) -> Option<PathBuf> {
Self::initial_settings_dir_path(app_identifier)
.map(|d| d.join(LAUNCHER_LOGS_FOLDER_NAME))
}
@@ -176,15 +195,15 @@ impl DirectoryInfo {
settings: &mut Settings,
exec: E,
io_semaphore: &IoSemaphore,
app_identifier: &str,
) -> crate::Result<()>
where
E: sqlx::Executor<'a, Database = sqlx::Sqlite> + Copy,
{
let app_dir = DirectoryInfo::get_initial_settings_dir().ok_or(
crate::ErrorKind::FSError(
let app_dir = DirectoryInfo::initial_settings_dir_path(app_identifier)
.ok_or(crate::ErrorKind::FSError(
"Could not find valid config dir".to_string(),
),
)?;
))?;
if let Some(ref prev_custom_dir) = settings.prev_custom_dir {
let prev_dir = PathBuf::from(prev_custom_dir);
+10 -5
View File
@@ -80,9 +80,9 @@ pub struct State {
}
impl State {
pub async fn init() -> crate::Result<()> {
pub async fn init(app_identifier: String) -> crate::Result<()> {
let state = LAUNCHER_STATE
.get_or_try_init(Self::initialize_state)
.get_or_try_init(move || Self::initialize_state(app_identifier))
.await?;
tokio::task::spawn(async move {
@@ -132,9 +132,11 @@ impl State {
}
#[tracing::instrument]
async fn initialize_state() -> crate::Result<Arc<Self>> {
async fn initialize_state(
app_identifier: String,
) -> crate::Result<Arc<Self>> {
tracing::info!("Connecting to app database");
let pool = db::connect().await?;
let pool = db::connect(&app_identifier).await?;
legacy_converter::migrate_legacy_data(&pool).await?;
@@ -153,9 +155,12 @@ impl State {
&mut settings,
&pool,
&io_semaphore,
&app_identifier,
)
.await?;
let directories = DirectoryInfo::init(settings.custom_dir).await?;
let directories =
DirectoryInfo::init(settings.custom_dir, &app_identifier).await?;
let discord_rpc = DiscordGuard::init()?;