diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 4f5bd1b2a..3bec57114 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 { areUpdatesEnabled, getOS, isDev, restartApp } from '@/helpers/utils.js' +import { areUpdatesEnabled, 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' @@ -59,7 +59,6 @@ import { get_opening_command, initialize_state } from '@/helpers/state' import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state' import { renderString } from '@modrinth/utils' import { useFetch } from '@/helpers/fetch.js' -import { check } from '@tauri-apps/plugin-updater' import NavButton from '@/components/ui/NavButton.vue' import { get as getCreds, login, logout } from '@/helpers/mr_auth.js' import { get_user } from '@/helpers/cache.js' @@ -72,6 +71,7 @@ import QuickInstanceSwitcher from '@/components/ui/QuickInstanceSwitcher.vue' import UpdateModal from '@/components/ui/UpdateModal.vue' import { get_available_capes, get_available_skins } from './helpers/skins' import { generateSkinPreviews } from './helpers/rendering/batch-skin-renderer' +import { get as getSettings, set as setSettings } from '@/helpers/settings.ts' const themeStore = useTheming() @@ -347,6 +347,7 @@ async function handleCommand(e) { } const availableUpdate = ref(null) +const updateSkipped = ref(false) const updateModal = useTemplateRef('updateModal') async function checkUpdates() { if (!(await areUpdatesEnabled())) { @@ -361,17 +362,30 @@ async function checkUpdates() { } const update = await invoke('plugin:updater|check') - if (!!update) { - console.log(`Update ${update.version} is available.`) - if (update.version === availableUpdate.value?.version) { - console.log( - 'Skipping update modal because the new version is the same as the dismissed update', - ) - } else { - availableUpdate.value = update - updateModal.value.show(update) - } + if (!update) { + return } + + console.log(`Update ${update.version} is available.`) + + if (update.version === availableUpdate.value?.version) { + console.log( + 'Skipping update modal because the new version is the same as the dismissed update', + ) + return + } + + availableUpdate.value = update + + const settings = await getSettings() + if (settings.skipped_update === update.version) { + updateSkipped.value = true + console.log('Skipping update modal because the user chose to skip this update') + return + } + + updateSkipped.value = false + updateModal.value.show(update) } await performCheck() @@ -384,6 +398,23 @@ async function checkUpdates() { ) } +async function skipUpdate(version) { + updateSkipped.value = true + let settings = await getSettings() + settings.skipped_update = version + await setSettings(settings) +} + +async function forceOpenUpdateModal() { + if (updateSkipped.value) { + updateSkipped.value = false + let settings = await getSettings() + settings.skipped_update = null + await setSettings(settings) + } + updateModal.value.show(availableUpdate.value) +} + function handleClick(e) { let target = e.target while (target != null) { @@ -425,7 +456,7 @@ function handleAuxClick(e) {
- + @@ -480,10 +511,11 @@ function handleAuxClick(e) { - - + + + diff --git a/apps/app-frontend/src/components/ui/UpdateModal.vue b/apps/app-frontend/src/components/ui/UpdateModal.vue index 7aa165af5..fc831a777 100644 --- a/apps/app-frontend/src/components/ui/UpdateModal.vue +++ b/apps/app-frontend/src/components/ui/UpdateModal.vue @@ -17,12 +17,12 @@ - - @@ -40,6 +40,10 @@ import { getUpdateSize } from '@/helpers/utils' import { formatBytes } from '@modrinth/utils' import { handleError } from '@/store/notifications' +const emit = defineEmits<{ + (e: 'updateSkipped', version: string): void +}>() + const { formatMessage } = useVIntl() const messages = defineMessages({ @@ -100,6 +104,11 @@ function hide() { } defineExpose({ show, hide, isOpen }) + +function skipUpdate() { + hide() + emit('updateSkipped', update.value!.version) +} diff --git a/apps/app-frontend/src/helpers/settings.ts b/apps/app-frontend/src/helpers/settings.ts index c256575a4..6b00e9bb8 100644 --- a/apps/app-frontend/src/helpers/settings.ts +++ b/apps/app-frontend/src/helpers/settings.ts @@ -62,6 +62,7 @@ export type AppSettings = { developer_mode: boolean feature_flags: Record + skipped_update: string | null } // Get full settings object diff --git a/apps/app-frontend/src/helpers/utils.js b/apps/app-frontend/src/helpers/utils.js index e5d1568c5..1cda120de 100644 --- a/apps/app-frontend/src/helpers/utils.js +++ b/apps/app-frontend/src/helpers/utils.js @@ -45,13 +45,6 @@ export async function restartApp() { return await invoke('restart_app') } -/** - * @deprecated This method is no longer needed, and just returns its parameter - */ -export function sanitizePotentialFileUrl(url) { - return url -} - export const releaseColor = (releaseType) => { switch (releaseType) { case 'release': diff --git a/packages/app-lib/.sqlx/query-3613473fb4d836ee0fb3c292e6bf5e50912064c29ebf1a1e5ead79c44c37e64c.json b/packages/app-lib/.sqlx/query-6dd3b14f3736735ee9a734062c990d152b0ffb7abf87a729931dc6c54754be6d.json similarity index 86% rename from packages/app-lib/.sqlx/query-3613473fb4d836ee0fb3c292e6bf5e50912064c29ebf1a1e5ead79c44c37e64c.json rename to packages/app-lib/.sqlx/query-6dd3b14f3736735ee9a734062c990d152b0ffb7abf87a729931dc6c54754be6d.json index 2fce764bc..63320e4c4 100644 --- a/packages/app-lib/.sqlx/query-3613473fb4d836ee0fb3c292e6bf5e50912064c29ebf1a1e5ead79c44c37e64c.json +++ b/packages/app-lib/.sqlx/query-6dd3b14f3736735ee9a734062c990d152b0ffb7abf87a729931dc6c54754be6d.json @@ -1,12 +1,12 @@ { "db_name": "SQLite", - "query": "\n UPDATE settings\n SET\n max_concurrent_writes = $1,\n max_concurrent_downloads = $2,\n\n theme = $3,\n default_page = $4,\n collapsed_navigation = $5,\n advanced_rendering = $6,\n native_decorations = $7,\n\n discord_rpc = $8,\n developer_mode = $9,\n telemetry = $10,\n personalized_ads = $11,\n\n onboarded = $12,\n\n extra_launch_args = jsonb($13),\n custom_env_vars = jsonb($14),\n mc_memory_max = $15,\n mc_force_fullscreen = $16,\n mc_game_resolution_x = $17,\n mc_game_resolution_y = $18,\n hide_on_process_start = $19,\n\n hook_pre_launch = $20,\n hook_wrapper = $21,\n hook_post_exit = $22,\n\n custom_dir = $23,\n prev_custom_dir = $24,\n migrated = $25,\n\n toggle_sidebar = $26,\n feature_flags = $27,\n hide_nametag_skins_page = $28\n ", + "query": "\n UPDATE settings\n SET\n max_concurrent_writes = $1,\n max_concurrent_downloads = $2,\n\n theme = $3,\n default_page = $4,\n collapsed_navigation = $5,\n advanced_rendering = $6,\n native_decorations = $7,\n\n discord_rpc = $8,\n developer_mode = $9,\n telemetry = $10,\n personalized_ads = $11,\n\n onboarded = $12,\n\n extra_launch_args = jsonb($13),\n custom_env_vars = jsonb($14),\n mc_memory_max = $15,\n mc_force_fullscreen = $16,\n mc_game_resolution_x = $17,\n mc_game_resolution_y = $18,\n hide_on_process_start = $19,\n\n hook_pre_launch = $20,\n hook_wrapper = $21,\n hook_post_exit = $22,\n\n custom_dir = $23,\n prev_custom_dir = $24,\n migrated = $25,\n\n toggle_sidebar = $26,\n feature_flags = $27,\n hide_nametag_skins_page = $28,\n skipped_update = $29\n ", "describe": { "columns": [], "parameters": { - "Right": 28 + "Right": 29 }, "nullable": [] }, - "hash": "3613473fb4d836ee0fb3c292e6bf5e50912064c29ebf1a1e5ead79c44c37e64c" + "hash": "6dd3b14f3736735ee9a734062c990d152b0ffb7abf87a729931dc6c54754be6d" } diff --git a/packages/app-lib/.sqlx/query-6e3fa492c085ebb8e7280dd4d55cdcf73da199ea6ac05ee3ee798ece80d877cf.json b/packages/app-lib/.sqlx/query-6e3fa492c085ebb8e7280dd4d55cdcf73da199ea6ac05ee3ee798ece80d877cf.json index 9742cb7b4..22e39e75b 100644 --- a/packages/app-lib/.sqlx/query-6e3fa492c085ebb8e7280dd4d55cdcf73da199ea6ac05ee3ee798ece80d877cf.json +++ b/packages/app-lib/.sqlx/query-6e3fa492c085ebb8e7280dd4d55cdcf73da199ea6ac05ee3ee798ece80d877cf.json @@ -41,7 +41,7 @@ { "name": "display_claims!: serde_json::Value", "ordinal": 7, - "type_info": "Null" + "type_info": "Text" } ], "parameters": { diff --git a/packages/app-lib/.sqlx/query-5193f519f021b2e7013cdb67a6e1a31ae4bd7532d02f8b00b43d5645351941ca.json b/packages/app-lib/.sqlx/query-cb20c8117eeec23ea1ebc2ef293caf425d722bd103cd6164c2b9d6abe5539aef.json similarity index 93% rename from packages/app-lib/.sqlx/query-5193f519f021b2e7013cdb67a6e1a31ae4bd7532d02f8b00b43d5645351941ca.json rename to packages/app-lib/.sqlx/query-cb20c8117eeec23ea1ebc2ef293caf425d722bd103cd6164c2b9d6abe5539aef.json index 5dc714e29..d87a4032c 100644 --- a/packages/app-lib/.sqlx/query-5193f519f021b2e7013cdb67a6e1a31ae4bd7532d02f8b00b43d5645351941ca.json +++ b/packages/app-lib/.sqlx/query-cb20c8117eeec23ea1ebc2ef293caf425d722bd103cd6164c2b9d6abe5539aef.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "\n SELECT\n max_concurrent_writes, max_concurrent_downloads,\n theme, default_page, collapsed_navigation, hide_nametag_skins_page, advanced_rendering, native_decorations,\n discord_rpc, developer_mode, telemetry, personalized_ads,\n onboarded,\n json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,\n mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,\n hook_pre_launch, hook_wrapper, hook_post_exit,\n custom_dir, prev_custom_dir, migrated, json(feature_flags) feature_flags, toggle_sidebar\n FROM settings\n ", + "query": "\n SELECT\n max_concurrent_writes, max_concurrent_downloads,\n theme, default_page, collapsed_navigation, hide_nametag_skins_page, advanced_rendering, native_decorations,\n discord_rpc, developer_mode, telemetry, personalized_ads,\n onboarded,\n json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,\n mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,\n hook_pre_launch, hook_wrapper, hook_post_exit,\n custom_dir, prev_custom_dir, migrated, json(feature_flags) feature_flags, toggle_sidebar,\n skipped_update\n FROM settings\n ", "describe": { "columns": [ { @@ -142,6 +142,11 @@ "name": "toggle_sidebar", "ordinal": 27, "type_info": "Integer" + }, + { + "name": "skipped_update", + "ordinal": 28, + "type_info": "Text" } ], "parameters": { @@ -175,8 +180,9 @@ true, false, null, - false + false, + true ] }, - "hash": "5193f519f021b2e7013cdb67a6e1a31ae4bd7532d02f8b00b43d5645351941ca" + "hash": "cb20c8117eeec23ea1ebc2ef293caf425d722bd103cd6164c2b9d6abe5539aef" } diff --git a/packages/app-lib/migrations/20250708222117_add-skipped-updates.sql b/packages/app-lib/migrations/20250708222117_add-skipped-updates.sql new file mode 100644 index 000000000..76003b85c --- /dev/null +++ b/packages/app-lib/migrations/20250708222117_add-skipped-updates.sql @@ -0,0 +1,2 @@ +ALTER TABLE settings +ADD COLUMN skipped_update TEXT NULL; diff --git a/packages/app-lib/src/state/settings.rs b/packages/app-lib/src/state/settings.rs index 2615e150e..44ac55674 100644 --- a/packages/app-lib/src/state/settings.rs +++ b/packages/app-lib/src/state/settings.rs @@ -38,6 +38,7 @@ pub struct Settings { pub developer_mode: bool, pub feature_flags: HashMap, + pub skipped_update: Option, } #[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, Hash, PartialEq)] @@ -63,7 +64,8 @@ impl Settings { json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars, mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start, hook_pre_launch, hook_wrapper, hook_post_exit, - custom_dir, prev_custom_dir, migrated, json(feature_flags) feature_flags, toggle_sidebar + custom_dir, prev_custom_dir, migrated, json(feature_flags) feature_flags, toggle_sidebar, + skipped_update FROM settings " ) @@ -117,6 +119,7 @@ impl Settings { .as_ref() .and_then(|x| serde_json::from_str(x).ok()) .unwrap_or_default(), + skipped_update: res.skipped_update }) } @@ -170,7 +173,8 @@ impl Settings { toggle_sidebar = $26, feature_flags = $27, - hide_nametag_skins_page = $28 + hide_nametag_skins_page = $28, + skipped_update = $29 ", max_concurrent_writes, max_concurrent_downloads, @@ -199,7 +203,8 @@ impl Settings { self.migrated, self.toggle_sidebar, feature_flags, - self.hide_nametag_skins_page + self.hide_nametag_skins_page, + self.skipped_update ) .execute(exec) .await?;