Commit graph

28 commits

Author SHA1 Message Date
Horizontal42
edfa55e4dc
extract sparkline SVG rendering into its own module 2026-08-09 15:57:22 +03:00
Horizontal42
c89242b626 debounce variable highlight scanning in editor 2026-07-29 14:14:49 +03:00
Horizontal42
5ccb46b01c cache sheet results for numeric search 2026-07-29 14:14:49 +03:00
Horizontal42
c1a7254fdf fix arbitrary file write via write_text_file/write_image_file
Both Tauri commands took a raw path string straight from the frontend
and wrote to it with no validation — any code able to call invoke()
(a compromised or malicious extension script, which run with full page
privileges) could write to any path the OS user has access to, not just
one chosen through the save dialog. Move the save-file dialog into the
Rust command itself so the only path ever used is one the native dialog
returned; the frontend now only sends the content to save.
2026-07-08 15:50:13 +03:00
Horizontal42
47beea4652 avoid rebuilding decoration fields on every editor transaction
highlightField and varHighlightField rebuilt from scratch on every
CodeMirror transaction, including ones that touch neither the doc nor
the selection (e.g. the setResults effect firing after evaluation).
varHighlightField now only rebuilds when the doc or selection actually
changed; highlightField remaps existing decorations through doc edits
and only does a full rebuild when new results arrive.
2026-07-08 14:15:04 +03:00
Horizontal42
bb6b08f153 fix: results-width slider still showed the native OS control
appearance:none on the <input> alone didn't strip the native chrome
in every Chromium build — some keep ::-webkit-slider-runnable-track
styled natively unless that pseudo-element gets its own
appearance:none. Made the track's styling explicit there instead of
relying on it inheriting from the input.
2026-07-03 13:12:50 +03:00
Horizontal42
7b94f6a5b0 sheets: reorder by dragging instead of up/down buttons
Move-up/move-down felt disconnected from the result — clicking a
button and having two rows silently swap position doesn't read as
motion. Dropped both buttons for native HTML5 drag-and-drop: drag a
sheet, an accent line shows where it'll land, drop to reorder. Still
respects the pinned/unpinned grouping — dragging across that boundary
is a no-op, same as the old up/down buttons.
2026-07-03 12:57:14 +03:00
Horizontal42
5205c9fb63 design: market status matches rates styling, shows a loading pulse
#market-info had no CSS at all — different font size and color from
#rates-info right next to it, and its own hardcoded English "Market"
text ignored the language setting. Merged its styling into the same
rule as #rates-info and gave it the same .spin pulse while a fetch
is in flight, so a market refresh is as visible as a rates refresh.
2026-07-03 12:55:32 +03:00
Horizontal42
88a60c4e73 design: style the results-width slider to match the theme
It was still the bare OS-native slider — flat gray track everywhere
else in Settings is themed. Now a thin themed track with an accent
thumb that grows slightly while dragging.
2026-07-03 12:53:47 +03:00
Horizontal42
708206d245 fix: overlays only animated opening, closing snapped instantly
Settings, export menu, modal, and search all drove their entrance
with a @keyframes animation gated on :not(.hidden), triggered by a
display:none toggle — animations don't run when a property changes
away from display:none, only when the element (re)enters the render
tree. Closing just flipped straight to display:none with nothing to
watch. Replaced with opacity/transform transitions plus a delayed
visibility flip (visibility switches instantly on open, only after
the fade completes on close) — same visual effect, correct both ways.
2026-07-03 12:53:08 +03:00
Horizontal42
fd97484c4a design: pulsing indicator while rates refresh
The status bar just dimmed the "Rates" text to 0.5 opacity and left
it static for the whole fetch — easy to miss as feedback that
anything is happening. A slow pulse reads as "working" instead of
just "disabled".
2026-07-03 12:35:22 +03:00
Horizontal42
4302f7025c design: keyboard focus ring on form fields
Doc title, search input, and settings inputs/selects either zeroed
out the default outline or never set one — Tab-only navigation had
no visible indicator of what's focused. :focus-visible keeps mouse
clicks silent and only rings for keyboard focus.
2026-07-03 12:34:27 +03:00
Horizontal42
ec8b2f6448 design: thin scrollbars matching the theme
Default Windows scrollbars were chunky and out of place next to the
minimal chrome elsewhere. WebView2 is Chromium under the hood, so a
plain ::-webkit-scrollbar override works everywhere without JS.
2026-07-03 12:33:51 +03:00
Horizontal42
92dd4e3125 extend subtle animations from settings to the rest of the app
Sidebar collapse now transitions width instead of snapping via
display:none. Export menu, the modal, and the search overlay all get
a short pop-in (scale + fade) matching the settings panel's motion.
Buttons, doc-list items, and status-bar text ease their hover/color
changes instead of snapping.

