Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
injectNotificationManager,
OverflowMenu,
StyledInput,
Toggle,
useVIntl,
} from '@modrinth/ui'
import { useQueryClient } from '@tanstack/vue-query'
Expand Down Expand Up @@ -44,6 +45,21 @@ const releaseChannelDisabledItems = computed<ReleaseChannel[]>(() =>
savingReleaseChannel.value ? [...releaseChannelOptions] : [],
)

const autoUpdateModpack = ref(instance.value.auto_update_modpack ?? false)

const hasLinkedModpack = computed(() => !!instance.value.linked_data)

watch(autoUpdateModpack, async (value) => {
await edit(instance.value.path, { auto_update_modpack: value }).catch(handleError)
})

watch(
() => instance.value.auto_update_modpack,
(val) => {
autoUpdateModpack.value = val ?? false
},
)

const newCategoryInput = ref('')

const installing = computed(() => instance.value.install_stage !== 'installed')
Expand Down Expand Up @@ -263,6 +279,15 @@ const messages = defineMessages({
id: 'instance.settings.tabs.general.update-channel.select',
defaultMessage: 'Select update channel',
},
autoUpdateModpack: {
id: 'instance.settings.tabs.general.auto-update-modpack',
defaultMessage: 'Auto-update modpack',
},
autoUpdateModpackDescription: {
id: 'instance.settings.tabs.general.auto-update-modpack.description',
defaultMessage:
'Automatically update this modpack to the latest version. Updates are checked before launching and periodically in the background.',
},
deleteInstance: {
id: 'instance.settings.tabs.general.delete',
defaultMessage: 'Delete instance',
Expand Down Expand Up @@ -409,6 +434,18 @@ const messages = defineMessages({
</p>
</div>

<div v-if="hasLinkedModpack" class="flex items-center justify-between gap-4 mt-6">
<div>
<h2 class="m-0 text-lg font-semibold text-contrast">
{{ formatMessage(messages.autoUpdateModpack) }}
</h2>
<p class="m-0 mt-1 text-sm">
{{ formatMessage(messages.autoUpdateModpackDescription) }}
</p>
</div>
<Toggle id="auto-update-modpack" v-model="autoUpdateModpack" />
</div>

<div class="flex flex-col gap-2.5 mt-6">
<h2 id="delete-instance-label" class="m-0 text-lg font-semibold text-contrast block">
{{ formatMessage(messages.deleteInstance) }}
Expand Down
5 changes: 5 additions & 0 deletions apps/app-frontend/src/helpers/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ export async function update_managed_modrinth_version(
})
}

// Auto-update all modpacks with auto_update_modpack enabled
export async function auto_update_all_modpacks(): Promise<void> {
return await invoke('plugin:profile|profile_auto_update_all_modpacks')
}

// Repair a managed Modrinth profile
export async function update_repair_modrinth(path: string): Promise<void> {
return await invoke('plugin:profile|profile_repair_managed_modrinth', { path })
Expand Down
1 change: 1 addition & 0 deletions apps/app-frontend/src/helpers/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type GameInstance = {
force_fullscreen?: boolean
game_resolution?: [number, number]
hooks: Hooks
auto_update_modpack?: boolean
}

type InstallStage =
Expand Down
6 changes: 6 additions & 0 deletions apps/app-frontend/src/locales/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,12 @@
"instance.settings.tabs.general": {
"message": "General"
},
"instance.settings.tabs.general.auto-update-modpack": {
"message": "Auto-update modpack"
},
"instance.settings.tabs.general.auto-update-modpack.description": {
"message": "Automatically update this modpack to the latest version. Updates are checked before launching and periodically in the background."
},
"instance.settings.tabs.general.delete": {
"message": "Delete instance"
},
Expand Down
1 change: 1 addition & 0 deletions apps/app/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ fn main() {
"profile_edit_icon",
"profile_export_mrpack",
"profile_get_pack_export_candidates",
"profile_auto_update_all_modpacks",
])
.default_permission(
DefaultPermissionRule::AllowAllCommands,
Expand Down
18 changes: 18 additions & 0 deletions apps/app/src/api/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
profile_edit_icon,
profile_export_mrpack,
profile_get_pack_export_candidates,
profile_auto_update_all_modpacks,
])
.build()
}
Expand Down Expand Up @@ -432,6 +433,20 @@ pub struct EditProfile {
)]
pub game_resolution: Option<Option<WindowSize>>,
pub hooks: Option<Hooks>,

#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "serde_with::rust::double_option"
)]
pub auto_update_modpack: Option<Option<bool>>,
}

// Auto-update all modpacks with auto_update_modpack enabled
// invoke('plugin:profile|profile_auto_update_all_modpacks')
#[tauri::command]
pub async fn profile_auto_update_all_modpacks() -> Result<()> {
Ok(profile::auto_update_all_modpacks().await?)
}

// Edits a profile
Expand Down Expand Up @@ -480,6 +495,9 @@ pub async fn profile_edit(path: &str, edit_profile: EditProfile) -> Result<()> {
if let Some(hooks) = edit_profile.hooks.clone() {
prof.hooks = hooks;
}
if let Some(auto_update_modpack) = edit_profile.auto_update_modpack {
prof.auto_update_modpack = auto_update_modpack;
}

prof.modified = chrono::Utc::now();

Expand Down
13 changes: 13 additions & 0 deletions apps/app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ fn main() {
tracing::warn!("Failed to set window shadow: {e}");
}

// Background task: auto-update modpacks every 60 minutes
tauri::async_runtime::spawn(async move {
// Wait for state to initialize before first check
tokio::time::sleep(std::time::Duration::from_secs(30)).await;
loop {
tracing::debug!("Running background modpack auto-update check");
if let Err(e) = theseus::profile::auto_update_all_modpacks().await {
tracing::warn!("Background modpack auto-update failed: {e}");
}
tokio::time::sleep(std::time::Duration::from_secs(3600)).await;
}
});

Ok(())
});

Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/AGENTS.md
2 changes: 1 addition & 1 deletion packages/api-client/AGENTS.md

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE profiles ADD COLUMN auto_update_modpack INTEGER NULL;
1 change: 1 addition & 0 deletions packages/app-lib/src/api/profile/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ pub async fn profile_create(
wrapper: None,
post_exit: None,
},
auto_update_modpack: None,
};

let result = async {
Expand Down
Loading