@7n/tauri-components 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/tauri-components",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "Shared LLM agent engine + Vue/Quasar UI for Tauri apps (chat, journal, trust-tier approval).",
6
6
  "license": "MIT",
@@ -36,6 +36,8 @@
36
36
  "peerDependencies": {
37
37
  "@tauri-apps/api": "^2.0.0",
38
38
  "@tauri-apps/plugin-http": "^2.0.0",
39
+ "@tauri-apps/plugin-process": "^2.0.0",
40
+ "@tauri-apps/plugin-updater": "^2.0.0",
39
41
  "@vue/test-utils": "^2.0.0",
40
42
  "quasar": "^2.0.0",
41
43
  "vue": "^3.0.0"
@@ -43,6 +45,8 @@
43
45
  "peerDependenciesMeta": {
44
46
  "@tauri-apps/api": { "optional": true },
45
47
  "@tauri-apps/plugin-http": { "optional": true },
48
+ "@tauri-apps/plugin-process": { "optional": true },
49
+ "@tauri-apps/plugin-updater": { "optional": true },
46
50
  "@vue/test-utils": { "optional": true },
47
51
  "quasar": { "optional": true }
48
52
  },
package/src/vue/index.js CHANGED
@@ -5,5 +5,6 @@
5
5
 
6
6
  export { useAgent } from './use-agent.js'
7
7
  export { useOmlx } from './use-omlx.js'
8
+ export { useUpdater } from './use-updater.js'
8
9
  export { createTauriJournalStore } from './journal-store-tauri.js'
9
10
  export { tauriTransport } from './transports.js'
@@ -0,0 +1,116 @@
1
+ import { onMounted, onUnmounted } from 'vue'
2
+ import { relaunch } from '@tauri-apps/plugin-process'
3
+ import { check } from '@tauri-apps/plugin-updater'
4
+ import { useQuasar } from 'quasar'
5
+
6
+ // Checks for an app update on mount and hourly thereafter, prompting via a
7
+ // Quasar dialog; after install, offers an immediate relaunch. Requires the
8
+ // host app's tauri.conf.json to configure plugins.updater (pubkey + endpoint)
9
+ // and capabilities/default.json to grant "updater:default" — without the
10
+ // capability, check() fails with a silent permission-denied that only surfaces
11
+ // via console.error (no dialog, no visible error).
12
+ //
13
+ // No-op in dev builds: tauri.conf.json's version is the CI-injected release
14
+ // version, not what's running locally, so the updater would always think dev
15
+ // code is stale.
16
+
17
+ const FIRST_CHECK_DELAY_MS = 3000
18
+ const CHECK_INTERVAL_MS = 60 * 60 * 1000
19
+
20
+ /**
21
+ * @returns {void}
22
+ */
23
+ export function useUpdater() {
24
+ if (import.meta.env.DEV) return
25
+
26
+ const $q = useQuasar()
27
+ let timer = null
28
+ // A dialog is showing or an install already ran — don't stack background checks.
29
+ let busy = false
30
+
31
+ /**
32
+ * Asks the configured update endpoint for a newer version and, if found,
33
+ * walks the user through the install flow.
34
+ * @returns {Promise<void>}
35
+ */
36
+ async function checkForUpdates() {
37
+ if (busy) return
38
+ try {
39
+ const update = await check()
40
+ if (!update) return
41
+
42
+ busy = true
43
+ $q.dialog({
44
+ title: 'Доступне оновлення',
45
+ message: `Версія ${update.version} готова. Встановити зараз?`,
46
+ cancel: { label: 'Пізніше', flat: true },
47
+ ok: { label: 'Встановити', color: 'primary' },
48
+ persistent: true,
49
+ })
50
+ .onOk(() => installAndRelaunch(update))
51
+ .onCancel(() => {
52
+ busy = false
53
+ })
54
+ }
55
+ catch (error) {
56
+ // No network, or the updater isn't configured/permitted — don't bother
57
+ // the user, but leave a trace for diagnosis.
58
+ console.error('[updater] check failed:', error)
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Downloads and installs the update with progress, then offers a relaunch.
64
+ * @param {import('@tauri-apps/plugin-updater').Update} update the update found by check()
65
+ * @returns {Promise<void>}
66
+ */
67
+ async function installAndRelaunch(update) {
68
+ let downloaded = 0
69
+ let total = 0
70
+ const dismiss = $q.notify({ group: false, timeout: 0, spinner: true, message: 'Завантаження оновлення…' })
71
+ try {
72
+ await update.downloadAndInstall(event => {
73
+ switch (event.event) {
74
+ case 'Started': {
75
+ total = event.data.contentLength ?? 0
76
+ break
77
+ }
78
+ case 'Progress': {
79
+ downloaded += event.data.chunkLength
80
+ if (total) dismiss({ message: `Завантаження… ${Math.round((downloaded / total) * 100)}%` })
81
+ break
82
+ }
83
+ case 'Finished': {
84
+ dismiss()
85
+ break
86
+ }
87
+ // No default
88
+ }
89
+ })
90
+ // busy stays true: the update is already on disk, a repeat check would
91
+ // only offer to install the same thing again.
92
+ $q.dialog({
93
+ title: 'Оновлення встановлено',
94
+ message: `Перезапустити зараз, щоб перейти на версію ${update.version}?`,
95
+ cancel: { label: 'Пізніше', flat: true },
96
+ ok: { label: 'Перезапустити', color: 'primary' },
97
+ persistent: true,
98
+ }).onOk(() => relaunch())
99
+ }
100
+ catch (error) {
101
+ dismiss()
102
+ busy = false
103
+ console.error('[updater] install failed:', error)
104
+ $q.notify({ message: `Помилка оновлення: ${error}`, color: 'negative', timeout: 5000 })
105
+ }
106
+ }
107
+
108
+ onMounted(() => {
109
+ setTimeout(checkForUpdates, FIRST_CHECK_DELAY_MS)
110
+ timer = setInterval(checkForUpdates, CHECK_INTERVAL_MS)
111
+ })
112
+
113
+ onUnmounted(() => {
114
+ if (timer) clearInterval(timer)
115
+ })
116
+ }