Update completion toasts (#3978)
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
"tsc:check": "vue-tsc --noEmit",
|
||||
"lint": "eslint . && prettier --check .",
|
||||
"fix": "eslint . --fix && prettier --write .",
|
||||
"intl:extract": "formatjs extract \"{,src/components,src/composables,src/helpers,src/pages,src/store}/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
|
||||
"intl:extract": "formatjs extract \"src/**/*.{vue,ts,tsx,js,jsx,mts,cts,mjs,cjs}\" --ignore \"**/*.d.ts\" --ignore node_modules --out-file src/locales/en-US/index.json --format crowdin --preserve-whitespace",
|
||||
"test": "vue-tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -71,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 { defineMessages, useVIntl } from '@vintl/vintl'
|
||||
|
||||
const themeStore = useTheming()
|
||||
|
||||
@@ -109,6 +110,18 @@ onUnmounted(() => {
|
||||
document.querySelector('body').removeEventListener('auxclick', handleAuxClick)
|
||||
})
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const messages = defineMessages({
|
||||
updateInstalledToastTitle: {
|
||||
id: 'app.update.complete-toast.title',
|
||||
defaultMessage: 'Version {version} was successfully installed!',
|
||||
},
|
||||
updateInstalledToastText: {
|
||||
id: 'app.update.complete-toast.text',
|
||||
defaultMessage: 'Click here to view the changelog.',
|
||||
},
|
||||
})
|
||||
|
||||
async function setupApp() {
|
||||
stateInitialized.value = true
|
||||
const {
|
||||
@@ -122,6 +135,7 @@ async function setupApp() {
|
||||
toggle_sidebar,
|
||||
developer_mode,
|
||||
feature_flags,
|
||||
pending_update_toast_for_version,
|
||||
} = await getSettings()
|
||||
|
||||
if (default_page === 'Library') {
|
||||
@@ -218,6 +232,22 @@ async function setupApp() {
|
||||
} catch (error) {
|
||||
console.warn('Failed to generate skin previews in app setup.', error)
|
||||
}
|
||||
|
||||
if (pending_update_toast_for_version !== null) {
|
||||
const settings = await getSettings()
|
||||
settings.pending_update_toast_for_version = null
|
||||
await setSettings(settings)
|
||||
|
||||
const version = await getVersion()
|
||||
if (pending_update_toast_for_version === version) {
|
||||
notifications.addNotification({
|
||||
type: 'success',
|
||||
title: formatMessage(messages.updateInstalledToastTitle, { version }),
|
||||
text: formatMessage(messages.updateInstalledToastText),
|
||||
clickAction: () => openUrl('https://modrinth.com/news/changelog?filter=app'),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const stateFailed = ref(false)
|
||||
|
||||
@@ -93,7 +93,6 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
header: {
|
||||
id: 'app.update.modal-header',
|
||||
|
||||
@@ -62,7 +62,9 @@ export type AppSettings = {
|
||||
|
||||
developer_mode: boolean
|
||||
feature_flags: Record<FeatureFlag, boolean>
|
||||
|
||||
skipped_update: string | null
|
||||
pending_update_toast_for_version: string | null
|
||||
}
|
||||
|
||||
// Get full settings object
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
"app.update.changelog": {
|
||||
"message": "Changelog"
|
||||
},
|
||||
"app.update.complete-toast.text": {
|
||||
"message": "Click here to view the changelog."
|
||||
},
|
||||
"app.update.complete-toast.title": {
|
||||
"message": "Version {version} was successfully installed!"
|
||||
},
|
||||
"app.update.copied-error": {
|
||||
"message": "Copied to clipboard!"
|
||||
},
|
||||
|
||||
@@ -262,8 +262,22 @@ fn main() {
|
||||
if matches!(event, tauri::RunEvent::Exit) {
|
||||
let update_data = app.state::<PendingUpdateData>().inner();
|
||||
if let Some((update, data)) = &*update_data.0.lock().unwrap() {
|
||||
fn set_changelog_toast(version: Option<String>) {
|
||||
let toast_result: theseus::Result<()> = tauri::async_runtime::block_on(async move {
|
||||
let mut settings = settings::get().await?;
|
||||
settings.pending_update_toast_for_version = version;
|
||||
settings::set(settings).await?;
|
||||
Ok(())
|
||||
});
|
||||
if let Err(e) = toast_result {
|
||||
tracing::warn!("Failed to set pending_update_toast: {e}")
|
||||
}
|
||||
}
|
||||
|
||||
set_changelog_toast(Some(update.version.clone()));
|
||||
if let Err(e) = update.install(data) {
|
||||
tracing::error!("Error while updating: {e}");
|
||||
set_changelog_toast(None);
|
||||
|
||||
DialogBuilder::message()
|
||||
.set_level(MessageLevel::Error)
|
||||
|
||||
@@ -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 skipped_update\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, pending_update_toast_for_version\n FROM settings\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -147,6 +147,11 @@
|
||||
"name": "skipped_update",
|
||||
"ordinal": 28,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "pending_update_toast_for_version",
|
||||
"ordinal": 29,
|
||||
"type_info": "Text"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
@@ -181,8 +186,9 @@
|
||||
false,
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "cb20c8117eeec23ea1ebc2ef293caf425d722bd103cd6164c2b9d6abe5539aef"
|
||||
"hash": "30fecc13c6ea4da1e99e35d307aa8e7c4e7f15ea99527e7974619ef8ed946abe"
|
||||
}
|
||||
@@ -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 skipped_update = $29\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\n skipped_update = $29,\n pending_update_toast_for_version = $30\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 29
|
||||
"Right": 30
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "6dd3b14f3736735ee9a734062c990d152b0ffb7abf87a729931dc6c54754be6d"
|
||||
"hash": "cd7c9f394e4f0ec8fd0043352f7382ac2570aaa096cd2ebb4de990f4d42cc5c9"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN pending_update_toast_for_version TEXT NULL;
|
||||
@@ -38,7 +38,9 @@ pub struct Settings {
|
||||
|
||||
pub developer_mode: bool,
|
||||
pub feature_flags: HashMap<FeatureFlag, bool>,
|
||||
|
||||
pub skipped_update: Option<String>,
|
||||
pub pending_update_toast_for_version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, Hash, PartialEq)]
|
||||
@@ -65,7 +67,7 @@ impl Settings {
|
||||
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,
|
||||
skipped_update
|
||||
skipped_update, pending_update_toast_for_version
|
||||
FROM settings
|
||||
"
|
||||
)
|
||||
@@ -120,6 +122,8 @@ impl Settings {
|
||||
.and_then(|x| serde_json::from_str(x).ok())
|
||||
.unwrap_or_default(),
|
||||
skipped_update: res.skipped_update,
|
||||
pending_update_toast_for_version: res
|
||||
.pending_update_toast_for_version,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -174,7 +178,9 @@ impl Settings {
|
||||
toggle_sidebar = $26,
|
||||
feature_flags = $27,
|
||||
hide_nametag_skins_page = $28,
|
||||
skipped_update = $29
|
||||
|
||||
skipped_update = $29,
|
||||
pending_update_toast_for_version = $30
|
||||
",
|
||||
max_concurrent_writes,
|
||||
max_concurrent_downloads,
|
||||
@@ -204,7 +210,8 @@ impl Settings {
|
||||
self.toggle_sidebar,
|
||||
feature_flags,
|
||||
self.hide_nametag_skins_page,
|
||||
self.skipped_update
|
||||
self.skipped_update,
|
||||
self.pending_update_toast_for_version,
|
||||
)
|
||||
.execute(exec)
|
||||
.await?;
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
@mouseenter="stopTimer(item)"
|
||||
@mouseleave="setNotificationTimer(item)"
|
||||
>
|
||||
<div class="vue-notification-template vue-notification" :class="{ [item.type]: true }">
|
||||
<div
|
||||
class="vue-notification-template vue-notification"
|
||||
:class="{ [item.type]: true }"
|
||||
@click="item.clickAction"
|
||||
>
|
||||
<div class="notification-title" v-html="item.title"></div>
|
||||
<div class="notification-content" v-html="item.text"></div>
|
||||
</div>
|
||||
@@ -31,11 +35,14 @@ const notifications = ref([])
|
||||
|
||||
defineExpose({
|
||||
addNotification: (notification) => {
|
||||
notification.clickAction = notification.clickAction ?? (() => {})
|
||||
|
||||
const existingNotif = notifications.value.find(
|
||||
(x) =>
|
||||
x.text === notification.text &&
|
||||
x.title === notification.title &&
|
||||
x.type === notification.type,
|
||||
x.type === notification.type &&
|
||||
x.clickAction === notification.clickAction,
|
||||
)
|
||||
if (existingNotif) {
|
||||
setNotificationTimer(existingNotif)
|
||||
|
||||
Reference in New Issue
Block a user