Commit Graph

397 Commits

Author SHA1 Message Date
Utsav Singh 927d7dd9b2
Fix quick measuring of skewed and rotated layers by using the viewport space AABB (#2396)
* Make sure that quick measure overlays are based on AABBs drawn in the viewport local space

* Draw overlays to visualise AABBs of selected and hovered shapes

* use pre-existing functions to render dashed lines

* Redraw selected bounds using existing BoundingBoxManager

* remove unused variables

* Render transform cage after overlay is drawn

* Bring overlay and transform cage render calls above(before) other  gizmos

* Add line length tolerance and render single line for singal edge alignment with one axis overlap

* Comments

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-12 10:53:58 +00:00
0SlowPoke0 2bcfe5ea0c
In the Pen tool, make Space drag the whole manipulator group while dragging a handle (#2416)
* implemented space drag need to handle unwrap + clean snap cache

* completed the space drag need to refactor

* refactor

* small comment changes

* formating_fix

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-12 03:27:35 -07:00
Nitish Choudhary c0d3eb8072
Add sizing gizmos to the Text tool's text area (#2176)
* Fix abortion while dragging

* Create function for text bounding box

* Reorder arms of text tool FSM

* add transform cage to textbox pt.1

* add transform cage pt.2

* Fix minor issue after merge

* Get bounding box working in place without action keys

* Add max_height and disable pivot drag

* Cleanup code and write doco for new utility function

* Minor change due to merge

* Add bottom overlay

* Get modifier keys to work pt.1

* Code cleanup

* cleanup

* Fix transform

* Minor improvements

* Undo debug statement!

* Add comments and keep original layer transformation

* Alt from centre

* Fix merge conflict

* Minor code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: James Lindsay <78500760+0HyperCube@users.noreply.github.com>
2025-03-12 10:07:10 +00:00
Keavon Chambers a696aae044
Instance tables refactor part 5: unwrap GraphicGroup as multi-row Instance<GraphicElement> tables and move up transforms (#2363)
* Just group

* Partly working but without transforms

* Remove Transform/TransformMut from GraphicElement and GraphicGroupTable

* Fix layers and flattening

* Fix transform group handling on the remaining nodes

* Change collect metadata

* Add transform on vector data. TODO: Remove duplicate transform

* Small code tidying-up

* Add concatenate node?

* Remove ignore_modifications which is always false

* Improve transforms

* Mostly fix the nested transform cage angle (except leaf layers and skew)

* WIP attempt to integrate skew

* Fix nesting bounding box

* Avoid setting the transform

* Fix stroke transforms

* Renderer cleanup

* Fix tests for repeated elements not given unique point IDs

* Suppress cargo-deny warning

* Fix upgrade code for graphic group data

* Work around rendering issue in Isometric Fountain

---------

Co-authored-by: Adam <adamgerhant@gmail.com>
Co-authored-by: hypercube <0hypercube@gmail.com>
2025-03-12 01:38:36 -07:00
Ellen Gu 74b6abbb97
Fix fill tool on raster image temporarily breaking the graph (#2398)
* Fix fill tool on raster image temporarily breaks the graph

* Avoid vector filling raster layer via checking node category

* check raster image using input type instead

* Add additional check for TextureFrameTable

* Enable the ignore raster test

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
2025-03-09 19:18:42 +00:00
Priyanshu 0a91dd2141
Disable the Path tool's "Colinear Handles" checkbox when no interior anchors are selected (#2339)
* disable "Colinear Handles" checkbox when only endpoint or its handle is selected

* small refactor

* ignore endpoints when calculating multiple selected points colinearity

---------

Co-authored-by: indierusty <priyaayadav@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-07 21:50:52 -08:00
Keavon Chambers c4cf47703a
Tidy up NodeNetworkInterface, replacing &[] root network arguments with methods for the document network (#2393)
* Replace `.selected_nodes(&[])` with `.selected_nodes_in_nested_network()` and `.selected_nodes()`

* Replace `.network(&[])` with `.document_network()` and `.nested_network()`

* Replace `.network_metadata(&[])` with `.document_network_metadata()`
2025-03-07 01:33:24 -08:00
James Lindsay b171eeba84
Add tests to the Ellipse, Artboard, and Fill tools (#2181)
* Add ellipse tests

* Add tests for fill tool and re-enable some other tests

* Code review

* Fix Rust crate advisory

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-07 02:13:15 +00:00
Keavon Chambers f1160e1ca6 Instance tables refactor part 2: move the transform and alpha_blending fields up a level (#2249)
* Fix domain data structure field plural naming

* Rename method one_item to one_instance

Rename method one_item to one_instance

* Move the Instance<T> methods over to providing an Instance<T>/InstanceMut<T>

Move the Instance<T> methods over to providing an Instance<T>/InstanceMut<T>

* Add transform and alpha_blending fields to Instances<T>

* Finish the refactor (Brush tool is broken though)

* Add test for brush node

* Fix brush node

* Fix default empty images being 1x1 instead of 0x0 as they should be

* Fix tests

* Fix path transform

* Add correct upgrading to move the transform/blending up a level

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
2025-03-06 05:36:09 -08:00
mTvare 0c1e96b9c6
Fix chaining GRS commands so they work smoothly and don't add intermediate undo steps (#2297)
Fix GRS chaining behaviour and generalise Abort to have n≠1 undos

Fixes https://discord.com/channels/731730685944922173/881073965047636018/1328281947918696458
2025-03-06 13:16:19 +00:00
Nitish Choudhary 8f7dd2021d
Allow the Line tool to drag start and end points of line layers (#2278)
* Initial attempt

* Allow editing and display overlays

* Fix modifier keys

* Handles show up correctly when layer is transformed

* Add multi-layer editing support and cleanup

* Fix transform breaking the handles

* line between handles

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-06 12:39:56 +00:00
Priyanshu 27cf1682bc
Fix Pen tool click-dragging from handle causing opposite colinear handle to rotate with drag (#2338)
fix pen tool rotating the handle of the endpoint we are extending

Co-authored-by: indierusty <priyaayadav@gmail.com>
2025-03-06 12:14:03 +00:00
mTvare e9ecdc7e01
Enable free movement of transform cage edge during skew when Ctrl is held (#2358)
* Enable free movement of edge during skew when ctrl is held

Fixes #2299
Follow-up to #2300

* Simplify code

* Change test along the lines of new behaviour

* Make the hint Title Case

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-06 11:57:02 +00:00
Dennis Kobert e7cde88c04
Fix perf regression from updating the hints bar every frame (#2360)
* Store has_dragged in tool state

* Revert tool_data inclusion in update hints method
2025-03-06 00:23:47 -08:00
Keavon Chambers ddb0c8c249 Reorganize the menu bar and add additional commands to it 2025-03-01 13:44:28 -08:00
mTvare 1510ad820c
Add draggable skew triangles to the transform cage (#2300)
* Add triangle handles to transform cage for skew transform

Fixes #2299

* Add skew triangles

* Fix conflicts which github didn't show

* cargo fmt

* Fix needed

* remove unreachable

* use the trap and rect logic

* fix quad checks

* cursor fix; no triangles if already dragging and not skewing

* cargo fmt

* Resolve Clippy lints

* Add min length for triangle visibility

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-01 10:24:56 +00:00
mTvare 37b4e3d410
Make it easier to resize short/narrow edges of the transform cage without corners taking precedence (#2320)
* Add threshold beyond which the corner point is valid

Fixes https://discord.com/channels/731730685944922173/931942323644928040/1344594798404964364

* Add missing delimeters

* Code review

* Widen the constant

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-01 08:39:47 +00:00
0SlowPoke0 1b59a9414a
Fix several minor Pen and Path tool bugs (#2327)
* code-todo-fixes

* small typo

* fixed bent_case when drawn from start point

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-03-01 08:14:29 +00:00
Priyanshu c3b01605c4
Fix Spline tool so its merging endpoints with other layers happens immediately, not after canceling (#2319)
merge endpoints on point insert

Co-authored-by: indierusty <priyaayadav@gmail.com>
2025-02-27 02:53:55 -08:00
Priyanshu 674db97dc4
Implement merging pairs of {paths, splines} with the Pen and Spline tools (#2292)
* refactor

* impl find_spline function

* impl merge_layers() to merge two spline layer to one spline layer

* impl merging spline to another spline which are not in the same layer

* impl merging of spline with path

* impl merge spline start endpoint and last endpoint

* fix naming

* fix handle transformation

* refactor

* fix merging with path with only one segment

* refactor

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-21 17:43:49 -08:00
mTvare 0004bbb14b
Fix transform cage bug where aborted resize/rotate after drag is used for next resize/rotate (#2308)
* Fix the said issues

* Replace numbers with consts

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-20 23:32:40 +00:00
Adesh Gupta cf2a071fb9
Make the Pen tool extend an endpoint by starting with a colinear, equidistant handle (#2295)
* Fixed Pen extension having collienar handles

* Reformat a little

* handles being colinear for GRS

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-20 13:42:10 +00:00
mTvare 38e542e6c0
Fix regressions introduced in #2282 with the compass rose feature (#2298)
* Fix mouse states and priority order of operation

* Add metadata for tampered transform

* Add comments explaining details

* Improve comments

* Move out of bounds checks into rotate check

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-20 03:04:41 -08:00
mTvare 90a8036c47
Fix self-chaining of transforms; fix compass rose getting offset when rotating a layer (#2296)
* Fix self-chaining of transforms and compass rose under single layer

https://discord.com/channels/731730685944922173/931942323644928040/1340632846863175702
https://discord.com/channels/731730685944922173/931942323644928040/1340608972071243906

* When not invertible transformation, do nothing

* Fix overlays and compass control when can't be visible

* Simplify selection logic in compass states

* Show compass only if it was possible that it could be seen before dragging

* Prevent resizing line objects

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-17 04:28:33 -08:00
0SlowPoke0 e444785301
Make the Pen tool use Ctrl to lock the angle of handles such that they maintain colinearity (#2284)
* pen tool feature and other minor fixes

* ctrl done,need to improve handle_modifications

* completes collinear and ctrl for all cases,need to refactor

* more bug fix need to refactor

* fixed minor issues and refactor done

* Code review

* minor bug fixes

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-16 23:41:55 -08:00
mTvare 687744d999
Improve grab/rotate/scale handling of pan/tilt/zoom (#2285)
* Fix P and G

* Fix (R, S) x (P, Z)

* Fix (G, Z)

* Fix R overlays

* Fix S overlays

* Fix (G, T)

* Fix last 2 fixes

* Fix mouse issues

* Cleanup

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-16 10:58:58 +00:00
Adesh Gupta 4fe3462af5
Fixed minor issues related to frontier selection visibility in the Pen/Path tools (#2291)
* Fixed issues

* Get back selection when abort

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-15 01:23:48 -08:00
mTvare 70b4beab49
Add the compass rose translation gizmo to the transform cage (#2277)
* Rotate pivot and squares to orient along quad

* Add compass rose UI

* Add compass rose functionality

* Refactor code and polish things

* Fix UI

* Fix crash

* More polish

* Rework arrow to use different selection method

* Adjust for rotated layer and show when within cage

* Don't show when other modes are possible

* Fix glitchy compass

* fixes

* fixes

* WIP separate pivot and compass rose (not compiling)

* Complete file moving fixes

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-14 22:29:32 -08:00
Sidharth-Singh10 e44c460cf8
Implement initial infrastructure for the Spline tool to join itself with other splines and paths (#2269)
* merge 2 spline layers

* merge path layers with spline_tool

* merge path and spline path with spline_tool

* handle line layers

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-13 02:43:00 -08:00
Priyanshu 2d90bb0cbf
Add upgrade script to convert "Spline" node to "Path" -> "Spline from Points" (#2274)
* write document upgrade code to transfrom Spline node into Path -> Spline from Points

* fix only connecting to single output

* shift position of newly inserted Path -> Spline from Points node

* refactor

* remove all old Spline node code

* rename Spline from Points node to Spline

* Code cleanup

* Update the demo art to natively use the new Spline node

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-12 23:45:30 +00:00
Nitish Choudhary 95bbc95606
Fix scale transform being applied when drawing shapes while zoomed in (#2286)
* Nothing works a.k.a. init commit

* Everything works a.k.a. final commit

* Minor change

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-12 13:06:15 -08:00
Keavon Chambers 7bbbf7fa7c Add icons and tooltips for the previous commit's feature 2025-02-12 01:54:30 -08:00
Adesh Gupta 20a5f71bda
Add Pen and Path tool modes to avoid showing all handles (#2264)
* Path tool only show frontier overlays

* Implemented all modes for pen and path tool

* Fixed formatting issue

* Changes in selection behaviour of handles

* Selection toggle only on drag not click

* Changed comment

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-12 01:30:15 -08:00
Keavon Chambers ec8c8d6485
Polish and add aborting to several input widgets: no Esc closing parent menus; color picker axis align; repeat on arrow buttons (#2276)
* Remove color input outline; reduce antialiasing compositing artifacts in color widgets

* Rename ColorButton to ColorInput

* Add features and aborting to several other widgets

- Prevent Esc from closing parent floating menus when aborting
- Fix missing icon regression
- Gutter resizing abort
- Color picker aborts, Shift axis alignment, improve click/drag behavior for gradient spectrum
- Scrollbar abort, repeat when held, fix directional arrows when viewport is zoomed
- Number input abort, repeat when held

* Move ColorInput into the inputs folder

* Fix tiny logo
2025-02-10 05:46:41 -08:00
Keavon Chambers f13efd2d06 Standardize increment snapping to use the Shift key 2025-02-05 03:23:47 -08:00
mTvare 4de65c292a
Further polishing of G/R/S visualization and features (#2243)
* Further polishing of G/R/S visualisation and features

Followup to #2229.

* Begin typing only if constrained or not in G

* Prevent adding empty group in R mode. Order fn alphabetically as was before

* Always show typing hints unless can't begin typing

* Fix one frame bug

* Add cancel and confirm groups for GRS hints

* Fix inconsistency in call increments, snaps

* Use top/bottom left/right methods with quads where more readable

* Fix inconsistent use of narrow/flat

* Add hints to transform cage

Fixes https://discord.com/channels/731730685944922173/881073965047636018/939265895509925898.

* Rename some hints

* Fix scale radial behaviour, grab constraints and local edge orientation

* Fix not being able to remove the whole selection with delete modifier

Fixes https://discord.com/channels/731730685944922173/881073965047636018/1336221441716391937.

* Fix compiling

* Fix crash when single point bbox

Fixes #2267

* Fix the same crash in scale and use better name for bbox

* cargo fmt

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-05 02:57:47 -08:00
Nitish Choudhary da752e5324
Make primitive shape tools no longer draw transformed unit shapes (#2236)
* Line tool pt.1

* Line tool complete

* Fix hints

* Rectangle tool

* Fix bad naming

* Ellipse tool but cant get id

* Fix line tool

* Polygon tool

* Revert unrequested Line tool keybind change; code review cleanup

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-05 02:25:07 -08:00
Sidharth-Singh10 b60af758a9
Make joining path endpoints across layers work to merge the two layers (#2245)
* move merge_layers function to graph_modification_utils

* merge_layer before segment insertion

* Tidying up

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-05 07:25:54 +00:00
Adesh Gupta 12cd0c33a3
Fix copied/duplicated selected layers getting misordered (#2257)
* fixed duplicates ordering issues on alt drag

* Maintain order while copying

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-05 06:59:11 +00:00
James Lindsay 1f836cd2a1
Add support for skewing the transform cage by Ctrl-dragging its edges (#2251)
* Skew select bounds with ctrl

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-05 06:11:59 +00:00
Priyanshu 99a141c2e1
Fix shallow select mode not allowing a Ctrl-click select deepest if the target's ancestor is already selected (#2247)
* Fix deepselect with control key not working when shallow select mode set.

* refactor

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-04 21:39:40 -08:00
Utsav Singh 0f03762cff
Make the Select tool avoid updating hints just when clicking but not dragging (#2248)
* make Fsm update_hints function borrow tool_data and update individual tool implementations accordingly, use tool_data in select_tool update_hints function as well as add a UpdateHints response when the pointer moves after the change from  DragStart to Dragging state

* Also add for selection box drawing

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-05 04:45:57 +00:00
0SlowPoke0 41ee1cf8bc
Improve the Pen tool's colinearity and equidistance controls (#2242)
* basic implementation done now refactor

* fixed overlays refactoring need to fix colinear(update it)

* more_refactoring ,only toggle C for grs to be done(if required)

* cleanup

* cleanup

* more formatting checks

* refactoring alt fixed hints fixed

* code-review-changes

* path-tool-tab-fix

* fixed bugs

* some refactor

* fixed ctrl_snap

* added lock-overlays and fixed grs bug

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-04 19:15:43 -08:00
Adesh Gupta 133d872a9f
Fix Path tool issue where the selected points could be dragged from afar within the layer interior (#2260)
Fixed point drag from inside shape

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-02-04 11:32:56 +00:00
Priyanshu 6d52151d60
Improve naming for variables from the lasso selection feature (#2244)
small correction in naming
2025-02-02 00:43:09 +00:00
Priyanshu 6802365e14
Add lasso selection mode (#2235)
* add document method to check intersection and insideness with polygon

* impl lasso selection

* impl lasso select to always add to selection

* add hint for lasso selection

* fix calculating selection mode based on direction on each pointer move

* fix lasso polygon lagging behing mouse position

* add overlay to draw lasso polygon with fill color same as quad

* fix comment

* change removing from selection key binding from Sift + Ctrl to just Alt

* impl Alt to shrink selection for quad in path tool

* refactor rename SelectionType to SelectionShape

* impl lasso overlay for path tool

* impl selecting anchors and handles intersection lasso in path tool

* add keys hint info

* fix converting lasso polygon to closed subpath which is has less than two points

* Code review

* impl preferences-based selection mode to the Path tool for only for overlays,

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-01-31 00:37:49 -08:00
Sidharth-Singh10 f462963a36
Add joining of path endpoints with Ctrl+J in the Path tool (#2227)
* feat(path-tool): ctrlJ to join endpoints

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-01-31 05:43:44 +00:00
Mohamed Osama 86f09be0ee
Group layers with Ctrl+G into independent groups if they're spread across artboards (#2239)
* Continuation of first attempt with unmerged PR #1992

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-01-30 20:27:35 -08:00
James Lindsay 5a8eb9dd1b
Make the transform cage resize about the pivot when Alt is pressed (#2226)
* Change the pivot behaviour when resizing bounds with alt in the select tool

* Add scale factor maximum

* Fix bug when encountering snapping; tidy up and comment the code

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-01-30 18:07:40 -08:00
mTvare fb7eae8f02
Polish the G/R/S feature behavior, visualizations, and hints (#2229)
* Fix GRS overlays bugs

- [ ] Another change: when typing values, we shouldn't round the number to 2 decimal places, instead it should show the exact number the user types, including trailing zeros if the user types those.
- [ ] For Scale, the solid vs. dashed line that follows the cursor is following the projected location of the cursor onto that line. It should not be doing that, instead it should be displaying the actual scale ratio. 0 means at the center. 1 means at the starting point of the Sscale. 0.5 means half is solid, half is dashed. Notice in my video below, I'm able to make the solid line's end go all the way to the center, which should occur at a scale factor of 0, without ever having the scale factor even go below 0.5. Because currently the two values aren't related. Furthermore, this is necessary to visualize snapping when Ctrl is pressed and to properly handle slowing when Shift is pressed.
    https://files.keavon.com/-/QuirkyYummyGrayfox/capture_38_.mp4
- [ ] Implement integer-value snapping for Grab when Ctrl is pressed? It should work whether we're freely moving or constrained to X or Y (but still mouse controlled; Ctrl doesn't affect typed numbers). So when Ctrl is held, we shouldn't see decimal values. You'll need to zoom in past 100% to see decimal values.
- [ ] We don't enter G, R, or S mode until after pressing one of those keys and then moving the mouse cursor. It should happen immediately upon pressing the key, before needing to move the cursor.
- [ ] The hints need to be updated to work dynamically with the state of global vs. local X and Y constraint, and include - negation, numbers, and Backspace if numbers are typed.
- [ ] In the Path tool, we actually do want the Rotation to start from the direction of the cursor rather than the local rotation of the layer. So if you can undo that change specifically for the Path tool, but keep it for the Select tool, that would be ideal.
- [ ] When G is constrained to Y in both Path and Select tools, the number label shouldn't swap sides based on moving the mouse left and right offset by the pivot-to-start-point X offset distance. Alternatively, you could keep this behavior but make it swap to the side that the mouse is currently on (removing the pivot-to-start-point X offset from the current mouse position). When solving this, just be sure you don't break the correct behavior for G when unconstrained to an axis, since we like how the Y component label swaps sides. Please also double-check that you're not drawing any extra (overlapping) overlay lines than the necessary 1 when in X or Y constraint mode, or when X or Y happen to be precisely 0. https://files.keavon.com/-/EachWeeArcticseal/capture_39_.mp4
- [ ] Remove the bottom-left viewport overlay labels for the G/R/S status

* Remove bottomleft GRS overlay

* Fix backspace minus

* Implement integer-value snapping for Grab when Ctrl

* Use built-in coordinates for translation

* Show the exact value in Typing including trailing zeros

* Make rotation overlay start along the cursor rather than the local rotation of the layer in path tool

* Properly handle slow down and other effects on scale

* Start the transformation overlay immediately rather than after first change

* Hints for typing and global/local axes

* Prevent drawing overlapping if X or Y is 0

* Fix number being replaced by - when in negated transformation

* Fix fixes

* Invert scale delta in inverted mode

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-01-30 15:29:17 -08:00