Left alone on purpose: the results overlay (re-rendered on every
keystroke — animating it would feel laggy, not smooth), the
autocomplete tooltip (CodeMirror's own timing), and the column-resize
drag handle (wants instant feedback while dragging).
2026-07-03 12:25:53 +03:00
Horizontal42
702670e08d settings: subtle open and tab-switch animations
Settings panel pops in (scale + fade, 0.15s) instead of appearing
instantly; switching tabs fades the new panel in (0.12s); the tab
buttons themselves transition their background/color on hover and
selection instead of snapping. CSS-only — @keyframes animations run
even from display:none, so no JS timing/exit-animation complexity.
2026-07-03 12:14:26 +03:00
Horizontal42
e5ef1164cc settings: show the running app version
Updates tab, below the check-update button. Reads from
tauri.conf.json via getVersion() in a real build (the source of
truth for what's actually installed); falls back to package.json's
version under vite dev, where there's no Tauri runtime to ask.
2026-07-03 12:13:01 +03:00
Horizontal42
1e06281f5e settings: tabbed panel, date format, update controls
The flat settings list had grown to 14 fields plus footer buttons —
split it into General / Format / Data / Updates tabs (same pill style
as the pinned-doc sidebar, active tab gets the selection color).

Wired the date-format setting into the engine, and reworked update
checks per an actual bug report: a boot-only check is easy to miss on
a tray app that can run for weeks without a cold restart, and every
failure was swallowed silently with no logging at all. Now: failures
are logged (console.warn) and successful "no update" checks say why
(console.info, current version vs. latest published release) so the
next report has something to go on; checks also rerun every 6 hours;
Settings has both a manual "Check for updates" button (reports back
via toast) and a toggle to turn automatic checking off entirely —
manual checks keep working either way.
2026-07-03 12:00:39 +03:00
Horizontal42
5af7c66c3c refactor: pull cross-sheet search and PNG export out of main.ts
Both were self-contained enough to live in their own modules —
src/ui/search.ts (Ctrl+F overlay, text and result-value queries) and
src/ui/export.ts (render the sheet + results to a PNG, clipboard or
file). Trims main.ts by about 150 lines.

Also fixes a real bug while it's in there: the PNG export's clipboard
fallback did btoa(String.fromCharCode(...bytes)), which blows the
call stack on large sheets (spreading a big array as call arguments).
Chunks the conversion in 0x8000-byte pieces instead.
2026-07-03 11:57:33 +03:00
Horizontal42
90c19e343f show unresolved cross-sheet references as a visible #ref? marker 2026-07-02 05:41:17 +03:00
Horizontal42
9d8f977c46 wire cross-sheet references into the editor and document lifecycle 2026-07-02 05:38:02 +03:00
Horizontal42
4b5381d7e7 sheet organization: pin and reorder with up/down arrows 2026-07-01 20:31:43 +03:00
Horizontal42
f8f9095fca add ISO date literals and days until/since 2026-07-01 20:27:55 +03:00
Horizontal42
eff90d3219 add chart/spark sparkline keyword — renders inline SVG in results column 2026-07-01 20:05:24 +03:00
Horizontal42
9aca062add add search across all sheets and always-on-top toggle
Ctrl+F opens an overlay that searches every document's lines, not just
the active one, and jumps to the hit on click. Always-on-top is a
plain window pin, off by default, toggleable in settings.
2026-07-01 14:54:44 +03:00
Horizontal42
b0c46c390c RU math phrases, half/полтора constants, export button
- vocab: EN+RU aliases for abs/log/ln/round; RU already had sqrt/cbrt
- engine: "half"/"a half"/"one half"/"половина" → 0.5; "one and a half"/"полтора"/"полторы" → 1.5 as named constants; widen const union in parser/tokenizer/evaluator/registry
- export: ⤓ button in statusbar dropdown — copy sheet, save .sum, export .txt, print/PDF; write_text_file Tauri command; print media CSS hides chrome
2026-06-24 00:27:06 +03:00
Horizontal42
4c05d63b55 expand vocab: more RU cases for currencies/units, Tab-only autocomplete
- EUR: add "Euros"; CHF: add "franc,francs"; INR: add "rupee,rupees"; USD: add "buck,bucks"; CNY: add "renminbi"
- RU USD: full declension + slang бакс/баксов/...; JPY: all 8 cases for иена/йена; UAH: all гривна cases; TRY: bare лира declension; CNY: жэньминьби + full cases; CHF: all франк cases; BRL/KRW/PLN: extended declension
- RU units: fill missing dative/instrumental/prepositional/accusative for час/минута/секунда/день/неделя/месяц/год/метр/грамм/литр/тонна/унция/фут/дюйм/миля/ярд
- RU scales: тысяча/миллион/миллиард full declension
- RU conversion: добавить "перевести в / конвертировать в"
- editor: autocompletion defaultKeymap:false so Enter only newlines, Tab accepts suggestion
2026-06-23 23:48:40 +03:00
Horizontal42
f55266f70b v1.1.0: bug fixes, atomic writes, safe quit, .sum files, CI
Engine: fix BigInt crash on NaN, KM/KG case-insensitive units, space-grouped
and comma-decimal number parsing, variable-vs-unit shadowing, small value
display (1 mm in km), DST-safe date arithmetic, month-end clamp, log mustTouch,
avg counted, 50% of 50%, 100 USD + 20 after conversion, percent power.

Rust: atomic writes (temp+rename) for documents.json, safe quit (app-quit event
+ 2s watchdog so tray-quit doesn't lose edits), .sum file association + open,
migration safety (canonicalize + all_copied guard), opener API for backups and
extensions folders.

UI: decimal separator setting, hotkey rollback on failure, corrupted JSON guard,
ru welcome sheet, orange cursor visibility.

CI: windows-latest workflow (tsc + vitest + cargo clippy).
2026-06-11 12:57:39 +03:00
Horizontal42
0cef414e9a feat: Summarum — natural language calculator notebook for Windows
Write plain text, get live results per line. English + Russian, units,
live currency rates with crypto, percents, dates and timezones, bitwise
ops, variables and sheet totals. Tauri 2 + TypeScript engine +
CodeMirror 6; daily backups and a deleted-sheets bin.

Inspired by Numi for macOS (numi.app); built from scratch for Windows.
2026-06-10 22:19:24 +03:00