diff --git a/CHANGELOG.md b/CHANGELOG.md index ada443f..eb0ad2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,43 @@ All notable changes to znote are written down here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.2.0] - 2026-10-18 + +### Added + +- OpenRouter settings let you choose which providers answer: privacy first + (only providers that keep nothing) or cheapest first. +- A 60 second trailer of the demo (`demo.trailer.mp4`, + `scripts/record.sh --trailer`). The demo and the trailer open and close on + a title card with the app icon. + +### Changed + +- The OpenRouter model list only offers models that can look at pictures, so + Design mode works with each of them. DeepSeek V4 Pro and GLM 5.3 are gone. +- Shorter screens: the descriptions under the start screen, the chat + overview, the advanced settings, the connect screen and the Assistant and + Privacy settings are gone. +- The Pages and files tab of the chat overview has Undo and Undo all changes + as icons, a "Remove all from chat" button above the list and a remove button + next to each page and file. +- In the Privacy settings a note that your organisation requires hiding sits + with the switches it locks, and the glossary has its own section. +- A file that cannot be attached says so in a few words: its type is not + supported, or it could not be read. +- zsuite: `zsuite-agent`, `tauri-plugin-zsuite-assistant` and + `@zsuite/assistant` 0.2.0. + +### Fixed + +- One file that cannot be attached no longer keeps the other files you picked + with it out of the chat, and leaves no copy behind that broke the Pages and + files tab. +- Two attached files with the same name no longer break the list above the + message box. +- The assistant panel no longer flashes a red "no knowledge file" warning + while the app starts. + ## [1.1.0] - 2026-10-17 ### Added @@ -223,5 +260,6 @@ All notable changes to znote are written down here. The format follows - The first version: a Tauri and SvelteKit window with the basic interface and a Windows build in CI. +[1.2.0]: https://github.com/ZAL-Analytics/znote/releases/tag/v1.2.0 [1.1.0]: https://github.com/ZAL-Analytics/znote/releases/tag/v1.1.0 [1.0.0]: https://github.com/ZAL-Analytics/znote/releases/tag/v1.0.0 diff --git a/package.json b/package.json index 0a9c567..4b12e62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "znote", - "version": "1.1.0", + "version": "1.2.0", "description": "", "type": "module", "scripts": { diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index b43420b..d8f5693 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -1,5 +1,5 @@ pkgname=znote -pkgver=1.1.0 +pkgver=1.2.0 pkgrel=1 pkgdesc="A lightweight desktop editor for Typst with live preview" arch=('x86_64') diff --git a/packaging/linux/com.zalanalytics.znote.metainfo.xml b/packaging/linux/com.zalanalytics.znote.metainfo.xml index dcc07b6..4ca92ef 100644 --- a/packaging/linux/com.zalanalytics.znote.metainfo.xml +++ b/packaging/linux/com.zalanalytics.znote.metainfo.xml @@ -22,6 +22,7 @@ znote + diff --git a/packaging/repo/demo.gif b/packaging/repo/demo.gif index 71db0ed..fda6d3e 100644 Binary files a/packaging/repo/demo.gif and b/packaging/repo/demo.gif differ diff --git a/packaging/repo/demo.mp4 b/packaging/repo/demo.mp4 index f898582..31f131f 100644 Binary files a/packaging/repo/demo.mp4 and b/packaging/repo/demo.mp4 differ diff --git a/packaging/repo/demo.trailer.mp4 b/packaging/repo/demo.trailer.mp4 new file mode 100644 index 0000000..b720973 Binary files /dev/null and b/packaging/repo/demo.trailer.mp4 differ diff --git a/packaging/repo/demo/01_Welcome.png b/packaging/repo/demo/01_Welcome.png index 948285b..3a46bb7 100644 Binary files a/packaging/repo/demo/01_Welcome.png and b/packaging/repo/demo/01_Welcome.png differ diff --git a/packaging/repo/demo/02_Password.png b/packaging/repo/demo/02_Password.png index 169ad6c..d8e02cc 100644 Binary files a/packaging/repo/demo/02_Password.png and b/packaging/repo/demo/02_Password.png differ diff --git a/packaging/repo/demo/03_FirstStart_Layout.png b/packaging/repo/demo/03_FirstStart_Layout.png index c168a3d..ede4730 100644 Binary files a/packaging/repo/demo/03_FirstStart_Layout.png and b/packaging/repo/demo/03_FirstStart_Layout.png differ diff --git a/packaging/repo/demo/04_FirstStart_Privacy.png b/packaging/repo/demo/04_FirstStart_Privacy.png index db13c8c..6a6ce79 100644 Binary files a/packaging/repo/demo/04_FirstStart_Privacy.png and b/packaging/repo/demo/04_FirstStart_Privacy.png differ diff --git a/packaging/repo/demo/05_FirstStart_Downloads.png b/packaging/repo/demo/05_FirstStart_Downloads.png index 6f46956..0160a74 100644 Binary files a/packaging/repo/demo/05_FirstStart_Downloads.png and b/packaging/repo/demo/05_FirstStart_Downloads.png differ diff --git a/packaging/repo/demo/06_Edit_ProjectBrief.png b/packaging/repo/demo/06_Edit_ProjectBrief.png index f3f16c8..99fe843 100644 Binary files a/packaging/repo/demo/06_Edit_ProjectBrief.png and b/packaging/repo/demo/06_Edit_ProjectBrief.png differ diff --git a/packaging/repo/demo/07_Edit_Typing.png b/packaging/repo/demo/07_Edit_Typing.png index aa12fb5..ecdfdfa 100644 Binary files a/packaging/repo/demo/07_Edit_Typing.png and b/packaging/repo/demo/07_Edit_Typing.png differ diff --git a/packaging/repo/demo/08_Layout_Assistant.png b/packaging/repo/demo/08_Layout_Assistant.png index 40dd835..fcbbc81 100644 Binary files a/packaging/repo/demo/08_Layout_Assistant.png and b/packaging/repo/demo/08_Layout_Assistant.png differ diff --git a/packaging/repo/demo/09_Layout_Redact.png b/packaging/repo/demo/09_Layout_Redact.png index f932072..7834b54 100644 Binary files a/packaging/repo/demo/09_Layout_Redact.png and b/packaging/repo/demo/09_Layout_Redact.png differ diff --git a/packaging/repo/demo/10_Marketplace.png b/packaging/repo/demo/10_Marketplace.png index ec66ae3..d44431d 100644 Binary files a/packaging/repo/demo/10_Marketplace.png and b/packaging/repo/demo/10_Marketplace.png differ diff --git a/packaging/repo/demo/11_Marketplace_Installed.png b/packaging/repo/demo/11_Marketplace_Installed.png index d769f0b..d52af0b 100644 Binary files a/packaging/repo/demo/11_Marketplace_Installed.png and b/packaging/repo/demo/11_Marketplace_Installed.png differ diff --git a/packaging/repo/demo/12_Template_ZalNote.png b/packaging/repo/demo/12_Template_ZalNote.png index e85444c..6b4a7be 100644 Binary files a/packaging/repo/demo/12_Template_ZalNote.png and b/packaging/repo/demo/12_Template_ZalNote.png differ diff --git a/packaging/repo/demo/13_Assistant_Output.png b/packaging/repo/demo/13_Assistant_Output.png index a216524..db22327 100644 Binary files a/packaging/repo/demo/13_Assistant_Output.png and b/packaging/repo/demo/13_Assistant_Output.png differ diff --git a/packaging/repo/demo/14_Assistant_NewPage.png b/packaging/repo/demo/14_Assistant_NewPage.png index 7c48fcc..c05ca27 100644 Binary files a/packaging/repo/demo/14_Assistant_NewPage.png and b/packaging/repo/demo/14_Assistant_NewPage.png differ diff --git a/packaging/repo/demo/15_Assistant_Edit.png b/packaging/repo/demo/15_Assistant_Edit.png index 839e371..9669063 100644 Binary files a/packaging/repo/demo/15_Assistant_Edit.png and b/packaging/repo/demo/15_Assistant_Edit.png differ diff --git a/packaging/repo/demo/16_Assistant_Review.png b/packaging/repo/demo/16_Assistant_Review.png index 7fbe1d8..4c57496 100644 Binary files a/packaging/repo/demo/16_Assistant_Review.png and b/packaging/repo/demo/16_Assistant_Review.png differ diff --git a/packaging/repo/demo/17_Assistant_AnalysePdf.png b/packaging/repo/demo/17_Assistant_AnalysePdf.png index 377d47e..2c4f6a9 100644 Binary files a/packaging/repo/demo/17_Assistant_AnalysePdf.png and b/packaging/repo/demo/17_Assistant_AnalysePdf.png differ diff --git a/packaging/repo/demo/18_Filter_ChatFiles.png b/packaging/repo/demo/18_Filter_ChatFiles.png index cf5eb4a..89e268c 100644 Binary files a/packaging/repo/demo/18_Filter_ChatFiles.png and b/packaging/repo/demo/18_Filter_ChatFiles.png differ diff --git a/packaging/repo/demo/19_Filter_Strict.png b/packaging/repo/demo/19_Filter_Strict.png index c00eb38..4cc9253 100644 Binary files a/packaging/repo/demo/19_Filter_Strict.png and b/packaging/repo/demo/19_Filter_Strict.png differ diff --git a/packaging/repo/demo/20_Filter_Light.png b/packaging/repo/demo/20_Filter_Light.png index f8858d1..6fd7978 100644 Binary files a/packaging/repo/demo/20_Filter_Light.png and b/packaging/repo/demo/20_Filter_Light.png differ diff --git a/packaging/repo/demo/21_Filter_Pdf.png b/packaging/repo/demo/21_Filter_Pdf.png index 4bd93c8..e848edc 100644 Binary files a/packaging/repo/demo/21_Filter_Pdf.png and b/packaging/repo/demo/21_Filter_Pdf.png differ diff --git a/packaging/repo/demo/22_Filter_Message.png b/packaging/repo/demo/22_Filter_Message.png index a99dc7a..ad17c25 100644 Binary files a/packaging/repo/demo/22_Filter_Message.png and b/packaging/repo/demo/22_Filter_Message.png differ diff --git a/packaging/repo/demo/23_Language_German.png b/packaging/repo/demo/23_Language_German.png index 3f39168..d0cf737 100644 Binary files a/packaging/repo/demo/23_Language_German.png and b/packaging/repo/demo/23_Language_German.png differ diff --git a/packaging/repo/demo/24_Language_Arabic.png b/packaging/repo/demo/24_Language_Arabic.png index 5f53da5..2f30847 100644 Binary files a/packaging/repo/demo/24_Language_Arabic.png and b/packaging/repo/demo/24_Language_Arabic.png differ diff --git a/packaging/repo/demo/25_Dark.png b/packaging/repo/demo/25_Dark.png index 262f07d..248e4a2 100644 Binary files a/packaging/repo/demo/25_Dark.png and b/packaging/repo/demo/25_Dark.png differ diff --git a/packaging/repo/demo/26_Export.png b/packaging/repo/demo/26_Export.png index 7708680..5f66648 100644 Binary files a/packaging/repo/demo/26_Export.png and b/packaging/repo/demo/26_Export.png differ diff --git a/scripts/record.sh b/scripts/record.sh index 6748a42..5d2634b 100755 --- a/scripts/record.sh +++ b/scripts/record.sh @@ -1,18 +1,21 @@ #!/usr/bin/env bash -# Records the demo of the real app: a clip, the stills and a gif of the stills, -# all under packaging/repo. +# Records the demo of the real app: a clip, the stills, a gif of the stills and +# a 60 second trailer, all under packaging/repo (demo.mp4, demo.gif, +# demo.trailer.mp4). # # scripts/record.sh --sign-in # once: sign Claude Code in for the demo app (in the terminal) -# scripts/record.sh --all # record, then the gif and the clip +# scripts/record.sh --all # record, then the gif, the clip and the trailer # scripts/record.sh --record # run the app and record the clip and stills # scripts/record.sh --gif # the gif, from the last stills # scripts/record.sh --video [out] # the clip, from the last recording +# scripts/record.sh --trailer # the 60 second trailer, from the last recording # # SKIP_BUILD=1 ... reuse the current src-tauri/dist/ # DEMO_ASSISTANT=0 ... leave out the parts that need Claude Code # DEMO_HOLD=2.4 ... a slower gif # DEMO_SPEED=1.1 ... speed of the clip as a whole # DEMO_SKIP_SPEED=10 ... speed of the waits (downloads, the assistant at work) +# DEMO_TRAILER=60 ... length of the trailer in seconds # # The demo app runs under its own identifier, com.zalanalytics.znote.demo, so # it starts from a first run without touching a real install. Its Claude Code @@ -140,6 +143,7 @@ cut_filter() { local cuts="$1" skip="$2" speed="$3" awk -v skip="$skip" -v speed="$speed" ' $1 == "trim" { at = $2; next } + $1 == "scene" { next } { if ($1 > at) parts[n++] = sprintf("%s %s 1", at, $1) parts[n++] = sprintf("%s %s %s", $1, $2, skip) @@ -160,6 +164,46 @@ cut_filter() { }' "$cuts" } +# The filter that plays only the scenes the demo marked for the trailer, with the +# waits inside them sped up, as fast as needed to last at most `length` seconds. +trailer_filter() { + local cuts="$1" skip="$2" length="$3" + awk -v skip="$skip" -v limit="$length" ' + BEGIN { n = 0; s = 0; k = 0 } + $1 == "trim" { next } + $1 == "scene" { from[s] = $2; to[s++] = $3; next } + { a[k] = $1; b[k++] = $2 } + function piece(start, end, speed) { + if (end <= start) return + parts[n] = start " " end " " speed + total += (end - start) / speed + n++ + } + END { + for (i = 0; i < s; i++) { + at = from[i] + for (j = 0; j < k; j++) { + if (b[j] <= at || a[j] >= to[i]) continue + piece(at, a[j] > at ? a[j] : at, 1) + piece(a[j] > at ? a[j] : at, b[j] < to[i] ? b[j] : to[i], skip) + at = b[j] < to[i] ? b[j] : to[i] + } + piece(at, to[i], 1) + } + if (n == 0) exit 1 + factor = total > limit ? total / limit : 1 + printf "[0:v]split=%d", n + for (i = 0; i < n; i++) printf "[s%d]", i + printf ";" + for (i = 0; i < n; i++) { + split(parts[i], p, " ") + printf "[s%d]trim=start=%s:end=%s,setpts=(PTS-STARTPTS)/%s/%s[p%d];", i, p[1], p[2], p[3], factor, i + } + for (i = 0; i < n; i++) printf "[p%d]", i + printf "concat=n=%d:v=1:a=0[out]", n + }' "$cuts" +} + video() { local out="${1:-$REPO/demo.mp4}" need ffmpeg "install it from your package manager" @@ -177,10 +221,21 @@ video() { local fit="scale=1920:1080:force_original_aspect_ratio=decrease:flags=lanczos" fit="$fit,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=$backdrop" + local cut pad="" + if [ "${2:-}" = trailer ]; then + out="$REPO/demo.trailer.mp4" + grep -q '^scene ' "$cuts" || { echo "$cuts has no scenes for the trailer, record again" >&2; exit 1; } + cut="$(trailer_filter "$cuts" "${DEMO_SKIP_SPEED:-10}" "${DEMO_TRAILER:-60}")" + # a short cut holds its last frame, the closing card, to the full length + pad=",tpad=stop_mode=clone:stop_duration=${DEMO_TRAILER:-60},trim=duration=${DEMO_TRAILER:-60}" + else + cut="$(cut_filter "$cuts" "${DEMO_SKIP_SPEED:-10}" "${DEMO_SPEED:-1.1}")" + fi + echo "==> encoding $out" mkdir -p "$(dirname "$out")" ffmpeg -hide_banner -loglevel error -y -i "$webm" \ - -filter_complex "$(cut_filter "$cuts" "${DEMO_SKIP_SPEED:-10}" "${DEMO_SPEED:-1.1}");[out]fps=30,$fit,format=yuv420p[v]" \ + -filter_complex "$cut;[out]fps=30$pad,$fit,format=yuv420p[v]" \ -map "[v]" -an -c:v libx264 -preset slow -crf 20 -profile:v high -level:v 4.0 -movflags +faststart \ "$out" @@ -191,16 +246,17 @@ video() { (($#)) || { usage; exit 1; } -do_sign_in=0 do_record=0 do_gif=0 do_video=0 +do_sign_in=0 do_record=0 do_gif=0 do_video=0 do_trailer=0 video_out="" while (($#)); do case "$1" in - --all) do_record=1 do_gif=1 do_video=1 ;; + --all) do_record=1 do_gif=1 do_video=1 do_trailer=1 ;; --sign-in) do_sign_in=1 ;; --record) do_record=1 ;; --gif) do_gif=1 ;; --video) do_video=1 ;; + --trailer) do_trailer=1 ;; -h | --help) usage; exit 0 ;; -*) echo "unknown flag $1" >&2; usage >&2; exit 1 ;; *) video_out="$1" ;; @@ -212,4 +268,5 @@ done ((do_record)) && record ((do_gif)) && gif ((do_video)) && video "$video_out" +((do_trailer)) && video "" trailer exit 0 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index a8af42b..39c9629 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6205,7 +6205,7 @@ dependencies = [ [[package]] name = "tauri-plugin-zsuite-assistant" -version = "0.1.0" +version = "0.2.0" dependencies = [ "serde_json", "tauri", @@ -8556,7 +8556,7 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" [[package]] name = "znote" -version = "1.1.0" +version = "1.2.0" dependencies = [ "notify", "rusqlite", @@ -8595,7 +8595,7 @@ dependencies = [ [[package]] name = "zsuite-agent" -version = "0.1.0" +version = "0.2.0" dependencies = [ "keyring", "lopdf", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1fdc812..55d8ff1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "znote" -version = "1.1.0" +version = "1.2.0" description = "A lightweight desktop editor for Typst with live preview, built with Tauri" license = "Apache-2.0" repository = "https://github.com/ZAL-Analytics/znote" @@ -42,8 +42,8 @@ zsuite-veil = { version = "0.1.0", path = "../vendor/zsuite/crates/zsuite-veil", zsuite-finder = { version = "0.1.0", path = "../vendor/zsuite/crates/zsuite-finder" } zsuite-typst = { version = "0.1.0", path = "../vendor/zsuite/crates/zsuite-typst" } zsuite-sealed = { version = "0.1.0", path = "../vendor/zsuite/crates/zsuite-sealed", features = ["typst"] } -zsuite-agent = { version = "0.1.0", path = "../vendor/zsuite/crates/zsuite-agent" } -tauri-plugin-zsuite-assistant = { version = "0.1.0", path = "../vendor/zsuite/crates/tauri-plugin-zsuite-assistant" } +zsuite-agent = { version = "0.2.0", path = "../vendor/zsuite/crates/zsuite-agent" } +tauri-plugin-zsuite-assistant = { version = "0.2.0", path = "../vendor/zsuite/crates/tauri-plugin-zsuite-assistant" } [target.'cfg(windows)'.dependencies] rusqlite = { version = "0.40", features = ["bundled-sqlcipher-vendored-openssl"] } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e60cec1..dc22c95 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "znote", - "version": "1.1.0", + "version": "1.2.0", "identifier": "com.zalanalytics.znote", "build": { "beforeDevCommand": "pnpm dev --port 1420 --strictPort", diff --git a/src/lib/assets/locale/ar/backend.json b/src/lib/assets/locale/ar/backend.json index d75e9cb..d7676a9 100644 --- a/src/lib/assets/locale/ar/backend.json +++ b/src/lib/assets/locale/ar/backend.json @@ -44,6 +44,8 @@ "noAttachments": "لا يمكن لهذه الدردشة الاحتفاظ بملفات مرفقة.", "notAttached": "تعذر إرفاق ”{name}“: {error}", "tooLarge": "”{name}“ كبير جداً بحيث لا يمكن إرفاقه. الحد الأقصى هو 32 ميجابايت.", + "notSupported": "«{name}»: نوع الملف هذا غير مدعوم.", + "notRead": "تعذّرت قراءة «{name}».", "notSaved": "تعذر حفظ هذه الدردشة: {error}", "notSavedOther": "تعذر حفظ الدردشة: {error}", "tooLong": "لقد أصبحت طويلة جداً. ابدأ دردشة جديدة.", diff --git a/src/lib/assets/locale/ar/workspace.json b/src/lib/assets/locale/ar/workspace.json index 9a7d995..51a80a8 100644 --- a/src/lib/assets/locale/ar/workspace.json +++ b/src/lib/assets/locale/ar/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "مرحباً بك في znote", "title": "ملفات znote الخاصة بك", - "text": "تُحفظ كل ملاحظاتك في ملف واحد يمكنك نسخه إلى حاسوب آخر.", "new": "ملف znote جديد…", "open": "فتح ملف znote…", "bringIn": "جلب الملاحظات التي لدي بالفعل…", diff --git a/src/lib/assets/locale/da/backend.json b/src/lib/assets/locale/da/backend.json index 6d0bd44..78a9da1 100644 --- a/src/lib/assets/locale/da/backend.json +++ b/src/lib/assets/locale/da/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Denne chat kan ikke indeholde vedhæftede filer.", "notAttached": "“{name}” kunne ikke vedhæftes: {error}", "tooLarge": "“{name}” er for stor til at blive vedhæftet. Grænsen er 32 MB.", + "notSupported": "“{name}”: denne filtype understøttes ikke.", + "notRead": "“{name}” kunne ikke læses.", "notSaved": "Denne chat kunne ikke gemmes: {error}", "notSavedOther": "Chatten kunne ikke gemmes: {error}", "tooLong": "den er blevet for lang. Start en ny chat.", diff --git a/src/lib/assets/locale/da/workspace.json b/src/lib/assets/locale/da/workspace.json index d750cc1..1431374 100644 --- a/src/lib/assets/locale/da/workspace.json +++ b/src/lib/assets/locale/da/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Velkommen til znote", "title": "Dine znote-filer", - "text": "Alle dine noter gemmes i én fil, som du kan kopiere til en anden computer.", "new": "Ny znote-fil…", "open": "Åbn en znote-fil…", "bringIn": "Hent de noter, jeg allerede har…", diff --git a/src/lib/assets/locale/de/backend.json b/src/lib/assets/locale/de/backend.json index 680e264..2be4809 100644 --- a/src/lib/assets/locale/de/backend.json +++ b/src/lib/assets/locale/de/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Dieser Chat kann keine angehängten Dateien enthalten.", "notAttached": "„{name}“ konnte nicht angehängt werden: {error}", "tooLarge": "„{name}“ ist zu groß zum Anhängen. Das Limit beträgt 32 MB.", + "notSupported": "„{name}“: Dieser Dateityp wird nicht unterstützt.", + "notRead": "„{name}“ konnte nicht gelesen werden.", "notSaved": "Dieser Chat konnte nicht gespeichert werden: {error}", "notSavedOther": "Der Chat konnte nicht gespeichert werden: {error}", "tooLong": "Er ist zu lang geworden. Starten Sie einen neuen Chat.", diff --git a/src/lib/assets/locale/de/workspace.json b/src/lib/assets/locale/de/workspace.json index e1bf213..2293752 100644 --- a/src/lib/assets/locale/de/workspace.json +++ b/src/lib/assets/locale/de/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Willkommen bei znote", "title": "Ihre znote-Dateien", - "text": "Alle Ihre Notizen werden in einer Datei gespeichert, die Sie auf einen anderen Computer kopieren können.", "new": "Neue znote-Datei…", "open": "znote-Datei öffnen…", "bringIn": "Vorhandene Notizen importieren…", diff --git a/src/lib/assets/locale/el/backend.json b/src/lib/assets/locale/el/backend.json index aa64508..d4a73ae 100644 --- a/src/lib/assets/locale/el/backend.json +++ b/src/lib/assets/locale/el/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Αυτή η συνομιλία δεν μπορεί να περιέχει συνημμένα αρχεία.", "notAttached": "Δεν ήταν δυνατή η επισύναψη του “{name}”: {error}", "tooLarge": "Το “{name}” είναι πολύ μεγάλο για επισύναψη. Το όριο είναι 32 MB.", + "notSupported": "«{name}»: αυτός ο τύπος αρχείου δεν υποστηρίζεται.", + "notRead": "Δεν ήταν δυνατή η ανάγνωση του «{name}».", "notSaved": "Δεν ήταν δυνατή η αποθήκευση αυτής της συνομιλίας: {error}", "notSavedOther": "Δεν ήταν δυνατή η αποθήκευση της συνομιλίας: {error}", "tooLong": "Έχει γίνει πολύ μεγάλη. Ξεκινήστε μια νέα συνομιλία.", diff --git a/src/lib/assets/locale/el/workspace.json b/src/lib/assets/locale/el/workspace.json index 69d71c8..ae66e10 100644 --- a/src/lib/assets/locale/el/workspace.json +++ b/src/lib/assets/locale/el/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Καλώς ήρθατε στο znote", "title": "Τα αρχεία znote σας", - "text": "Όλες οι σημειώσεις σας αποθηκεύονται σε ένα αρχείο που μπορείτε να αντιγράψετε σε άλλον υπολογιστή.", "new": "Νέο αρχείο znote…", "open": "Άνοιγμα αρχείου znote…", "bringIn": "Εισαγωγή των σημειώσεων που έχω ήδη…", diff --git a/src/lib/assets/locale/en/backend.json b/src/lib/assets/locale/en/backend.json index d81b027..06478ad 100644 --- a/src/lib/assets/locale/en/backend.json +++ b/src/lib/assets/locale/en/backend.json @@ -44,6 +44,8 @@ "noAttachments": "This chat cannot hold attached files.", "notAttached": "“{name}” could not be attached: {error}", "tooLarge": "“{name}” is too large to attach. The limit is 32 MB.", + "notSupported": "“{name}”: this file type is not supported.", + "notRead": "“{name}” could not be read.", "notSaved": "This chat could not be saved: {error}", "notSavedOther": "The chat could not be saved: {error}", "tooLong": "it has grown too long. Start a new chat.", diff --git a/src/lib/assets/locale/en/workspace.json b/src/lib/assets/locale/en/workspace.json index 94337c0..b8289fa 100644 --- a/src/lib/assets/locale/en/workspace.json +++ b/src/lib/assets/locale/en/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Welcome to znote", "title": "Your znote files", - "text": "All your notes in one file you can copy.", "new": "New znote file…", "open": "Open znote file…", "bringIn": "Import existing notes…", diff --git a/src/lib/assets/locale/es/backend.json b/src/lib/assets/locale/es/backend.json index e45396e..f8ce951 100644 --- a/src/lib/assets/locale/es/backend.json +++ b/src/lib/assets/locale/es/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Este chat no puede contener archivos adjuntos.", "notAttached": "No se pudo adjuntar “{name}”: {error}", "tooLarge": "“{name}” es demasiado grande para adjuntarlo. El límite es de 32 MB.", + "notSupported": "«{name}»: este tipo de archivo no es compatible.", + "notRead": "No se pudo leer «{name}».", "notSaved": "No se pudo guardar este chat: {error}", "notSavedOther": "No se pudo guardar el chat: {error}", "tooLong": "Se ha vuelto demasiado largo. Inicie un chat nuevo.", diff --git a/src/lib/assets/locale/es/workspace.json b/src/lib/assets/locale/es/workspace.json index 599e6ac..30477d3 100644 --- a/src/lib/assets/locale/es/workspace.json +++ b/src/lib/assets/locale/es/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Bienvenido a znote", "title": "Tus archivos de znote", - "text": "Todas tus notas se guardan en un archivo que puedes copiar a otro equipo.", "new": "Nuevo archivo de znote…", "open": "Abrir un archivo de znote…", "bringIn": "Importar las notas que ya tengo…", diff --git a/src/lib/assets/locale/fa/backend.json b/src/lib/assets/locale/fa/backend.json index 7ae32f4..565efa3 100644 --- a/src/lib/assets/locale/fa/backend.json +++ b/src/lib/assets/locale/fa/backend.json @@ -44,6 +44,8 @@ "noAttachments": "این گپ (Chat) نمی‌تواند فایل‌های پیوست داشته باشد.", "notAttached": "«{name}» پیوست نشد: {error}", "tooLarge": "«{name}» برای پیوست کردن بیش از حد بزرگ است. محدودیت ۳۲ مگابایت است.", + "notSupported": "«{name}»: این نوع فایل پشتیبانی نمی‌شود.", + "notRead": "«{name}» خوانده نشد.", "notSaved": "این گپ ذخیره نشد: {error}", "notSavedOther": "گپ ذخیره نشد: {error}", "tooLong": "بیش از حد طولانی شده است. یک گپ جدید شروع کنید.", diff --git a/src/lib/assets/locale/fa/workspace.json b/src/lib/assets/locale/fa/workspace.json index e570968..e299985 100644 --- a/src/lib/assets/locale/fa/workspace.json +++ b/src/lib/assets/locale/fa/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "خوش‌آمدید به znote", "title": "فایل‌های znote شما", - "text": "همهٔ یادداشت‌های شما در یک فایل ذخیره می‌شوند که می‌توانید آن را به رایانه دیگری کپی کنید.", "new": "فایل znote جدید…", "open": "باز کردن یک فایل znote…", "bringIn": "وارد کردن یادداشت‌هایی که از قبل دارم…", diff --git a/src/lib/assets/locale/fr/backend.json b/src/lib/assets/locale/fr/backend.json index ddd082d..465aeaf 100644 --- a/src/lib/assets/locale/fr/backend.json +++ b/src/lib/assets/locale/fr/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Ce chat ne peut pas contenir de fichiers joints.", "notAttached": "« {name} » n’a pas pu être joint : {error}", "tooLarge": "« {name} » est trop volumineux pour être joint. La limite est de 32 Mo.", + "notSupported": "« {name} » : ce type de fichier n’est pas pris en charge.", + "notRead": "« {name} » n’a pas pu être lu.", "notSaved": "Ce chat n’a pas pu être enregistré : {error}", "notSavedOther": "Le chat n’a pas pu être enregistré : {error}", "tooLong": "il est devenu trop long. Démarrez un nouveau chat.", diff --git a/src/lib/assets/locale/fr/workspace.json b/src/lib/assets/locale/fr/workspace.json index bc8b4ab..2de5d0f 100644 --- a/src/lib/assets/locale/fr/workspace.json +++ b/src/lib/assets/locale/fr/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Bienvenue dans znote", "title": "Vos fichiers znote", - "text": "Toutes vos notes sont enregistrées dans un seul fichier que vous pouvez copier sur un autre ordinateur.", "new": "Nouveau fichier znote…", "open": "Ouvrir un fichier znote…", "bringIn": "Importer mes notes existantes…", diff --git a/src/lib/assets/locale/he/backend.json b/src/lib/assets/locale/he/backend.json index 99197fa..4c6993b 100644 --- a/src/lib/assets/locale/he/backend.json +++ b/src/lib/assets/locale/he/backend.json @@ -44,6 +44,8 @@ "noAttachments": "צ'אט זה אינו יכול להכיל קבצים מצורפים.", "notAttached": "לא ניתן היה לצרף את “{name}”: {error}", "tooLarge": "“{name}” גדול מדי מכדי לצרף. המגבלה היא 32 MB.", + "notSupported": "„{name}”: סוג קובץ זה אינו נתמך.", + "notRead": "לא ניתן היה לקרוא את „{name}”.", "notSaved": "לא ניתן היה לשמור צ'אט זה: {error}", "notSavedOther": "לא ניתן היה לשמור את הצ'אט: {error}", "tooLong": "הוא הפך לארוך מדי. התחילו צ'אט חדש.", diff --git a/src/lib/assets/locale/he/workspace.json b/src/lib/assets/locale/he/workspace.json index 9fa2ce4..9f8fb04 100644 --- a/src/lib/assets/locale/he/workspace.json +++ b/src/lib/assets/locale/he/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "ברוכים הבאים ל-znote", "title": "קבצי ה-znote שלך", - "text": "כל ההערות שלך נשמרות בקובץ אחד שאפשר להעתיק למחשב אחר.", "new": "קובץ znote חדש…", "open": "פתיחת קובץ znote…", "bringIn": "ייבוא הערות קיימות…", diff --git a/src/lib/assets/locale/it/backend.json b/src/lib/assets/locale/it/backend.json index a8e5084..37c4c52 100644 --- a/src/lib/assets/locale/it/backend.json +++ b/src/lib/assets/locale/it/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Questa chat non può contenere file allegati.", "notAttached": "Non è stato possibile allegare “{name}”: {error}", "tooLarge": "“{name}” è troppo grande per essere allegato. Il limite è 32 MB.", + "notSupported": "«{name}»: questo tipo di file non è supportato.", + "notRead": "Impossibile leggere «{name}».", "notSaved": "Non è stato possibile salvare questa chat: {error}", "notSavedOther": "Non è stato possibile salvare la chat: {error}", "tooLong": "è diventata troppo lunga. Avvia una nuova chat.", diff --git a/src/lib/assets/locale/it/workspace.json b/src/lib/assets/locale/it/workspace.json index c5ced42..341e953 100644 --- a/src/lib/assets/locale/it/workspace.json +++ b/src/lib/assets/locale/it/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Benvenuto in znote", "title": "I tuoi file znote", - "text": "Tutte le tue note sono salvate in un unico file che puoi copiare su un altro computer.", "new": "Nuovo file znote…", "open": "Apri un file znote…", "bringIn": "Importa le note che ho già…", diff --git a/src/lib/assets/locale/ja/backend.json b/src/lib/assets/locale/ja/backend.json index ddb3553..eefbff6 100644 --- a/src/lib/assets/locale/ja/backend.json +++ b/src/lib/assets/locale/ja/backend.json @@ -44,6 +44,8 @@ "noAttachments": "このチャットにはファイルを添付できません。", "notAttached": "「{name}」を添付できませんでした: {error}", "tooLarge": "「{name}」は大きすぎて添付できません。上限は 32 MB です。", + "notSupported": "「{name}」: この種類のファイルには対応していません。", + "notRead": "「{name}」を読み込めませんでした。", "notSaved": "このチャットを保存できませんでした: {error}", "notSavedOther": "チャットを保存できませんでした: {error}", "tooLong": "長くなりすぎました。新しいチャットを開始してください。", diff --git a/src/lib/assets/locale/ja/workspace.json b/src/lib/assets/locale/ja/workspace.json index 60220e7..b7add57 100644 --- a/src/lib/assets/locale/ja/workspace.json +++ b/src/lib/assets/locale/ja/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "znote へようこそ", "title": "あなたの znote ファイル", - "text": "メモはすべて 1 つのファイルに保存され、別のコンピューターにコピーできます。", "new": "新規 znote ファイル…", "open": "znote ファイルを開く…", "bringIn": "既存のメモを取り込む…", diff --git a/src/lib/assets/locale/nb/backend.json b/src/lib/assets/locale/nb/backend.json index 2931332..9303080 100644 --- a/src/lib/assets/locale/nb/backend.json +++ b/src/lib/assets/locale/nb/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Denne chatten kan ikke inneholde vedlagte filer.", "notAttached": "“{name}” kunne ikke legges ved: {error}", "tooLarge": "“{name}” er for stor til å legges ved. Grensen er 32 MB.", + "notSupported": "«{name}»: denne filtypen støttes ikke.", + "notRead": "«{name}» kunne ikke leses.", "notSaved": "Denne chatten kunne ikke lagres: {error}", "notSavedOther": "Chatten kunne ikke lagres: {error}", "tooLong": "den har blitt for lang. Start en ny chat.", diff --git a/src/lib/assets/locale/nb/workspace.json b/src/lib/assets/locale/nb/workspace.json index c28e1d1..1e3cb0d 100644 --- a/src/lib/assets/locale/nb/workspace.json +++ b/src/lib/assets/locale/nb/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Velkommen til znote", "title": "Dine znote-filer", - "text": "Alle notatene dine lagres i én fil som du kan kopiere til en annen datamaskin.", "new": "Ny znote-fil…", "open": "Åpne en znote-fil…", "bringIn": "Hent inn notater jeg allerede har…", diff --git a/src/lib/assets/locale/nl/backend.json b/src/lib/assets/locale/nl/backend.json index c720ff6..66ef310 100644 --- a/src/lib/assets/locale/nl/backend.json +++ b/src/lib/assets/locale/nl/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Deze chat kan geen bijgevoegde bestanden bevatten.", "notAttached": "“{name}” kon niet worden bijgevoegd: {error}", "tooLarge": "“{name}” is te groot om bij te voegen. De limiet is 32 MB.", + "notSupported": "“{name}”: dit bestandstype wordt niet ondersteund.", + "notRead": "“{name}” kon niet worden gelezen.", "notSaved": "Deze chat kon niet worden opgeslagen: {error}", "notSavedOther": "De chat kon niet worden opgeslagen: {error}", "tooLong": "hij is te lang geworden. Begin een nieuwe chat.", diff --git a/src/lib/assets/locale/nl/workspace.json b/src/lib/assets/locale/nl/workspace.json index 397892a..a07394e 100644 --- a/src/lib/assets/locale/nl/workspace.json +++ b/src/lib/assets/locale/nl/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Welkom bij znote", "title": "Je znote-bestanden", - "text": "Al je notities worden opgeslagen in één bestand dat je naar een andere computer kunt kopiëren.", "new": "Nieuw znote-bestand…", "open": "Een znote-bestand openen…", "bringIn": "De notities die ik al heb toevoegen…", diff --git a/src/lib/assets/locale/pl/backend.json b/src/lib/assets/locale/pl/backend.json index 7476ee8..9482228 100644 --- a/src/lib/assets/locale/pl/backend.json +++ b/src/lib/assets/locale/pl/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Ten czat nie może zawierać załączonych plików.", "notAttached": "Nie udało się załączyć „{name}”: {error}", "tooLarge": "„{name}” jest zbyt duży, aby go załączyć. Limit wynosi 32 MB.", + "notSupported": "„{name}”: ten typ pliku nie jest obsługiwany.", + "notRead": "Nie można odczytać „{name}”.", "notSaved": "Nie udało się zapisać tego czatu: {error}", "notSavedOther": "Nie udało się zapisać czatu: {error}", "tooLong": "stał się zbyt długi. Rozpocznij nowy czat.", diff --git a/src/lib/assets/locale/pl/workspace.json b/src/lib/assets/locale/pl/workspace.json index 159b018..4f670ad 100644 --- a/src/lib/assets/locale/pl/workspace.json +++ b/src/lib/assets/locale/pl/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Witaj w znote", "title": "Twoje pliki znote", - "text": "Wszystkie notatki są zapisywane w jednym pliku, który możesz skopiować na inny komputer.", "new": "Nowy plik znote…", "open": "Otwórz plik znote…", "bringIn": "Zaimportuj notatki, które już mam…", diff --git a/src/lib/assets/locale/pt/backend.json b/src/lib/assets/locale/pt/backend.json index aa28845..6f52dc1 100644 --- a/src/lib/assets/locale/pt/backend.json +++ b/src/lib/assets/locale/pt/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Este chat não pode conter ficheiros anexados.", "notAttached": "Não foi possível anexar “{name}”: {error}", "tooLarge": "“{name}” é demasiado grande para ser anexado. O limite é 32 MB.", + "notSupported": "“{name}”: este tipo de ficheiro não é suportado.", + "notRead": "Não foi possível ler “{name}”.", "notSaved": "Não foi possível guardar este chat: {error}", "notSavedOther": "Não foi possível guardar o chat: {error}", "tooLong": "tornou-se demasiado longo. Inicie um novo chat.", diff --git a/src/lib/assets/locale/pt/workspace.json b/src/lib/assets/locale/pt/workspace.json index 0e34a4b..573ac30 100644 --- a/src/lib/assets/locale/pt/workspace.json +++ b/src/lib/assets/locale/pt/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Bem-vindo ao znote", "title": "Os seus ficheiros znote", - "text": "Todas as suas notas são guardadas num ficheiro que pode copiar para outro computador.", "new": "Novo ficheiro znote…", "open": "Abrir um ficheiro znote…", "bringIn": "Importar as notas que já tenho…", diff --git a/src/lib/assets/locale/ru/backend.json b/src/lib/assets/locale/ru/backend.json index 322d98c..c708b45 100644 --- a/src/lib/assets/locale/ru/backend.json +++ b/src/lib/assets/locale/ru/backend.json @@ -44,6 +44,8 @@ "noAttachments": "В этот чат нельзя добавлять файлы.", "notAttached": "Не удалось прикрепить «{name}»: {error}", "tooLarge": "Файл «{name}» слишком велик для вложения. Ограничение составляет 32 МБ.", + "notSupported": "«{name}»: этот тип файла не поддерживается.", + "notRead": "Не удалось прочитать «{name}».", "notSaved": "Не удалось сохранить этот чат: {error}", "notSavedOther": "Не удалось сохранить чат: {error}", "tooLong": "он стал слишком длинным. Начните новый чат.", diff --git a/src/lib/assets/locale/ru/workspace.json b/src/lib/assets/locale/ru/workspace.json index 5f5fd28..e7378a6 100644 --- a/src/lib/assets/locale/ru/workspace.json +++ b/src/lib/assets/locale/ru/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Добро пожаловать в znote", "title": "Ваши файлы znote", - "text": "Все заметки сохраняются в одном файле, который можно скопировать на другой компьютер.", "new": "Новый файл znote…", "open": "Открыть файл znote…", "bringIn": "Импортировать имеющиеся заметки…", diff --git a/src/lib/assets/locale/sv/backend.json b/src/lib/assets/locale/sv/backend.json index 7b63f38..29f5de0 100644 --- a/src/lib/assets/locale/sv/backend.json +++ b/src/lib/assets/locale/sv/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Den här chatten kan inte innehålla bifogade filer.", "notAttached": "”{name}” kunde inte bifogas: {error}", "tooLarge": "”{name}” är för stor för att bifogas. Gränsen är 32 MB.", + "notSupported": "”{name}”: den här filtypen stöds inte.", + "notRead": "”{name}” kunde inte läsas.", "notSaved": "Den här chatten kunde inte sparas: {error}", "notSavedOther": "Chatten kunde inte sparas: {error}", "tooLong": "Den har blivit för lång. Starta en ny chatt.", diff --git a/src/lib/assets/locale/sv/workspace.json b/src/lib/assets/locale/sv/workspace.json index 149a28e..2d31465 100644 --- a/src/lib/assets/locale/sv/workspace.json +++ b/src/lib/assets/locale/sv/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Välkommen till znote", "title": "Dina znote-filer", - "text": "Alla dina anteckningar sparas i en fil som du kan kopiera till en annan dator.", "new": "Ny znote-fil…", "open": "Öppna en znote-fil…", "bringIn": "Importera anteckningar jag redan har…", diff --git a/src/lib/assets/locale/tr/backend.json b/src/lib/assets/locale/tr/backend.json index 328fb44..e423557 100644 --- a/src/lib/assets/locale/tr/backend.json +++ b/src/lib/assets/locale/tr/backend.json @@ -44,6 +44,8 @@ "noAttachments": "Bu sohbet ekli dosyaları tutamaz.", "notAttached": "“{name}” eklenemedi: {error}", "tooLarge": "“{name}” eklenemeyecek kadar büyük. Sınır 32 MB'tır.", + "notSupported": "“{name}”: bu dosya türü desteklenmiyor.", + "notRead": "“{name}” okunamadı.", "notSaved": "Bu sohbet kaydedilemedi: {error}", "notSavedOther": "Sohbet kaydedilemedi: {error}", "tooLong": "çok uzadı. Yeni bir sohbet başlatın.", diff --git a/src/lib/assets/locale/tr/workspace.json b/src/lib/assets/locale/tr/workspace.json index 70b02ac..cfd8440 100644 --- a/src/lib/assets/locale/tr/workspace.json +++ b/src/lib/assets/locale/tr/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "znote'a hoş geldiniz", "title": "znote dosyalarınız", - "text": "Tüm notlarınız, başka bir bilgisayara kopyalayabileceğiniz tek bir dosyada saklanır.", "new": "Yeni znote dosyası…", "open": "Bir znote dosyası aç…", "bringIn": "Zaten sahip olduğum notları getir…", diff --git a/src/lib/assets/locale/uk/backend.json b/src/lib/assets/locale/uk/backend.json index 2af5d4c..aca3f6d 100644 --- a/src/lib/assets/locale/uk/backend.json +++ b/src/lib/assets/locale/uk/backend.json @@ -44,6 +44,8 @@ "noAttachments": "У цьому чаті не можна додавати файли.", "notAttached": "Не вдалося додати «{name}»: {error}", "tooLarge": "«{name}» занадто великий для додавання. Ліміт становить 32 МБ.", + "notSupported": "«{name}»: цей тип файлу не підтримується.", + "notRead": "Не вдалося прочитати «{name}».", "notSaved": "Не вдалося зберегти цей чат: {error}", "notSavedOther": "Не вдалося зберегти чат: {error}", "tooLong": "Він став занадто довгим. Почніть новий чат.", diff --git a/src/lib/assets/locale/uk/workspace.json b/src/lib/assets/locale/uk/workspace.json index bb79c8c..6532b32 100644 --- a/src/lib/assets/locale/uk/workspace.json +++ b/src/lib/assets/locale/uk/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "Ласкаво просимо до znote", "title": "Ваші файли znote", - "text": "Усі ваші нотатки зберігаються в одному файлі, який можна скопіювати на інший комп’ютер.", "new": "Новий файл znote…", "open": "Відкрити файл znote…", "bringIn": "Імпортувати наявні нотатки…", diff --git a/src/lib/assets/locale/zh-CN/backend.json b/src/lib/assets/locale/zh-CN/backend.json index 031a1b7..03bb38e 100644 --- a/src/lib/assets/locale/zh-CN/backend.json +++ b/src/lib/assets/locale/zh-CN/backend.json @@ -44,6 +44,8 @@ "noAttachments": "此聊天不支持附加文件。", "notAttached": "无法附加“{name}”:{error}", "tooLarge": "“{name}”太大,无法附加。上限为 32 MB。", + "notSupported": "“{name}”:不支持此文件类型。", + "notRead": "无法读取“{name}”。", "notSaved": "无法保存此聊天:{error}", "notSavedOther": "无法保存聊天:{error}", "tooLong": "它已经变得太长了。请开始新的聊天。", diff --git a/src/lib/assets/locale/zh-CN/workspace.json b/src/lib/assets/locale/zh-CN/workspace.json index 18eab45..4af9142 100644 --- a/src/lib/assets/locale/zh-CN/workspace.json +++ b/src/lib/assets/locale/zh-CN/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "欢迎使用 znote", "title": "您的 znote 文件", - "text": "您的所有笔记都保存在一个文件中,可复制到另一台电脑。", "new": "新建 znote 文件…", "open": "打开 znote 文件…", "bringIn": "导入我已有的笔记…", diff --git a/src/lib/assets/locale/zh-TW/backend.json b/src/lib/assets/locale/zh-TW/backend.json index 21df171..e8740b4 100644 --- a/src/lib/assets/locale/zh-TW/backend.json +++ b/src/lib/assets/locale/zh-TW/backend.json @@ -44,6 +44,8 @@ "noAttachments": "這個聊天無法附加檔案。", "notAttached": "無法附加「{name}」:{error}", "tooLarge": "「{name}」太大,無法附加。上限為 32 MB。", + "notSupported": "「{name}」:不支援此檔案類型。", + "notRead": "無法讀取「{name}」。", "notSaved": "無法儲存這個聊天:{error}", "notSavedOther": "無法儲存聊天:{error}", "tooLong": "它已經變得太長。請開始新的聊天。", diff --git a/src/lib/assets/locale/zh-TW/workspace.json b/src/lib/assets/locale/zh-TW/workspace.json index 40cf08d..05899f0 100644 --- a/src/lib/assets/locale/zh-TW/workspace.json +++ b/src/lib/assets/locale/zh-TW/workspace.json @@ -56,7 +56,6 @@ "file": { "welcome": "歡迎使用 znote", "title": "您的 znote 檔案", - "text": "您的所有筆記都儲存在一個檔案中,可以複製到另一部電腦。", "new": "新增 znote 檔案…", "open": "開啟 znote 檔案…", "bringIn": "匯入我已有的筆記…", diff --git a/src/lib/components/FirstStart.svelte b/src/lib/components/FirstStart.svelte index 1bdadad..f888aaf 100644 --- a/src/lib/components/FirstStart.svelte +++ b/src/lib/components/FirstStart.svelte @@ -113,7 +113,6 @@ settings.set("marketplace", checked)} /> -

{t("privacy.start.later")}

diff --git a/src/lib/components/PrivacySettings.svelte b/src/lib/components/PrivacySettings.svelte index c1e596c..fcaa969 100644 --- a/src/lib/components/PrivacySettings.svelte +++ b/src/lib/components/PrivacySettings.svelte @@ -50,11 +50,12 @@ {#if !usable}

{t("privacy.settings.needsFile")}

{/if} {#if privacy.blocked}{/if} - {#if privacy.required("hideNames")}

{t("privacy.panel.required")}

{/if} + {#if privacy.required("hideNames")}

{t("privacy.panel.required")}

{/if} {#each switches.slice(0, 2) as { key, disabled } (key)}{@render toggle(key, disabled())}{/each} {@render toggle("privacyNames", switches[2].disabled())} +

{t("privacy.glossary.title")}

diff --git a/src/lib/components/ProjectStart.svelte b/src/lib/components/ProjectStart.svelte index a8a24ad..18963d8 100644 --- a/src/lib/components/ProjectStart.svelte +++ b/src/lib/components/ProjectStart.svelte @@ -65,7 +65,6 @@

znote

{/if} {t(first ? "workspace.file.welcome" : "workspace.file.title")} - {t("workspace.file.text")}
diff --git a/src/lib/components/SettingsDialog.svelte b/src/lib/components/SettingsDialog.svelte index 083b1d0..e4b42f9 100644 --- a/src/lib/components/SettingsDialog.svelte +++ b/src/lib/components/SettingsDialog.svelte @@ -139,12 +139,10 @@ -

{t("providers.dialogText")}

-

{t("privacy.settings.text")}

diff --git a/src/lib/state/agent.svelte.ts b/src/lib/state/agent.svelte.ts index 54c15e0..4ca298c 100644 --- a/src/lib/state/agent.svelte.ts +++ b/src/lib/state/agent.svelte.ts @@ -72,7 +72,7 @@ if (import.meta.vitest) { handler({ kind: "text", text }); handler({ kind: "done", session: "session-1", failure: null }); }), - agentAttach: vi.fn(async () => [{ name: "report.pdf", id: "1.pdf", path: "/data/assistant/1-report.pdf", text: null, level: 1 }]), + agentAttach: vi.fn(async () => ({ files: [{ name: "report.pdf", id: "1.pdf", path: "/data/assistant/1-report.pdf", text: null, level: 1 }], problems: [] as string[] })), agentFiles: vi.fn(async () => [{ name: "report.pdf", id: "1.pdf", path: "/data/assistant/1-report.pdf", text: null, level: 1 }]), agentSeen: vi.fn(async () => new ArrayBuffer(0)), agentDetach: vi.fn(async () => {}), @@ -173,6 +173,19 @@ if (import.meta.vitest) { expect(agent.references.map(({ label }) => label)).toEqual(["report.pdf"]); }); + test("a file that could not be attached does not keep the others out", async () => { + const { agent, backend } = setup(["Done."]); + backend.agentAttach.mockResolvedValueOnce({ + files: [{ name: "report.pdf", id: "1.pdf", path: "/data/assistant/1-report.pdf", text: null, level: 1 }], + problems: ["“tool.exe” could not be attached: This file cannot be read as text."], + }); + await agent.attach(); + expect(agent.references.map(({ label }) => label)).toEqual(["report.pdf"]); + expect(agent.failure).toContain("tool.exe"); + await agent.attach(); + expect(agent.failure).toBe(null); + }); + test("the chosen preset decides the model, what the assistant may do, and whether it asks before deleting", async () => { const reply = '```znote\n{"do":"delete","path":"Work/Old"}\n{"do":"create","path":"Work/New"}\n```'; const { agent, files, chosen, backend, linked } = setup([reply, reply]); diff --git a/src/lib/state/settings.svelte.ts b/src/lib/state/settings.svelte.ts index c5799d7..2fc77bc 100644 --- a/src/lib/state/settings.svelte.ts +++ b/src/lib/state/settings.svelte.ts @@ -24,6 +24,7 @@ export type Settings = { assistantPreset: string | null; assistantModels: Record; assistantPresets: Record; + assistantRouting: "private" | "cheapest"; privacyAsked: boolean; privacyVeil: boolean; privacyAmounts: boolean; @@ -58,6 +59,7 @@ export const defaults: Settings = { assistantPreset: null, assistantModels: {}, assistantPresets: {}, + assistantRouting: "private", privacyAsked: false, privacyVeil: false, privacyAmounts: true, @@ -103,6 +105,7 @@ export function merged(stored: Record, osPrefersDark: boolean): assistantPreset: text(stored.assistantPreset), assistantModels: names(stored.assistantModels), assistantPresets: storedPresets(stored.assistantPresets), + assistantRouting: stored.assistantRouting === "cheapest" ? "cheapest" : "private", privacyAsked: flag(stored.privacyAsked, defaults.privacyAsked), privacyVeil: flag(stored.privacyVeil, defaults.privacyVeil), privacyAmounts: flag(stored.privacyAmounts, defaults.privacyAmounts), @@ -154,6 +157,7 @@ if (import.meta.vitest) { expect(merged({ pageLevels: { "Work/A": 3, "Work/B": 7, "Work/C": "high" }, layout: "agent" }, false)).toMatchObject({ pageLevels: { "Work/A": 3 }, layout: "agent" }); expect(merged({ layout: "huge" }, false).layout).toBe("edit"); expect(merged({ assistantModels: { custom: "llama", claude: 7 }, assistantProvider: "custom" }, false)).toMatchObject({ assistantModels: { custom: "llama" }, assistantProvider: "custom" }); + expect([merged({ assistantRouting: "cheapest" }, false), merged({ assistantRouting: "free" }, false)].map((values) => values.assistantRouting)).toEqual(["cheapest", "private"]); }); test("with no saved theme the OS decides", () => { diff --git a/tools/demo/demo.spec.ts b/tools/demo/demo.spec.ts index a32bc65..fd5c14a 100644 --- a/tools/demo/demo.spec.ts +++ b/tools/demo/demo.spec.ts @@ -43,8 +43,8 @@ const WORDS = { meeting: "Meeting notes", report: "Quarterly report.pdf", letter: "Supplier letter.pdf", - intro: ["Typst notes with a live preview and an assistant"], - outro: ["Typst, live preview, an assistant that cannot see your names", "github.com/ZAL-Analytics/znote"], + intro: ["Smart note app with an AI assistant that cannot see your data"], + outro: ["An AI assistant that cannot see your data"], welcome: "One file holds all your notes", password: "Encrypted with a password of your own", layout: "First start: pick a layout", @@ -81,8 +81,10 @@ const WORDS = { export: "Export to PDF, PowerPoint or Word" }; -const intro = { title: "znote", lines: WORDS.intro }; -const outro = { title: "znote", lines: WORDS.outro }; +// The title cards in the ZAL Analytics style, with the app icon. +const icon = `data:image/png;base64,${readFileSync(join(root, "src-tauri/icons/128x128@2x.png")).toString("base64")}`; +const intro = { title: "znote", lines: WORDS.intro, icon, footer: "github.com/ZAL-Analytics/znote" }; +const outro = { title: "znote", lines: WORDS.outro, icon, footer: "github.com/ZAL-Analytics/znote" }; // Starts from a first run: everything the demo app kept is removed except the // Claude Code folder, which holds the sign-in made with `--sign-in`. @@ -130,12 +132,13 @@ test("record the demo", async ({ page }) => { copyFileSync(source, copy); const listed = await relay.call("plugin:zsuite-assistant|agent_files", { chat }); if (!listed.ok) return listed; - return { ok: true, value: (listed.value as { path: string }[]).filter((file) => file.path === copy) }; + return { ok: true, value: { files: (listed.value as { path: string }[]).filter((file) => file.path === copy), problems: [] } }; }); const nextAttachment: string[] = []; await page.goto("/"); stage.begin(); + stage.trailer(true); const ui = new Ui(page, stage); await firstStart(ui); @@ -145,7 +148,9 @@ test("record the demo", async ({ page }) => { await filtering(ui, nextAttachment); await extras(ui); + stage.trailer(true); await stage.card(outro, 2600); + stage.trailer(false); stage.saveCuts(join(work, "cuts.txt")); } finally { await relay.stop(); @@ -222,6 +227,7 @@ async function firstStart(ui: Ui): Promise { await expect(ui.button(t("workspace.file.open"))).toBeVisible({ timeout: 60_000 }); await stage.beat(900); await stage.hideCard(); + stage.trailer(false); await stage.caption(WORDS.welcome, 900); await stage.still("Welcome"); @@ -239,12 +245,14 @@ async function firstStart(ui: Ui): Promise { await stage.still("FirstStart_Layout"); await ui.tap(ui.button(t("common.next"))); + stage.trailer(true); await stage.caption(WORDS.privacy, 600); for (const id of ["veil", "names", "knowledge"]) { const toggle = page.locator(`#start-${id}`); if ((await toggle.getAttribute("aria-checked")) !== "true") await ui.tap(toggle, 350); } await stage.still("FirstStart_Privacy"); + stage.trailer(false); await ui.tap(ui.button(t("common.next"))); await stage.caption(WORDS.knowledge, 300); @@ -284,6 +292,7 @@ async function layouts(ui: Ui): Promise { await ui.open(WORDS.brief); await stage.still("Edit_ProjectBrief"); + stage.trailer(true); await stage.caption(WORDS.typing, 200); const editor = page.locator(".cm-content").first(); await editor.click(); @@ -304,6 +313,7 @@ async function layouts(ui: Ui): Promise { await stage.caption(WORDS.redactLayout, 200); await ui.layout("redaction"); await stage.still("Layout_Redact"); + stage.trailer(false); await ui.layout("edit"); await stage.hideCaption(); @@ -312,6 +322,7 @@ async function layouts(ui: Ui): Promise { async function marketplace(ui: Ui): Promise { const { page, stage } = ui; + stage.trailer(true); await stage.caption(WORDS.marketplace, 200); await ui.tap(ui.button(t("common.mode.marketplace")), 800); const search = t("themes.search"); @@ -331,6 +342,7 @@ async function marketplace(ui: Ui): Promise { await stage.caption(WORDS.look, 200); await ui.tap(page.getByRole("button", { name: t("themes.use"), exact: true }).first(), 900); await stage.still("Marketplace_Installed"); + stage.trailer(false); await stage.caption(WORDS.templates, 200); await ui.tap(ui.button(t("common.layout.edit")), 500); @@ -361,6 +373,7 @@ async function assistant(ui: Ui, attachments: string[]): Promise { await ui.layout("agent"); await stage.caption(WORDS.claude, 400); + stage.trailer(true); await stage.caption(WORDS.document, 200); const target = ui.button(t("assistant.composer.target")); const template = ui.button(t("assistant.composer.template")); @@ -370,6 +383,7 @@ async function assistant(ui: Ui, attachments: string[]): Promise { await stage.still("Assistant_Output"); await send(ui, WORDS.documentPrompt); await stage.still("Assistant_NewPage"); + stage.trailer(false); // the composer keeps these choices across chats, so they are cleared for the next ones; // generate mode stays on, so the next chat may edit the page await ui.tap(ui.button(t("assistant.composer.targetClear")), 200); @@ -411,13 +425,16 @@ async function assistant(ui: Ui, attachments: string[]): Promise { async function filtering(ui: Ui, attachments: string[]): Promise { const { page, stage } = ui; if (ASSISTANT) { + stage.trailer(true); await stage.caption(WORDS.sees, 300); await ui.chatFiles(); await stage.still("Filter_ChatFiles"); await page.keyboard.press("Escape"); + stage.trailer(false); } await ui.layout("redaction"); + stage.trailer(true); await stage.caption(WORDS.levels, 200); // a page button also names the page's level, so only its start is matched await ui.tap(page.getByRole("region", { name: t("workspace.browser.notebooks") }).getByRole("button", { name: /^Planning/ }), 300); @@ -425,6 +442,7 @@ async function filtering(ui: Ui, attachments: string[]): Promise { const redaction = page.getByRole("region", { name: t("privacy.redact.title") }); for (const level of ["medium", "strict"]) await ui.tap(ui.level(redaction, t(`privacy.level.short.${level}`)), 1100); await stage.still("Filter_Strict"); + stage.trailer(false); await ui.tap(ui.level(redaction, t("privacy.level.short.light")), 900); await stage.still("Filter_Light"); @@ -457,6 +475,7 @@ async function extras(ui: Ui): Promise { await ui.layout("edit"); await ui.open(WORDS.brief); + stage.trailer(true); await stage.caption(WORDS.languages, 200); // its name changes with the language, so it is found by its place const language = page.locator("header [data-slot=select-trigger]").first(); @@ -475,6 +494,7 @@ async function extras(ui: Ui): Promise { await stage.caption(WORDS.export, 200); await ui.tap(ui.button(t("common.mode.export")), 900); await stage.still("Export"); + stage.trailer(false); await ui.tap(ui.button(t("common.appearance.toLight")), 400); await stage.hideCaption(); stage.mark("extras"); diff --git a/tools/demo/stage.ts b/tools/demo/stage.ts index 732025f..66c37ff 100644 --- a/tools/demo/stage.ts +++ b/tools/demo/stage.ts @@ -1,7 +1,8 @@ import type { Locator, Page } from "@playwright/test"; import { mkdirSync, writeFileSync } from "node:fs"; -export type Card = { title: string; lines: string[] }; +// A title card; icon is an image URL (the app icon), footer a line at the bottom. +export type Card = { title: string; lines: string[]; icon?: string; footer?: string }; type StageApi = { caption: (text: string) => void; @@ -57,14 +58,19 @@ export function installStage(intro: Card): void { #stage-card { position: fixed; inset: 0; z-index: 2147483002; display: flex; flex-direction: column; align-items: center; justify-content: center; - gap: 20px; background: #fafafa; color: #111; - font-family: ui-sans-serif, system-ui, sans-serif; text-align: center; + gap: 22px; color: #0a0a0a; text-align: center; + background: radial-gradient(circle, rgba(0, 0, 0, 0.09) 1px, transparent 1px) 0 0 / 24px 24px, #fafafa; + font-family: "Inter Variable", Inter, ui-sans-serif, system-ui, sans-serif; opacity: 0; transition: opacity 320ms ease; pointer-events: none; } #stage-card.on { opacity: 1; } - #stage-card .title { font-size: 64px; font-weight: 800; letter-spacing: -0.03em; } - #stage-card .line { font-size: 24px; color: #666; } - #stage-card .line.mono { font-family: ui-monospace, monospace; color: #111; } + #stage-card .icon { width: 140px; height: 140px; filter: drop-shadow(0 14px 30px rgba(0, 0, 0, 0.18)); } + #stage-card .title { font-family: ui-monospace, "JetBrains Mono", monospace; font-size: 72px; font-weight: 700; letter-spacing: -0.04em; } + #stage-card .bar { width: 72px; height: 4px; border-radius: 2px; background: #A37D86; } + #stage-card .line { max-width: 70vw; font-size: 30px; font-weight: 400; color: #525252; } + #stage-card .line.mono { font-family: ui-monospace, monospace; color: #0a0a0a; } + #stage-card .footer { position: absolute; bottom: 56px; display: flex; gap: 16px; align-items: baseline; font-size: 20px; color: #737373; } + #stage-card .footer b { font-family: ui-monospace, monospace; font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: #0a0a0a; } `; const build = (): void => { @@ -108,7 +114,9 @@ export function installStage(intro: Card): void { const lines = next.lines .map((line) => `
${line}
`) .join(""); - card.innerHTML = `
${next.title}
${lines}`; + const icon = next.icon ? `` : ""; + const footer = next.footer ? `` : ""; + card.innerHTML = `${icon}
${next.title}
${lines}${footer}`; }; window.__stage = { @@ -138,6 +146,8 @@ export function installStage(intro: Card): void { export class Stage { private readonly started = Date.now(); private readonly skips: [number, number][] = []; + private readonly scenes: [number, number][] = []; + private scene: number | null = null; private trim = 0; private taken = 0; @@ -191,6 +201,15 @@ export class Stage { return result; } + /** Starts or ends a stretch the 60 second trailer keeps. */ + trailer(on: boolean): void { + if (on) this.scene ??= this.now(); + else if (this.scene !== null) { + this.scenes.push([this.scene, this.now()]); + this.scene = null; + } + } + /** Marks where the clip starts: anything before is the app starting up. */ begin(): void { this.trim = this.now(); @@ -198,10 +217,15 @@ export class Stage { /** * Writes the cuts for scripts/record.sh: `trim ` first, then one - * ` ` line per sped up stretch. + * ` ` line per sped up stretch, then a `scene ` line per + * stretch the trailer keeps. */ saveCuts(file: string): void { - const lines = [`trim ${this.trim.toFixed(2)}`, ...this.skips.map(([from, to]) => `${from.toFixed(2)} ${to.toFixed(2)}`)]; + const lines = [ + `trim ${this.trim.toFixed(2)}`, + ...this.skips.map(([from, to]) => `${from.toFixed(2)} ${to.toFixed(2)}`), + ...this.scenes.map(([from, to]) => `scene ${from.toFixed(2)} ${to.toFixed(2)}`) + ]; writeFileSync(file, `${lines.join("\n")}\n`); } diff --git a/vendor/zsuite b/vendor/zsuite index 1d34e9e..e6ad303 160000 --- a/vendor/zsuite +++ b/vendor/zsuite @@ -1 +1 @@ -Subproject commit 1d34e9e6668481a2c1c8d0d498c10bb9e8e0e704 +Subproject commit e6ad303036fa7edc41f2f57491dcf0961caf6847