From 021aa20a9001f0eb81103e3d7aab438774fce84d Mon Sep 17 00:00:00 2001 From: Rique <97712131+Riqqqque@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:08:53 -0600 Subject: [PATCH 1/3] Polish restore reliability, performance, and interface --- .github/workflows/release.yml | 30 +- CHANGELOG.md | 46 + CONTRIBUTING.md | 3 +- README.md | 20 +- docs/assets/windowautolayout-apps.png | Bin 79135 -> 202053 bytes docs/manual-test.md | 31 +- docs/release.md | 18 +- docs/troubleshooting.md | 15 +- docs/usage.md | 38 +- examples/windowautolayout.example.json | 29 +- package-lock.json | 657 ++++++-------- package.json | 4 +- scripts/install-current.ps1 | 11 +- src-tauri/Cargo.lock | 1116 ++++-------------------- src-tauri/Cargo.toml | 7 +- src-tauri/capabilities/default.json | 7 +- src-tauri/src/commands.rs | 121 +-- src-tauri/src/config.rs | 270 +++++- src-tauri/src/desktop_guard.rs | 371 ++++++++ src-tauri/src/errors.rs | 2 + src-tauri/src/launcher.rs | 86 +- src-tauri/src/layout_lock.rs | 237 +---- src-tauri/src/lib.rs | 150 +++- src-tauri/src/logging.rs | 5 + src-tauri/src/models.rs | 43 +- src-tauri/src/monitors.rs | 16 +- src-tauri/src/performance.rs | 153 ++++ src-tauri/src/processes.rs | 53 +- src-tauri/src/profiles.rs | 689 +++++++++++---- src-tauri/src/single_instance.rs | 92 ++ src-tauri/src/window_actions.rs | 150 +++- src-tauri/src/windows_enum.rs | 60 +- src-tauri/tauri.conf.json | 14 +- src/App.tsx | 154 ++-- src/components/ErrorBoundary.tsx | 44 + src/components/Form.tsx | 14 +- src/components/IconButton.tsx | 7 +- src/components/MonitorPreview.tsx | 14 +- src/components/StatusBadge.tsx | 10 +- src/components/WindowPicker.tsx | 35 +- src/lib/api.ts | 42 +- src/lib/helpers.ts | 30 +- src/lib/types.ts | 24 +- src/main.tsx | 5 +- src/pages/Apps.tsx | 296 ++++--- src/pages/Dashboard.tsx | 217 +++-- src/pages/LayoutEditor.tsx | 42 +- src/pages/Logs.tsx | 19 +- src/pages/Profiles.tsx | 78 +- src/pages/Settings.tsx | 192 ++-- src/styles.css | 545 +++++++++++- 51 files changed, 3665 insertions(+), 2647 deletions(-) create mode 100644 src-tauri/src/desktop_guard.rs create mode 100644 src-tauri/src/performance.rs create mode 100644 src-tauri/src/single_instance.rs create mode 100644 src/components/ErrorBoundary.tsx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c26c8e1..2d9cbad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ on: workflow_dispatch: permissions: - contents: write + contents: read jobs: build-windows: @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Setup Node uses: actions/setup-node@v6 @@ -41,6 +41,15 @@ jobs: throw "Tag ${{ github.ref_name }} does not match package version $expected" } + - name: Validate distribution license + if: startsWith(github.ref, 'refs/tags/') + shell: pwsh + run: | + $license = Get-Content LICENSE -Raw + if ($license -match "not been finalized|Do not redistribute") { + throw "Public releases are blocked until LICENSE contains final distribution terms" + } + - name: TypeScript check run: npm run check @@ -86,14 +95,27 @@ jobs: src-tauri/target/release/bundle/**/*.msi src-tauri/target/release/bundle/**/*.sha256 + publish-release: + if: startsWith(github.ref, 'refs/tags/') + needs: build-windows + runs-on: windows-latest + permissions: + contents: write + + steps: + - name: Download Windows bundle + uses: actions/download-artifact@v8 + with: + name: WindowAutoLayout-Windows + path: release-artifacts + - name: Publish tagged release - if: startsWith(github.ref, 'refs/tags/') shell: pwsh env: GH_TOKEN: ${{ github.token }} run: | $tag = "${{ github.ref_name }}" - $files = Get-ChildItem "src-tauri/target/release/bundle" -Recurse -File | + $files = Get-ChildItem "release-artifacts" -Recurse -File | Where-Object { $_.Extension -in ".exe", ".msi", ".sha256" } | ForEach-Object { $_.FullName } diff --git a/CHANGELOG.md b/CHANGELOG.md index ee9f1bc..8602393 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,51 @@ # Changelog +## 0.1.23 + +- Serialized restore requests so startup, tray, dashboard, and event-lock restores cannot move the same windows at the same time. +- Reported restores paused by a foreground game as paused instead of success, and kept the event guard ready to retry after the game exits. +- Preserved maximized state when capturing layouts and constrained oversized saved bounds after monitor resolution changes. +- Made nearest-monitor fallback compare the saved profile canvas against every connected display. +- Added safe config import parsing, schema normalization, duplicate-ID repair, regex validation, and bounds for imported delays and rectangles. +- Made a second launch bring the existing tray app forward and made the close-button setting exit cleanly when tray hiding is disabled. +- Removed settings that did not affect runtime behavior and made fullscreen game protection unconditional. +- Isolated page scrolling inside the app shell, reset scroll position between views, and added an interface recovery screen. + +## 0.1.22 + +- Removed the global hotkey and disabled Tauri raw mouse and keyboard device events, so WindowAutoLayout no longer registers for background input. +- Replaced the five-second layout-lock poller with a blocking Windows event guard for Show Desktop and game-to-desktop transitions. +- Prevented automatic and startup restores from forcing window focus or synthesizing keyboard input. +- Added mid-restore game checks so background work stops if a game or fullscreen app becomes active. +- Coalesced restore events through one low-priority worker instead of creating a thread for every shell event. +- Tightened the Tauri content security policy and removed the unused opener plugin. +- Kept Microsoft Store app profiles working across versioned WindowsApps folder and executable-name changes. +- Redesigned the dashboard, layout editor, app editor, settings, profiles, and logs around a denser desktop control surface. + +## 0.1.21 + +- Added an event-driven desktop guard that restores already-running profile windows after Show Desktop or after leaving a latency-sensitive game. +- Kept the guard idle while games such as Valorant are foreground and restored without launching missing apps. +- Left the installed app running after local installs instead of closing the smoke-launch process. +- Prevented duplicate tray processes with a named single-instance guard. +- Accepted BOM-marked config files so a valid config is not replaced with defaults. +- Kept startup registration pointed at `WindowAutoLayout.exe --startup-restore` so the tray app comes back on Windows login. + +## 0.1.20 + +- Started the app hidden during startup restore so no WindowAutoLayout window is created on-screen before tray mode. +- Lowered WindowAutoLayout process priority and the layout-lock worker thread priority so the game scheduler wins. +- Raised layout-lock polling to a 5-30 second range and paused it for 60 seconds while Valorant or another latency-sensitive game is foreground. +- Treated tray-only OpenLaunchDeck as a clean no-op instead of relaunching it or marking the restore partial. +- Kept the exact-placement and low-CPU restore fixes from 0.1.19. + +## 0.1.19 + +- Restored normal windows after unmaximizing before the final move, so Windows does not undo the saved bounds. +- Rechecked restored windows and retried the saved rectangle once if Windows reported drift after the move. +- Kept stale or off-screen saved layouts on the target monitor while preserving exact saved bounds when they still touch the monitor. +- Made Capture Current Layout use the window's real monitor, falling back to its center point only when Windows does not report a monitor. + ## 0.1.18 - Cut layout lock CPU use by only running full restore work when managed windows actually change. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7439cf2..17b868b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,8 @@ powershell -ExecutionPolicy Bypass -File scripts\install-current.ps1 -SkipBuild - Keep Win32 calls inside the Rust backend. - Avoid permanent busy loops. -- Clamp polling intervals for lock/restore behavior. +- Prefer blocking Windows events over recurring polling for background behavior. +- Do not add global mouse hooks, keyboard hooks, raw-input listeners, or synthetic input. - Treat hidden tray windows, minimized windows, and delayed windows as normal cases. - Return clear errors to the UI instead of panicking. - Keep matching conservative enough to avoid tool windows and helper windows. diff --git a/README.md b/README.md index b889df9..ae53c42 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Streaming and gaming setups usually need the same windows in the same places: OBS on one side, Discord on another, a browser where chat or dashboards live, and everything ready after a reboot. Windows can remember some things, but tray apps, delayed startup windows, monitor offsets, and Show Desktop can still scramble a setup. -WindowAutoLayout saves workspace profiles and restores them from the app, tray menu, startup, or a hotkey. It is built for the everyday Windows workflow where pressing one button should bring the setup back, whether the apps are already open, minimized, hidden in the tray, or fully closed. +WindowAutoLayout saves workspace profiles and restores them from the app, tray menu, or Windows startup. It is built for the everyday Windows workflow where pressing one button should bring the setup back, whether the apps are already open, minimized, hidden in the tray, or fully closed. ## What It Does @@ -32,8 +32,10 @@ WindowAutoLayout saves workspace profiles and restores them from the app, tray m - Restores a profile by launching missing apps, waiting for real matching windows, then moving and resizing them with Win32 APIs. - Pulls minimized and hidden tray windows forward before treating an app as missing. - Handles OBS in the tray by asking OBS through its tray icon path, then waiting for the real OBS window to repaint before applying the saved layout. -- Keeps a selected profile locked while the lock is on, so Show Desktop, accidental minimize, and accidental moves get snapped back. -- Supports editable app presets, multiple profiles, startup restore, tray restore, logs, JSON import/export, and a global hotkey. +- Keeps a selected profile protected with an event-driven lock that reacts to Show Desktop and game-to-desktop transitions without a polling loop. +- Reopens the existing tray instance when WindowAutoLayout is launched a second time instead of creating a duplicate process. +- Does not install global mouse hooks, keyboard hooks, raw-input listeners, or system-wide hotkeys. +- Supports editable app presets, multiple profiles, startup restore, tray restore, logs, and JSON import/export. - Stores config and logs locally. No telemetry, accounts, analytics, or background network calls. ## Download @@ -58,7 +60,7 @@ After install, WindowAutoLayout lives under the current Windows user profile and 4. Open and arrange the apps you want in the profile. 5. On Dashboard, pick the capture monitor and press Capture current layout. 6. Fine-tune app matching on Apps or individual windows on Layout if needed. -7. Press Restore from Dashboard, the tray menu, startup restore, or `Ctrl+Alt+L`. +7. Press Restore from Dashboard, the tray menu, or startup restore. For a complete setup walkthrough, see [docs/usage.md](docs/usage.md). @@ -75,7 +77,11 @@ More details and recovery checks are in [docs/troubleshooting.md](docs/troublesh ## Layout Lock -The lock button watches the selected profile and only runs a full restore when one of its managed windows changes position, visibility, minimized state, or disappears. It is meant for live setups where the layout should recover after Show Desktop, accidental minimize, dragging, or another app stealing placement without burning CPU while everything is already stable. The lock interval is clamped to a low-impact range, and fullscreen non-profile apps get a longer pause so games are not polled hard. +The lock button arms a Windows shell-event guard for the selected profile. It restores after Show Desktop and after leaving a game or fullscreen app, but it does not run a timer or repeatedly inspect every window. Background restores never launch missing apps, never force focus, and stop immediately if a game or fullscreen app becomes active again. + +## Game And Input Safety + +WindowAutoLayout does not register global hotkeys or low-level mouse/keyboard hooks. Tauri's optional raw device-event stream is explicitly disabled, automatic restores run below normal process priority, and the background guard waits on Windows accessibility events instead of polling. Window movement uses normal Win32 window-management calls and does not synthesize keyboard or mouse input. ## Startup Restore @@ -168,9 +174,9 @@ scripts/ Local install/update helper Every version tag matching `v*` builds the Windows bundles and publishes installer assets to GitHub Releases. ```powershell -git tag v0.1.18 +git tag v0.1.23 git push origin main -git push origin v0.1.18 +git push origin v0.1.23 ``` The workflow validates that the tag matches `package.json`, runs TypeScript, frontend audit, and Rust checks, builds the Tauri bundle, generates checksums, uploads CI artifacts, and publishes the release. diff --git a/docs/assets/windowautolayout-apps.png b/docs/assets/windowautolayout-apps.png index 680512a5655a6bc9123f1c18695e3671825deafb..0542ab47b76da78212b4cb8d1122cef89e6687df 100644 GIT binary patch literal 202053 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 z zOnvFYvY>oR0yL=H%nbMKfRDI;_C8K%osp|N0@nheI<@tFDBf#x&Gsjf$79`yg0l<= zVX#X;_QisB@I6l8jB3*A-@jLcpPyUR10hZk9rbAGMzl;(N@Se+MQJTy_*vLw{`LSq zmEre*>Vykw>k8sy3f{k6rN>|&*|?ptC;b=ID-id5V!v4h3yh}t#ZsONNQOmQKL|!a z^VJM^|4hAJI20vl8bO;@)O;e^6S}xLz_kL=L*5HUW%~P{SbT?*9fsK#;~zeuU>$~i zU!XY+8VeinVY5n#>FJfC-8hvCY;qq@hkhHa#kZBPL2bBZY@b5LNJtRS)OIcY1Cv%# znV?W_Bp5;0`1QXm$Gn*oa?|mFk7W9 zGj6L*m!4%<{O&K>U*8_UOkc|Y9#iNJx@><-2t+h2tg(*oVt;hH!b{_D(crc^$6PRw z!f=1gdiYT0h7Yg7f6)Nr0!(~2WJ|>5my60oGti2l7F|%_d&_A#Au6m0O^4CLP>`Fn zn1O-tqkxo_8G(8mHX8MsBJ?s^Ldb77fVcEJoA#v;R4Tjw2-s_023n z_8HRjJ!X*in|hinPXf2l|J6%dj4j>zi(ruueG`Yi(UBJGj-(PN zbAXnR!kzz$x!5!HxSXO9dsM=Bfi4TJk`q{O+qXgS^8|p?{?WU9Q2=DDg;%qn-YmIu z`p+QTUcY6tQLtefj$dNC{D^aRWIn5pz(u6p)k|RlwP8PQfzDj0UC8^-x@J3TC*g`W zw@jco!3535zG0SIrJ+GFHkX|cS1Sb|tVF*WlwNN{SULP|pAIT~0Kjo^vhkR!W9E%E zFEuXmB)8!MsAi*Z#cLm$d8>C)m^V1c=+Z@U5-~j4Z@OTqXQ&QZts_{I%^i8-9&0c~ z)0$i9`{%gZi=k4m4K1@$u>S@CANKAV#?}|VpF*#}Rr9k8_5QJ5ZO@Bo*nw`p1!Jfb ze{@&kv;RPa=BP7vVOK96Ih862T3l>Ze6iCz!_09|YIP96W?R>eVDMsJvjAzVfv!a; zw}R&J(ceg_QX`|-i&tRVRO2X(WdpnVv3=zE*KDa+TVmr6HNW#{1hE29yq!*Rvq3-U zS5-6|-5Psbuzh$N<}KS$vF@^kc+<%-OKrIhYvh4aFfGJZkjLx~B;L+P0-bCCMc;ou zjO_Xjkw~*&Ym6ceWkx|Kb4-sZ`R*3q0J~!a4+C0pt`L%f-`)5aY>|i$r4ktT_zd6| z=SsT1rLSSqw`O+J9z0uvj&9zI&3}&^6MUW z82|YK#7^+(ybAK9y~?ecUkPz*Z(MUPach7Sj2t@A3}+d$1-ad9oz?aCSYLq?idu5S zJ_LUe@y;A}kr8W&{1TKxzec!v(HH*R!O2#v5x;u@v3nyvl)%=~Y4%*z?=K!Y$PV}r zJ31I^wa;4`E|ZW<*ol^hWZ2f9cvlup7;Z}q`bz%V11`3ni+`af?Y z8GxucO2#ZP!1%7kZxELR>sTXv%`p$X;{|)z9RF(#xRD=KhM^+X(ZrtSap^LaPYqrv z!SAa-uU{cIG5ybi3ZeoKI^XBb@|CD3qUUeBA-B2FOJIr+ay!s1*$y6FTJ)(gblp)E zKcy@)mN@4GFHp)hiqpUkYcg??!YA*Xn6{-{l+i=FRtP|w9JYEf6pET!l(Izv#UB&u ziQ{YuGCnfH=IUiB+?08bOG+8E{aRSG1jD}7|G4gFtVKs)=`*JKA6#iusM+f;I?+1_ znV3jl3JKNIkWy;vwW4DPLGe?UYrjSd*8@EikTc__$?_b?Hl=^vLHJjVhp8Spd%ewl zq4Upj7+HzFC3*u(ZQFC{Y~qMzOp;7W)>_Pwosf29HzE$OWUC6RS>);<-3I?~*Xy|UIdlP^nbgR*{3 zD21L3NF5ZY3QZA6hW-&p$F`7IZ*Jj4{Kk(n6qDZSD(CpnUd(V&`WCd3-oetJvDVO8 z^X-}rt16Y0zwWyYpjWcU4kl_1ej3{>DZM2mD{(sz^zNNETeyh;BmL{puLZyR4FtS; zX5UmK{OjAr4&~}0h6#GNjeGQw7S8jTtmG$cHksrOq;ok%v8B*4k!E?yE2r>-FWBD8 z_Zw9C9w!w!#TO^@xXlE_B?Hctp*>{r$P^K~>wPAxzTNt<&|v)3Xf`ps>u-R=2+)OC zZ)Q$_i%SW6{jTfFoX~&f^`y-`wc^&y?LX>0lH&J(S{abA=METYt3hY)%cNsp3A=1& z#_@uWKnoIJy$)7QEXG)^F%~4a8+I7mDw!5CUT6GZA2h19e9Qj6)^cQ*1Kbh?zlVy} z*5YZr9hrddqaw0X;~A=Fye^a3GuR(i&=^Fyv_G2$uOIyt4?~z0MzoTEH0qv7+Cq|^ zNkBmRrL#>dlsObT9MJ5lBsT|4p%!jh?ee>yqyX}mLvo3ap9?DoJO4CLCssHwWX~uG z99n{ByDvTFB~l&l{DUh0Hm%XLh&NWdvCOxfnO(0jr#w%m8qVU>nG19^h z4WF&dG&t>>3!85JSe+8CSIt`JC_K;7g{)Qr;wV6;6~FO1nkrxWo zCxCv~F~|>!mF8~jcNzo(A^hW>NgO8bMlIs9J-$JXtrHdf zLt8Avc_QRT#J;GjZ)@+{+!C>-)8Ra@mi6Z}4zP@p@Sh?Pu^(vvRa)PNuaQ#Ef-*=_ zkym`t((mic!cAoVr3ro4LrdXC`-#qT(F-u(za3kvgsD!N>VJTtlH#>pFo&0-)>x)c z_4z(L5D<`wd*AeCXe8*^ELMOsO2~9kN%)uzj=IF|Z|*O?_E-RlJY}=g{^ezC6xocw zQ)t}!T$&uBx9MqsPM1pZk|QkRrBAR+DYy8eFbU_IUjLYc4^iwzo}?uUu2=o2Ns`=O zdgo0@sST^wmUoM8U8_?T8ZIqNN?J+ubSrEgVDS}z#qWKMXJ5vcPUpb;@AemfJeyL? zMfa4sm%icmdsR(Y`@rzqSe^7kf?%!)(rbBU8_;_3wY4Kv)4zda!G>PZ(szbhQ z=Gi;fh~zSR)xMpu`X?|6$1htMgg~pK7U&dR1Kjt6eqx8GLhRRy0}-P_6)rHv6E_;+ z3YVoat>nvn3CGXvgEIF3c$;8#)MYNh$lZPM1XpR&R@4>F2L8b|&)2aLcy<=dn?JVX zcyb3iT^cjcT6-~jPD6Pg)@8unjw@peSr4*W8$PigZq{i;kd*CL5Gu6x%Gvucp@(Uu zWWqYoy`CuBBk7&SLUr^=*IMPT+@~Zn8^U{DYH~fja3ARFvyJAycvP=}qO4@gR)nAF z1S}PW8&$C-jIEv_c3m1yyYpUC zD`UK*MVseHZC|q2^=iJHh6gey6wmn{tuxI~v9?{A%C3R8gGVOZqpZmAd{D%9Wd+zo zXP9{Q#(tnorwZzuI4YZdaK?+ul#31}J|oR@aJ#4{bVZewW`|KSxi2$Q^4;5#FDWHl z;jh>@&Zz`0hV%M>WuLBkaF;bvy_2fy zXu**C@Wy0U8hbPoyI^DPG576Z4yQ!$d@TxsetS&x;Poh zvor$ATfoct*{U8U>EO^_+&(fYvPfXP&tJ1KFJo18uyxh~WGLLgoeVHbrcXPa&4(yO z%)Ymo4T!r9H)65cE;C)Y@af{r&KEHW$eM~Q>*ACc_1YF<%c2&4h~u~orxJ6i-CE}U zN+t=IUfa#7F|%K2Xr-ze`dVLqJAf(ZxdxlM{V8l>V-*GqqAjAFR^h%>R*~Z}kY@2* z?_J~Py|kJ1)hW-WB*j>ns(iD}D zN1oEs$I4xFx8X^fCAUrgE>9fF71h|;du|<}jy;J1QYtRTHu&1sH)v|xmo#_X13-Hw zcp&j^qPBYdv5wnL#clUbROXj;3^T$?QwJj6v*|2u-$s)!E3Id|#wpki#7*~GV@Ty9 z(z)%Y6G7ty|Kv91jYZ>)KbN=!qmm z?=20d4b@KOw2$p=GOk>J%z)1LB^rjIRX( zmlP5oj}r6p1*<$%`(O;_t7hlVrP*H#mxdx#7dQqSMmC}Pbo^A{4FI8_;Csq#)mR$w z%i-=f73332-&IsAO@Yn>Uu(6^ZGV~;4}ziLP-cyVjpZICpbH@6x&wZt3MRUVlOuXb z?RYYp1ww+V(Z|Dw*K7hXNnhKOln!vGFkWYz_oebZDijQMGhXX0A*T&6r*F|fQbpWP z01gMjxK-avRsHtZ%FqD+p<~kV|9bLT37omgam=>#JGZvpl;cG!utPW$k|y2LtZU}| zOOU(%UeJOS#W=`{$uSx|=*#yB6-3#p(nnwN%PmhAvj8Kl<2T;=@Dy?o5&*Luv&nwW z%=RR;iO2a48WpoeDdLk;?sOQAsZ?MXJC#tpRCao_qxRc#556Wp1j$Ln_X#-(%zbG$ z?UMLTtRlW}0kXOZY;1&)cQ%kOmXgzO5%Sj zp2_c==eh3tocI01>r#ZZ7i*3+=9qJi@8^qqMkhhfRrW>DcC&SbVyo$V4E0bu$<}*U zq-JQC@4H)+_FVp|jF|W6j(qo^^v1_GqD_-sJ*RWmyHWvfM&Vy?71U+}cW#Cc1!!_k z3Z%GZ2r~bKe^XOG2Jhpb=XlWtdPbn zs#T(gUk=6dKxbINcEWJtU=P0WsI-1)n6M1PIflNDAo=X$&8FOUgoY#RY;=v@wmT9m z?N8-MGZ-Vr-)pA%Zyi|$#$`%?k_AL8utK)XQQ2eRKP)vpVjIGaxQ*mb9}KATbEd}E?2Us&)?ZY3u^AGe2W~C% zR%{vp(a0vr=D-1`gJ9VTTYRK(Xo<%Q6?jyxRcc*Jbg2leHhw;A_rT3{l(i9}MC&ZZ z6O_}kIFIF`%X-9|V22;H`SHVMNi36{@<{V0`25vF<;VLD#CwZ49o??cr;2ttn{Z1{ zB8;Ma>7LQ@xXSp?bvYz2=a3GqHuRm*NQu}^U&S=V37*hc=cFL#J*9tkER*$Wg%2TH zVy@#;K3#j?-mCgCN+F`!#15SzLth~S)WHeW1PWjye;m@lG=mQ}th5*TIqh6Z&f_{Y z=i#$)L6r;HiLz!LH22v0y}}@aR*;h}y%hTi-gtEJ=Mv&JVzgkjIB&HMzJcHJ&#E(~ z#-lI1x@Rx=5Mf7Gv%nE`Pdc+~7i@z^tjhVfq!A(}!DY`@|8=i%nh?mzq%BhNI#eZC z-A>iDH{T3zLgp}I<@}|LjqAMc4_UTr!^x|DnEBF*Rr~D1Z#M8~`G_mft0 z+f1e}XY`((s)gLf-r$NY0Lqt;xPcRw&hNW$h}--7X+$+iA}&QnUg039zoSIV-#lS4 zK0Tuo-vcAm!8+(bCwesXPZ8iVyTrqzLFc^Z^3USkYmr^)TI&@JmiUcOciah=xe0xWsW^F*(dr=4?B5LSf`Wz9@zLjI11fv;G=9YlAH zYn@gWlIL*u>n7!kjL-Q`u#Tb;{{a$!nc`sSY;!j)7xIb@v&oP0fBl)^-J;WBIw<9$ zWumGcQ5PeJXejnsptGt=8clMj#oP&@r0|P<#JW>VJML>=-bWn`9|q>Qcuu*;E?~=0 zyv`)lUK!Kd#+WbH+F2Hh=$%Zf){#}U2vY1NXWXUhjiCpoAr`Wg9xh{=dnQ>%;+hqD zH!Tc_B3I3kO7FVnvJXF_aW=U9Ao1__&s$H;2~I$53u=g@H#`mlRL?5C=6n!DG-CE= zU|AO#lcjAu$z?WfblP?Gh}IXRXOO!me0B}=7lK#wr*j1a{rdlev+}5C)HT<9p8*O0 zf~;2lw_QQ{$0JdY_)<~-%_VFBifKx*&i*&vFt*$s|HtoHtmRt2qU%&1CS0`6s+!?L#GqdrB1ryj0Sd2~$ zbB?s@M2#Xkc`R8_(7=P$V&gK0ac`1AcVW^DSGy?UHQPWXzp@)SB-V;XURiX|igNNBqZGb~(u?Y^Upx3xnvb4CW&RwS4k2c#MOsn; zrDgGpO5`LbmZi+BGvQ>8J!WQK7L8+o4Jd?Dh-ok>kG#p#KIsxbYS;~GK$)$T7=d1yJD2@ZP?6qT0o{&ms{5TEmQ@7f`3Y~A`-KVQdX zI*SD#E*>6t51ME42H%|pD+=$6Cv%p(B0HaDDZ$UEAO1R-{mQCvUo2?t*JWf}roS6l zr2X@r6Vh~AhRI71z@5Zy+vk~V322&zX9J5Ql8tJ8uE8SFmrnHU*79@D)KY8~RX%-r zyUOCq?$%GbK+Cl#%6xeXpxD6Smy!p&r_9>b9$*Jw@z_=_b=`fBpN(s)%M$&OoxdaA*HK}ht(hs za#`l&u!J%Kccwy|Hq+J7T$5R`epPSR?Hc`f>&W{Fc~Uk}_t|Nw9H?w5A(4q+XFy|` z=jBq4RRN{)Nb3~1349ufN#7o};k+*aj|`h^CKGg1@#&Ho+EJh~H9_`exKqs4ro2I4K<1 zp1Xpi&(KGppyo2DMka{-kw+>A>Ehq z@L2qS&Bo+jTv$_JKR3~GZLC2n`Sx!3qvvsInde1b6hts&Iz5=nR<2ja{CLo;%3)|p z_tY%VL|MBc5T8z}#s1pd+&wp0#sfzMyJ~MhdY2G1D&u4EMro1uCZQ=Va`v$?v*#8q zvFay3$Es}g+y^Qn0vf(Bz1ajWZ>#e#h{*2FsIA*JlJ&1JAW{CI^WO7qGm=2!oRu6K zGzGLQ+9B*^ffo~$Pn3zw*iAqs+_|Z&e&jLWVj_+c^M)ggw7a7C(KAZ11`iYStcc_) zaR$CovTKz>bzfJ$W2+^UbY;atIDCE7Aa7J~Y9K@S{uSu~oVhcWwoH)Aq>OZE=2#PD z_3Ytjb3eX%0gg1oh6+n@hJD~C?t;93lw`Uc{QR&(En+C@vv7qL#{1>BSXdZPDLO<# z7jn&E%HI?u2tNG-yYhnR+fjPKXz_c$f}cICDk<-lrwtoTy{`t?c8?VMimA=+Ks%Ru z${*Hh@2@Flze}2apJh`m=_%Id=X%=Pr1~`$G`1FIUxvgpewo)! zXD>_g(x9Mu;$NIc6%%D&vYyCRCZR&KrMRK~ctd`!fLxEBx0DKpc%dq_4$JA1-@BqK z|7jELF)lqFddGFq5M7v&?vvyR?u9)Zlr^LC!(wo zHuFhlkG>u26MH#ViOb1*;s*%^w~-E+dWu-{tB!d41OxcI){}&?e*Hi4x;7dXFSN|q zSYGJbfDaIc=J}12z(me>%EfOrEb?oLkxxpsB)^mu9V_Z^htyPkkDjBgu~Y;1V4{tw zfZDtFvEcWUUL9HQCD<>>;EMwBgl_}MLT`RQZb3X6kkHn7g+_sxYC)*gHnW@kjqmyM zl>bMo)~D1Kwr`@6hfe;w3_8D~_AF~S&HlD4)4_CBHq%FcbHi6Zel6BzIsG?oR{am} zs~(=E>%5F0t$K_v;J+M&*r)~USK-*PC=3VI}RO(O`UfHwVbjO9K(@f!v0{zMWe4>8d7a=J zB&oilk;svGRT=WWH-N+JL}u91b(Ixd$T*muImuIH8$N~D*J?j<&A%6$WrP#+>GVir z$IswC9FRY6MM5nVb?h=)p;X{^xuh!iMO2!$@KYUWX}Px20@jS73?1pGw>01)>r>)FxEAa9S1? zfuB{mNy|HwES`yd(8qV!9yh#Tj;5WpM31Z5LpPvNsPU`{U)HmtVPH{kTda|*dW?TiVQsI7x?pYLzxeZ>c)8bm=-S{fLP{?HV}qZ9*p^D^23vMsYh4Q?^6 zX_=w2?F)(eE};FtlK_gG*ve&2(Zp5KgM0K=>9h~)SL_BxQ-VoHA%l^EEDE+cmf zK$%1Y538D{RDc6L8(mbjiB_!T%k)WvAtnYJZ{_S(|Ne*k&|8?EJ4FqmxY)N5Oz|!%~N|t~UY%o(V6| zAUr7gC9N{~!t&(fj{%_G4?24RPgniz?$#w$bHA7E$Shp|4zgQmF&Zm z>|rAqvx%sd%#pg18dUGdo=LQ~wtL18$^C#@(M&{*_&I(O%5K5tJ&*wn)LH~wcHqHd z!%G8g=5Uu8EfXF3ca2+KdZUp^AwA8DqT?0zbjWao_Oh`yST|*nWx%a}$rvhA2#FMF zB2WB1h$3MoW@09I_JLe5VijEBF9j)q2BdihW4Kx4SX|3-n3GA=aKv6MNRQ&;=i<>L zZYlTS5D21NUtV@qrj_-HKI# zlp~qA1|0bG^;YOE9AVG!ll4Hfp+fQT6ZzYbUdyp5)PSkvBB7{3S!0Q;FlJGPq5vIO zNG--v*0W&p^ZRvTKl@7=OG&l?>6~UCbb;}fU8#V3v(Pfqdf8%G53K7)gBJB4^EAni z+l4LfK$k0*P~<+O3q)x1Gl{krp{S9q7KZ|R2-dXgU<3o|9)9Q{W_)$<0Tu?!fjObz z?-S}I7aBq;Xl52_vp=H3r%i1boX4Jr~+tGgH2$r}|~%UfJcbCqgDh?p;8 zAs4@l$c?eTLcnovbfp6;1pP?RYc7NY`Kj2~DFv7L%JQN1C3JaVUTmbsXdP&FBMwfP zK3p&3P7YVYLq(PkI{cbQPCK_{Sb@0tZ?8%kZ^5v_XrfCVn!q4`RYwFL_)#q`5^F70 zpE#@V?ak&o!Gj*Sjk6H82;_m9aZS8`9sGJX{-pTr+wfzJA@bBO8ucC#3bMt7F{SpXxxib|O?>F=_ zEN*cI2jsP6N){5((|`}vcE0$L)Q^SFTZUF?M9ock{73&7ZA|6B$WnYtxB~SVN`HX= zbc{BCTHk0hcdV0Ad}w$=X1O|)w{$Wg>y?~J|rEDUI$zEP%8bJ;NzqMqO~ zvE+Nhk&_x{-H?AWGUVdwaI~9%uqa3cKI1wT;x+78F7+wDSAVVge!Gv9=`*^2*#Y+4jz!C9{#Z>)~%E)vb_G*%Hkh0PSuyE&9sO%$lRYE;S z)1u8P67gvWtZzo47(W>n$p}N`v54}lr}r>(aSIX!%RLiut%<90N$hxsRUgPa$ZNxv z1z6AIw9FV@;_5R|=gDrHk{6Oq?+vMI$`Ug{#1V?a&GB zkQguFt!wirKie3t(9F@K(JMItt@?;nG^s&3nD>&#*MF!#|X^ zY{k%dWO9kn3a%n=__ia%J<2cnFb*bWS6@to?ZuWaZcw}$^B6p<3wnvxIJtLd-)Mm%Lrr~=PEuhnQ3R4_EX&~ zBgJ>2m{R0>h9{8Rq|5lCkE2gWuVX}+(ojY~!#sS)cX5s%FyVbHJTu-~$aZ`DKAbYP^edP^LW`p%OICn1?G#U+=s<$hK zrJO)flC&kRNYE%}r{;qfH`-rW^%oIkBYp1AT?13r{HPu^20ryzNKaA5b*$5zw~Urq ztKC)m$Li_yu2^9xp^!lDfJLQG{~x1>BB68I8h}g`GVwj7=kxiqO0`|PZ&d9~Q6j2N zsXIOFJ+wrUpH0U2l1OfvZ7Hm~b??!y*_>bf=zX=jQqAt&t^TS8lfvF@hm(=BE)RK$ zR;IUv0DbDiZDNGX5{knUf1L^WNL?Q>n^coizujkXYu;?!P0LrXIQ&k({qE&>IB^M~ zXmob+NStxx;Y31nFt(e9i)@9UA~y=^8$U}OyI-%23)2`_rw#chALD!yq*pS-Fvp=G z>*q)4k(i1i5~T@|kW22I&@k8P8Mvm|V*fsllvQRTg^j7WKyfqI6LXD5K8{6ID*HM1 zJcjG>Y7eTXBOr^{>t~OV8QHbYiEex>f6%4Xuj>my`xPLA&~F@ubC{2)`c03AfQS4( zGC9(^N1`VciRB0y8~@}P9hFiklE@#K@>T0dbSs(E-V`#VVDcL!?<-H$ZP|Mie(ZoJ z<)UCpH5Qnkf4qj?`xL&4(#s%h+RjGB_#&QRK$)ANWAQBw2y)BUvSRT}c(G{H5ScXD z9ORV=b4LYb7iFcv7SC23edo|G;WBFoWCrF;RlmU)R!giZ%SV*k?L1g6joQr)3ib>) zm$q~$_O2kJo*It865k}}`%PmNEj#h*iMvnS*yE;d=e!_d(elweZeKdqcQtLcw;g)5 zVmRmcmBp7$2#{Z?JSnb!DruLuIn>QV-Lk7ZLTpN~E+H!rH(YKK?o7OCD8okn}|8EJd5o*%W zHo23EK#TEY4(i?V($g#Er&jB3;gfli28(cR-aI_;8)uFk`=1lwEWsG4@DX( zfHgRU#dP`A44YR=f^ZrMfyc|3v_nUzIFOQyjEtvsjq}SdY!4)%KdmUwIE&2{+!!L* z*yyZkua-tld3XD6TV;w7iE@N=4dfn|6?S+Zm{)30e$Rw52(Y=L{uH%@;=)o5;P9Px zD)w^-ZgC%!@AdX$n#D%2g0wMUX#(|*$2v{_3uO&H#+Td-k6ueKq%jq75Btq5u-vPG z{TRB%a#}mydbRZ%LdmH|6bnd5_b19PWM3k08_1?2uVAy$#3xxFplxv1PlSiFG!eO^ zfD~q>rOV;#i`@)KHF$I-+C!KlDxpD*PV2EkQ1RMrfvb)Nm9!t#Xt+I6wgtk_Vj17d zQWk2UHF|N>kQ-pxNZ=$%QH4>tP|GgR04J(=ONizN5|IGXFUlKk2CPRKxP}Lu+vZwS z$p2maSdxA~`l3y|W48IR05o}s+uV(gjID|0ZeGo!u9r^>I$r+0+^!uoY^=?hL~`Yn zcyqMVpgI9at>d&G!h(IJl|yB3i_NZ003S-}(4jI0EjZ26rgO=0=WpOrl@I_phzH&5 zyu+mP#&|7{1r~h=EsC1xi7fBfgna()fWYD_7D(fm^WQMcZN^whc@3`|MX~iQpJ}zd zY~(`E;Qag>0J#X3;jdXP0nftja3@7EXr!j$2l@6Os$wK86U*W2f9A8VK%r3|>41Pq z2r*D-|Cwcoo{y@o$qu7=8!2LHhbZ5b8B70xrN6ey|5%2hXi5QEm4pVNFv50oB%f_X zkDfr~YSA<3$~YwaMN?YymzmsZ{>r`(aLPsB*`*feTh z?YiK(afkD*d-HZupfrde1ygygn+nyNpv=B(%wY$RFN37*zQsm@f@Ox(rKjK($2fCj zqJ+4pWs0ZqMM^imUJ*7B9d}+lu%WKgG^&?0ALk9|YEBqiYap>nTIT}YRWkdsd87t* z<5y*^Zi%`1Kjl`F(59lQ$zjvA*Nem2B%!>a)RxSJVEnwt&RWLt%)%?xf>SfWkz4H7 zK6i~J?;+5*RxK2h*w^;9dp<0$i>Z`U=@Y#EB3mMH$BwC=Ir30NR&gvUW~N}kOby4l zG1uj`R!TpS6@36!{S*cyY##E#0)>rH+5yMkQ9HWTky&((AJ#lTdpiXiCGW3SM-}H# zisq;yW+=pR`Yz+4@<2?W`eKX#znB@|CjTFZ%d2YnYQiHs!sYURk3x zAHhbO;u3T14U;-jM4MtY>xMMR#ma~$YD6R@W{;A_y(ZP5rV0lI4Pr-ly?yZ+(FfxP zQCRY9ZYaDS>fLb3)INaRFyOo^Vvt4k0B%_QRKC6=B0^P<4R$)PjVp4K@$&fo7KIx` zXl1&2jIYt=uU1qYEqj|t9&&yYy^hHg4f;((lIOQP?cX;^)I6u4Y~r)$i}{+=X7w&O z5h;9lBDN(mGA0wtnlhpfVCM1)x&H`zV-|i3%#v+7tMh}p!%`&DD!+M>4;VG`o9lR= z^s@|*R3$d=Mc2Svr~c&8%SCsxsjD{5QO}2*oB%kf^&GW&3ayy?APMY?@egJ*eb1ef zPAy53VT5((^sS;s>=((g2(7LzRexI~k3f416nF_XcH*%tA!X@fl+Q1LL_Q$}2@h(= z+hc*0LDSp`8x@9DTXx;O5{9B)2ZoLB1NKA?df02QBO@gzYezw2;lxBWf-iivZ6_yW z5K1mc$g*cAN0i9JR*?d~ax zlfvd}>IR$jyF=YKVHO0|vJ$}ws9c2{+l`^gBj~CIS#3v3f_iVdj3UUbrhh+Y9gO)b z={fQ9-&0s+V)N<&fUMhJw=#VdQm5sr$F_POlhF(WxT(^{PE5}acRoiGc<&4J03MR7 z-xXXwl`fz;zlx60zjx25(V=6JXr;Y&@$$dN=}}b%pD|jK8((fqcF&tmBT%-yTs7^D z0k=x~?5!~A5LD(nc8*MEhH3k!Wxe>vc>0piBK{&(Z0>^w>KO*w#}S?FJIEWz3ekYw zG+~C>rJjk6Geum=>9A+YLZ{U9QvsVC`dn<~8J5a{XqR@65VB8|58*ZX-qt6$OYdjg ztvl4&MKDN9tGgPqJRei7myI%0w5VlAf&#(0&02UeeZ{bb`-PV#8|e^0Z8W9I2=3ys znBEobVTWxEh|t?UBj+{v02zT{ zV}mFk>Qjg1mf~6Q>0otMlN9vR3izK*NGXC&YssLWCwEL;g(c#epbZVQtAo=8dhov& z_Qy8~FDqkK{R6d$u9Q(8k#FxydEHEHMwd*u&iP*aI+Kd@*^@wlEdx>!ZfeV)qjzCvC}Qr`Y_7-0ZQa|asuFniW>0ki9iM(F>!K6W+om( zU>LKhs;CKH@IAP=k%z=(G{-9$cyY=R!oLW6B1TBoQ_E(x^k!J@AIZ4z07i$W*yrYD z)8^N6CDQ))Unl3^Zr>6B)Uj>c+tZn93Qp87Y+n3Uz!ac*sO=;`-AW|NKvvtx%@enX zv&aBjA3waTK}J|e1)Cw~alH$8J+~udDI35f=1WF8Eh8vuq;q4T&?nYlJhkSrP0>jsHQg^{Vv25(E*ZPtqSeX0#eGm(0i6^urfow#N^9qu zo2`|)Z~s)C{YIh)6_dYYM))l&pi#9N9!Uc`(n%x(f45G|K;7^v&r2p56PG%qm59nD z=CJBVTqwu|Y`qR&-BkY2AYK#%3|Ab^UEu>LY=mBE&66gk7%5C}s0)x!zZ}h}5uXWF zNNL#u=H9vzTHm0;nGd(~#;I!bW z1fU|SA74`&IWYkqQE{u7o-wUPvfcO4gaaoQcNJzkWu3W7Ya?d!#QvALXcpRYzdnky zZm}UqYF2Td5^v%}N+gF6Gt{L5U9^loK(z~u7VHKt_^q$28aNk$0(rScOfzUD3vjMu zBC{^urp#RO=a3sekI(81_$anEu%LLw@Dq+T#E`g{O zn<&Fp6(+$s=$LeS_`h1ue?lT-Gd8tgNZma)>d*gD3nMWZyFW%yy(jlq`6I6=o`w?r z7SU)C>Ez4S_+1R%*!OMTu2!V`n>kY1w#Oar0qvzJGQEff0P%Lh*Y8>ofaQvYR9{e zSsOodT$UYsaN3kRGSyp;9XoAs=yk_@C)`QJ$4m2!h#~KPTp7>J(_hc^3jJqm%fLcepMh~CQL&Q$pTIq z!T(}>A2^YBTI}Xhft!$p;JbgoGtPv!i$X(K@Ek>Z`lY?Mk+)SkOb+_ zr%6FQ5ifvyrwSR*;4B`aS4{J710*ods=Oqs=Sr>lRnHR2V744!YCz)CNF7fG zKQrOI3GjMW7J&``7YmjRBK_@GOE<3g4J%V@2$f3x_kGyBia3oMJrSeG1KS2t442d2 z#JvVy)k%2G`R!fxhl-$hxSp_;DFrBiKaU|W=kfuqZ4@24)O|!1`Qt&&&vm4 zDw_?zBIB5(-+27LN;~)sIYaz4Es0!MEF9v5=*92d>!n9_iM2jot-V3leW7*p`!RHXQT2(pVLl4VH0Lc3060-r^KeiO*Qc z+Tup+Py_WezEvt>RaIIX=l9m&bhG*$d9tOA7NLOuugbU$Iz3g=$!GiciWKb?kZZ9y{?Mt~ z0fSpXn8T(_O8Z6t!Rto9D4}spyy!UT`gf}LP2X8CPurcw{@dp=uau|Hl2z^5tex}w;poRWg;E8 z`6Dan{F-N6*qepw^5C#~A!Mn$92lU*S%jQ74Yf5p{lkbd7-Jb9x;^L~db{6Q*m`{9 zn|ZD6udciPJ-GF>|2*X8s;Ru?bj(%qwq@NSAox5ik71W;Cju?%oy=cG;q>Q5$c!=4 zR#B_$@M_!uVff)UI?a;X#|b6_n-vnfK9L2RgZgF8C5SRPN7s%R6sI)LOr$3Hz@AMK zY~fXG!Er%eQFSZQapSQZu<{KxfLHB(MK3$mWvh^yVwIVDa>+Fd#{NNM3#iKYJ@)-J zo>N${25=1v=C=I>nnE4`^NCkYE2)1Kp?CD`&?i9}C8%;0aC@b!Nx?z*_6C4#Xp*OKNoAp~suy}+}3IOMM-I``Q5|*MWltN}`)Aq6( z6Rt;LCoK zO{?y~meV~RDt+VDfVuOKgFL^+7m26ux#!r7E1H^lZVpn)L$0%~PH3%VKgxzH7UBE0 z-90zII{d<_VOk-9IzFC3?|<`!r{&}g$mA+|H;a+wt%qILx&=c_$_Yz9Y%~4uz+mr8 zx~6r|{srrxFZ*||cME7O=bF&1lr)f28X0y8c!<6nFJw1Qg}5-Px0;ay6dh&N>1v`arfbh^WG^OQT} z^y6V;wTBh?XB}z(e{^uI@Y#2CPFNfu2@g8nVGVx*8_>IW<{mGWSw4EbE2`(ja#n*V z=jigKuLFwCz7C+jkknZ7FJb*$6m9d~p08WD>nzev!jjvV8i`_1lb7!}9=g9sP;A}v zc-MM401)MQ22}d#&#VUffWgBBiG@Xj18qlC@tSG9-So`(naDN7EU#M_$_1B+nWzcv1!)y4&eBtzEvQ?%IhOksNZ!mW2#fe-_iReuSM zkMml~m#OB`ekX!h>fw)c(op7Hda*0qJ970xy~k+@s8HZZ8XQUYGQ{S;*<84uZ|NEnS$F$}4${D~ou z6~;Gx{y$0LLZM($@!F{~!t)I^`j&P$iUDcKe?Wsx$zV2TW?D(^QN>SQ1j*y_x8wfF zjzIlzg#S$?6h&9wdu(Puc-Z5{GzYuM@81Z0+nrAW;89exV8#WVe$kXVZUJ@|#{>@4 zP5qf|8;a6zTWYEbvUT}1Jh5aw6R#GT;zEFjrHc!@Le;wm z{`jz4CoCc(p}Cp7E)d#0D`mpx`fEe^7UPlgj(Aays-aK*EOL3im_OA6*QCMo|Aadi zA(JkK5L)fBaE-vDbaTmUO4(3}bB>z<^VduTOpDM@Fj`ag%HfDIqqf~2A`A5VK{Tve zpxLC-dipCS-8F*1Vt3A!4GOG4f^IU-Lpnb`hH#+2ds-(g=(h2JzWL(lu0wI1%lK-v z#Ff*mLBTUXO&Dg49+7=c|LkgQMtb*eUWhC!q?5yQjVJIl=KQhvxtdMM+lx_ZTOLX4 z4wzZD!&X!4;lz-B*<5ZDl(gj6=)Z?-d&k6zE1r(fxr}|9oJ9MdJ(zkuhj*bofumP{P)qd`7ox?;`;BHYtZ)eCaOZc`{2iFW!K@a50GmH->Cl` z8?s6VzoK-o1_^6IiJcOt2Be8Sd>;s5LG)Id*X->sX! z{dc5C?VOg7=63e;IZx|NL2s1r_VoU*P27Kar>K#zo36Snv&w*Q9?ENQU%}gRSwm(O zHMUt{+ak`s{?C8l4e+#GC6$M4OLQn`7*_a=`?lSWcEklUkq+cn>1hV-ZjPsIfZn-sIiK-*%+8+ZD`|9T?-7kB?ZZ;M4=+JDy+iSc6n#Ae|OYf-WGT_+A$Y^ zzsRDPgKg!vd(wajY=T3`ty@&<<`*u`z+&bCc=eoYE#(zf*^JA-scHOvJder+lJlSh zaIjfUiDWv2%~0&kxgLmQUCmc71Rgdmgly(0wvwwSlY7-z_c>TxjBJBAd8uVdY+ab& znD=oMv-M~dSQ&PQTn*wnitJt>;>>4iud}JXN~CM?GKO9w)tLa=x7A=pWNoVd^13hG z9dNyCx%^?f;CJ+G;o13-BSFaNKTNv7z1im>!MiOMlE=%wL((@ZtXa=m{Zkd+1H`_} z9_d4de#k1hV1veJ#)(74N6KOC8Ox%STtEm z#%j$$&oM&a|1ylvKu3QXpJd^L5Y?_`$S)Fgi&Av!vhH;Mt<<^xB4#NC{~dWE5fPkk z1`AwFOiyPHYjB#kwg(m+RWcl*UHbE5BYKXv!LT(8->6}fsohV)SxQj=UM=EglKPUu zZf?WU@|-X6et>Z|%!JIcZO5HBD)MEQ7rmR!`AA*s;au6+S{c1a@bsd#M8V)R|Eq~X zDqP4Ufs(F`>P5#f`vYua&9X5hMm?dV%o0P%@5E%wjPb-MUysRJeO`Swwi-PS{B3j zLdy=j>KG)KN9N%7({{Ja*K%ScZJKn-V;*;|)y~eCP15KrVvs0f>%j4`x@G|#tRt{^ z$tj`{*eG*hsDoj=Pfr<6g^63&sn(0b_vqb;m1AuIC#F%_{4nF+jz;>*+8&?AImi|S zZ0RH`?9@LBAc0>YY*y@nWe*Od7|um5rT%2kVe@Jn>L*v_k`Aj@{H&Ey&{tlY=y65% zphg(i(V_ctw@b_JiTgnlObcIsVc32{{Yq9Tv4PyeSsKJZ5S@#1DBg=gMK3WUE|+sI zD(RJxPXhMZ^hRUD7(Qqu2B6o+WdT3AN@{xsuiCoLx~Efv27jT*b9 z$2_0tS?-B(|7So2&?XaeQg)~`0!(30*Oy}!9Nu`mL?UeCcJ|CAvP2>Ya-*>J8YZ^0 z|GHb`5Mwb9eYHv*Sy>`kTvCXUcJUNcxw!fi=|P19%n~fi=P111-4wGHHB!JnU!^b= zstBI{cGnGY`?vIc>6a%3eddU-QW@*jt^k2kRudz<|l97F$k=4L~IHhm22tcpCgHZGN*1qi8+yi;*}O92<&p-J^Z_m4g0u zEzD+Hw~^w1&sH1We-n^=Ijf$C=1t9&X8Ukf8EZ$8y-Xq-l0L#u%31}u7n9Ig1rMTeRL2Iq=;bUnCppX17+XxK_V$1gioLJbk6jiSTWpUv}39yY5v>A%| z_OgTplvUx}rW^e8(|h!}e{~YU=^cF^jU(l7>vwhReP>~1+9G`tGc${j)}|%v;`lY1=cCN#f_gC{Nj2q zcwTpMr8ysX%eo)DGBbovC;XU6Om;#{TfpcL_&I9)$wpd$-?(Dg4~5?U7~*c{C=~OX zL)g1VhV({!wvh7YQ&Amn4Ds_fL$Ojc5VSGkQvNoS8NBi5?=DLt{r{ig3lCNS0Ze6X z)Z%hXe|Iu@-x6?|6>`5`w{R_gy?mS1c6+BOEg;=?xEnvy*Cc(r_~3Ikc-iBnb?U(eKlxUzk4Djwg2e_#++Lu6UFrGbWrj8TwIVrg3fR(y&|#}e$F zLsQrK!Yx-|9n*Al;ixHj+m)o*a@8Z!>U##+f4dS`E`4|6+IGJ+^?n|C%NWPY1alC( zVx(Zl%lez7|@ZR1a_Ji$wU#WGFVopuFkrX()a5?&^kE8@g*QW zN*C{`m}Z)%qNs0#ui^^>L$7!KzG;UM_O5A1@7P@<&J-vKF6>`;yp#8hcYSwE$ve-m zD};{``NLV!0bS59Iu0>(lXh=@;TK3>ek(;e&CafxSQR3GqCj{+qt(l z)%(k%t91+lJwfcWpw|TBRinPoNe>5j#)XBR5t+CxJ?YkrXlox+d9I0^$-- z0LkbZgFl+c`$zDEc1fflJcSxxekpnuaPQX9mI~&$rM*%0^)ywu#1aGL&Qq{`Y42a*gHy&=6=Pagz+a=-U~nY`y9#t zUo-I}Q2nX7zhl$;V+u;jgT$PE$N@OaQ8+GiKZQNvhDw1lKx}4LL`XQV0##0a!(1Hp+`DsBv)CA zk}w;;*qV{Po}<5itp0{D*(nmGzZYMj<_lqQj|$RmK002Wy#A;<7HIP=YA6%!>&1r* zCc>c!a2=3fJQHEM9HfPnASjZqPZqg~5t}>Ea)h)6{8-4& zVeZVK9G^!6^nK_BN4aRzDV^x6tsQV|r2bhf1h{a3#%t1YA2tR4e?Ndl29sE4R5cnz z)rWxTFRpmnBYGD+S|(=A2hT0Ey;lnMvfi&A%%<==mG*E+XOvcA+n8r&TLmwg&x`#A=k`o;WOjk00VW z&lzosR}=P1nxnlvYzC(yye^R0R^}LE_gUN4A-hY~GKQupbZ>Q+Th(=LeqP-X>%{h#a0|IFAXTDh&NAYWgPXGF$shSje|yM2!*{IHIe z=BvnT`@*MYO{^(&JaqQWioc`z_774!nG#eB>Gv)_fEWQ4bInXakkW(a7#jul0pFnc z&t4oJwZtVDpYMj%^Y00onr;3=3>9hN%PhOB-3dWZ?F@nv}tI^tx^{0-{_ef{G6J?k^Z;;@zZIr|a_p7gh#QL_m=(2g+7)RK9Pc%=)nKj&XF*a{wqYePW?neBeh-LQ9r-2BGp*9G`uW zRqzn^=0kd3cfuIlBuEyYKx8Yb(5-llOSfn9zIzfxtRkcZ{{86aR!j8eLHr(hNu?xt z*3G}C^^;cRL*wL!e;gW`qEsJjGs4oSY$c4{eA$+w3%o6UQ7e-%k|Ii=b4*+2uFRc| zd(bCeq(4;#cFZdkdk)>9DgyT7rvyS{!4*y>iI={-@toR{2DrH|kFt*;A` zZbw0-OtQO3R=9PvVO}>kc6Gz_d5CU$H|0Cv&4I}5{a=x}B51Ji71*_!&(&NbDTV2W zE00q3U{`GL|1lWD3q=j*P@F`+$U_43bKVaa&yidAFRYQ*Oc@ot&*_EN9zt-TIp$TT z4<)j2p5TY+W!TG^KP{Dxu7qtrEFW>%d6IJj8v%UR`u%Jo((*G}!Ph7GRC+OU0R)c` z92$td&%D7d>zTKX;^!NGZ3($Hr;Fd`SUnXwrMx+Lq#!eOzZ0RccvGx{@;gTmhd_?E86q0-#Hsz0j=)I>|tXhrs#K(qzhUc`Fub@prUg9K($} z!=#bg<3{K8H0E)A1PA`mXPU#iC!6W2x->rH-yFG{wwe)dXK)ULFejR0^!^jDsj~kw zU@NE)P3N1g%y}-eYmZpQE#dBHhOQ9@nAmMZKgs4~8QL4AayJ#YYc}}R);fm2YhQDe z&+mKV-3>>`s@p#grt(E0{RN%v1F4jxxSNb8#S{V5T6Z%cxBF2-+hXRmhLvYe+bwB% zigr!4XQ;3$$V6~Nt!hNA_Fn6cGWCvXuN3Ac^ST`MJLx^ggbX@-*T9AtaBE;3sWly50J>pRo?+?c|1Z8;|mQT-=a*FyKC#fbR*5x)5 zmL`g~l7g>K^NM9;^Gl00i>>dBXfK&Meg^N?c4z>}=g+G8)(+Hx_*B|zRhfPPv;7U^ z3TzwJ#SVKTe@diD7th*lDHh{Jc08|WqjbpxKkJg3>!GWY#5fGSr;he%%HOW)$f3NZ zzJ%Xt>Hup=;2F}#`hQtJjm4r(z1MBQd~~6(7B3qT-YFC1~a;*ZQo7AHtI zK5TvH!Ox2zTNf@C*PW+aLPh^>Jb4uWqbM&sz2z01?Futt>Y^vI+-N@+%wlMVLw<>e zM-&mz2`zzOcA5D>A*=kJY~~A+RSnjb<*OP)?U{xK+YqfC(Do#tqWM{DfkGqT`NzBG z3hq@Mz&t2}-w||-0v5<3RNQ0Kt4Uf;iZ9sY^=UDM5SxQ8LbU{`UDxgHYYVkw~8?) zH9ky?Gq_HE%E9aJ9EB?ysZ(pzoL5%;qu;B;#eKTqL`j93X<`I8Zh@i9@<(|naMdsj z6erP&HzWNqA?|Mcf9l`AyQFTJvKeZ*}F6_00Mgw7PmbUZNx zPh0i>c5wqwo04(kd&|`wSY-g9SH9m*I0WhJ+6Lv-==Sqn?h$G|DR&KA>@&(dMSqJ= zr?x~EiCC$I&DxyFazWahgsgH#(Gu^kiG>x@a0|2sqB*#Q;11MOE|7K)h8T7_E;!@v zTe0|LRAoS4A4#N^!tqEw>P6uU$V-Gwxo&LS2cB-N?KbhkpDL{kRe^IH!#!0G9JwQ) z!D>9GiWtcq31`c3EJuE>sLo($GEK&$8CE+NazTHhHNS+)HyE18CDMzZ2B6F33eD`?&`M zY_0rg^uxDAgIN7-e?SF^kaPeR&s*6iL}O{DSKweDu<0;hE3J%0kmTV&MxlSO`k??E zY$^lbjM2Vo(ydF?p1qxqfMJ#UfRo8uXBgBX-nnJ|05fp7BWyaCge$_doRlZLC&6lV zWrcddm{`h$Y7zfII+)o$G7Kyj@V$+!ulf3z&sI zZGVH4V@(sMB|1c&h@+xzaJ*pbGaN8{131Ei@vTWa06pjh3BNG@Xb%?vlgdZqUd}9r zabKIoATI%7sl-`@d&4%0CXhU^qhTU2ENl)`L)t5u^Q)(q*s$zczZ7z~s^4?_;6()~ z0qy_FjD}%o`w@|U;qw-YJ8OJ0n=x!lNr+E5;c9yZ5Z3V2%VeY zL3237Ii>?g5AV{ODn8P(b0jmgZh@qmMnJMr%=-EUzbo7crQpDI;7#3!Rh+W5L<3GH z0SoORN)?$2%;8XKd@~w><=KKppuzR&TYwZOn01!Hi2uB_46F?%1gy<}xu)hLpV-CE zttBr4ZLx1azt#@Qd&f57sE8-zLu5!CI|42k~p#Xm&+Zd_zJf7xC?^9%y_M)unCSfdlcnqyFw;Xf0k; z2wF9)|9lP@G61C3VgjJ=d_)j?e`dNkrk%_)61sV?GH9x)U65z>_9)@tNOwo z$H)oW5N%d?Q2(bSa(79=on4t_XXsYexNW2bDYHA;ip_Oa9`{>||Ca9sDgicg_nxG* z&cWckODhelV1(!-&7>)>c!Q_6mAMsGZD0}6NrdFEq(F?}67wMPKGWt0l>mO0b;yiV z3+NFg9YjonsoUhv?tuJdvc**9@O=C(#w^->SaUDjGa`o=a3~1VBu3t!Ks(r6N+lW1 zD1%4)Zmj3pMjKYqRlfCwz6&oDg2GUbEqhPX7XI?T)RNEA`Ae#)e~6%)iSGY9@?R!T zfK?Mnrur$KN@MFv_to3MdTi6^9~P#Vdqr>QH~;GlQt#EpUmIAMvp%kWI-+SXjrXc9 zZ*FLk!kvWn{|PmIW9XnOLe8joeS--4{oB)tk0S?yb5~<^5s(g%&7zRv4Pv<5bKZ#` zy+3k=+5Uheab{9vR2462i*!p$WeCa>sf1E+4yCn1zL67#(0EVDpn!IS9PU}j4Ct2n ztd*u7g&l=^*u4ElW)F1Zy&sbm?-J;iL0OFjfe)mMVOAuHS#_*~cHb!GyLf2Y{%iIu z1nFAp7(|;XExmRGf(-(RNx^w!Jr{g@J=7sa9p#~a=^@IA4=c#7LNNbUV#HqQbuv+O zTchXMgkartMmlrijnappm@AcK3P}&^Af^#*w4hKS%v%)WwZ>_4P!v^8<^6VTV;JJZ z4dbGvfy7vM$1>S8;hN};S%bc2A_mZlc~6pfyJc+lOeRYG|A<~NlTF_x@f$g4uH*{- z&u!@k`FN>1BM^tHT=ZHSlbu^BW}!ALlyk6R#R#6?>>{;^>=lXadTpP=SfvxY@1Non zWLVGpW#1p2OU8-u7H@U5F2t1tT#%Ibs4{3LM15d#LQm+nbs*IFT7j#Bk{^U~n*K`! za>!?Ct9cER%@**#%OE4$IxB-)9K!`6uHgQ+!&xCO}p--|t z`Pq%d`B{}&`sQvcM=hyELV=!wGwzPXdj>0a$vMC0y<=|7J-ek>i!nHA32Ah2tl$$k zTV+7;T9h`zR5$a;VlIiYGdLFp@jp1h0pY=>$EaP94eRb;^ZGNx)QIF!%nRmp_L2q! za_k|+VJX-lf4L?kVguHbS_gM*%H5Wh34DsFx znQ$y>y=tDdP=(o%dH8K7ZsG-x>|6w*!lA~_7%r(j7{D_lYBARoeduo8rL+);vY%sUH#L5C!#JA|6Fp9%0D zQNSh&$$MgT7fEZul1ZMvmPdgssoT>yz$3MmsC`iIctz_(=R-=D%#LVo@qSDZOyT$> zK{_`c!d3EWH^l5yqPvz$=fjQ=7EQ1azLxo)9rl!7Cb+0=n2h)aXewAlLK(3m;MR?Jui01O0S)yLvhS9L`HXmxrPro3Tait?CqZCfd#9m-$AAr z&j301@i~8`2K4y(T&OK_hZHT9%il#Khvo? zE_u93;sNl++n7u$3kR_ zsee17Nich|g}8w_CFBv8?6}n)U$va~ICRdjHGspg1~vBC&EOh=)2q?Yqi?kGV^zUDk4&F zKsgWpe1hV-^2|vLmp>NO#bA4+V)(-E9XvmaP-ym%b_i3ni1npK6rRV2V>PbUyEKcj zT;))D0`zpi3O>W@PS5EamAAv6y@IbWiqcu`qf_T{SFT${d4ss(W-U&oz8ids^zN9C=FJFa504M_0 z;-pZsYFV_G-Uy%kIs^lpU-U)u3je^jCytJXRW%NqQPhH%5ir}52Nlp*bUL6A zc7CZNj(+mFMIH1Nm|WUCXAOVq$SupGA+ydicF4Gak}D?6SGqBqvRWoOk-0GgI=swr zIrwtr`2F$t@7_OHecX(l(8^tF=L;h3Y8nqM=69eWP9VTmw$6YB9L~QQGz&5|@yn|z z2%o3)hxW#!P%cWv}{d;__GixU2&F$@eIz78{Mt-bE&JH9tiHqXwx}s`!&Y*42AC~b93hj zW!2L0HcG=4A-zib^O2Q@Tcpf(Cw^0a+hj8||4b$QYPdgvb)-?TBZ2ye9*ET+c$F8>flYzdLB-qNl zb_!J95OX?1Rm1;b#$>pbQAL28Wvj1yJ|BJGPM7|T9H{U=Fl&V~`*HjHD=2mjg>W_P7(ynk%)AS=5K&c>JAcru1J27|hGb+XH9v6MJQruv^R& z_pkpJIE7mmj^QD|D*9l+cv>UIFv#3c7YqFndR&(3w-bAu`Zns9p^>(wv=n$6-gdz6 z*GVEbp0d!x8 zdrno^s63C6V9y59Sk>$6$NcIB^DG3{OHM|k?*|l1coPONs{7lC*cwUOsJrRdjNf2- z-lz%_KKGz}eID50Jo8NV>YoniUX%ZZHZzRK$e);moqZ@diYb65*L)GSxJ;lfRgC8| zzoI7=d1HqohZS8)e9WA+n8(XH-A`bAdg&z88_OI~5dDbKnfe09WO?d!yJy#DMklEg zX@T&veEke#=&jgxi9y*7^>}4UfwA}2?aWGK;#9pkNk87*TIzAj^+KS9N7*W>EU4g* zegG2k-vraQ@C5y?&N84owr0hzEyu6a+=z0795P(1n9vL1(+1dDm;nC4k*}jWf5(LGW*xF$NSm~FPJ?U@~E_BuK`imsJarNy)cq3CT|xYgLNS6{qV>ZI8!m&UMq4Z z@^~kd0qtFR(|R^CpCU-p1g{+`;~AN*`R5j|C4x2J0}D)TxwRtqYnZUtW2&}sI372$ zUvV5vOZ>ghjAQwTIcbRpR-9^N#^cgUvSTfQ0Wt9-55p)QJ?7?DZ=Q<)nz?M%p z+BrNJsBcbSEs8x;HGphf+LaM16$LoM8r43ylhxl$B2ZTm;5h8X@kr8qPiy=AfjhoA zPqBRH`^+REtL!jy9f1~$?*sKhK^Gmb?q6vE3 z8qMbX#G-NaS4Jap+xVXip%`xB3w<4K`j@FM7}i0#2fb`SK2VcbSO!vOhoZHJ)+e8B zA-Ob4T=wiIm14Tu@^WioZnE*n*<&$bu?KWm76deFV+x$tf3oSU%UQY^FFZ&a4_Xzj z(zL)wZ5ml(pIBrA2w`33 zGV(}uQ}}wq%-s1cH}T_A1)w>`& zk}vl=j9vj6Zs*BQVh^L*3e!$oEo<|5UjA3%ZJrGd$gfD7`3xp1m%3Dp11=v`QZ+m# zspri6zuRbBspwZ;JsLxGku6E*==`Wgyv=8PQ@X!=qH8B4jE$6`Ye$)}kZM``K;)Xu z!ouPxg{;*>f?`?ZjC)g1X4`?5C4C#mqu;xRlo}C^&y_ow*7#z+z)r^y{GD#L@URS6!YHe<`ccuR2#&sW*EBX z>NZKc`jqOie+hhs?O6zc8T-@xJL7#YxULhr%8dr5)rgRBm$z3F(e^(WZH6YcV~_UiKTdYs@ajOdsAb1z&TMSm)nzB-jq z=A|;_TTtJo@4eycfZN`0 zI~4bqfdQBIZT^>?3zXWP2fw9Ux12{Rhk4rWGs=$qZu-9jUe6dqceI`SuNLCfcWf*C zcv5C8+7HY8FSe|pr*)%G8%||@H(Tu$e^uv3z0GZl+oN7U-T$v-%3n^4JrDrVSZ}sx z8z+}YTw4CRPk9*n2gkFPmBO9&-bBv%jEfa$7ZoJ%6uPDY{leG|-{rMCzu{!;Ut{Z5 zWAe!-P$P1av-KBt#FTlyB$wsRvM{|)J3Q*12?rkI_G33>Mv6CzAV=qfAZP9U$DuzY z%rZ3HQop`p5}sVH8F!OvH|M{QJmbRQK}g1!w!89r74GI8NPmc89I*3^!PtlN4{_$j zSKNMr(9_}jIKR`KHiEkSrs74!<**)_fnNO2!^J;93Z{p#)<5Ye@P5AtbVx@nBOiYm zSR(F_n{@{#LT?)SM|acDw=VY!2#|G&I|y-%2!*Kgea-&*M#Vq3JkXL?$hRN?!dm zHu}$%9CJIPtOT&S2^6@Yr zeYfKSH?Zie*7~_y37uxYJVJQ_?%7BF_uzH~HzXsMZ@A<5d_x`!Uj2Zv@5?l^wd&P7 z{6N`j8T<_0+9(vm8hL8m-fS1a1j%sMa#_rmJav~Xai}_6q6U5NX!tpAuQ!8P6)aIN zG-2|)bfsvcW0L97-~Wsu9uT)^BkSLI(EZYKvt8vBK>OKkOE#UY4qZF6JTB?n%332G5cWf&EBHpk5<%ebtCuJteh`%!Ky=z>@kNaY;1uqnrL#1<8 zkCDsq2P|9E#!2^hOo)qN=$VeJ@J)z`fY%TyM$uFzJ$L64pFfCo|DUU$(t*i`zj!%E-FQ-p{>@a84U|+SIzWcTOCn12K#n=lP+_u@KV0)@kIzSCqC;4c_@l5`I;m5YO0R>@%tVvmx5?#i_g=>&tH%3o(?(ln+Ty~>a%F9>yWp{d}UVf3iI~gSsp^ z%7^Ep$u3?s<3|#=!cK@b!wFM)LTeCZq=C_n7XC|*PY322K&X`lxeL}4b|pxNM%H8C z!PFK%YJ|HTLpViOT$;j|UywAZa_a8E;#`+XOfSxC`BTo0sFSY(i6oKQ%`v|=V*bce zSet-pz#4UyQsk{@{Y=_8+#%X>;yF@36NR^HpVUIW3(Ps2vvk=tf55J$eJvWp-L+Aj zDd+pbb5K5A>X=dMtbI*FmVzSWaV#X?w~MxbigvUgvAbwYJM9~WH6McX_7Xh9#}MZe zym$1c)nTzIOh$A9bf=6XvW#@>*>8S{YMo(&)bjhY`0DcdTUm5?Vm9{m%vgcR3Kew5 zw0K$(D%*hi;r_5+x2Db5#Vo%>`MKI7WSC%-sn{(^)OxMs*EPKpHu1$TJDS?P6=S5l zQM!v%MX^UvBEPAu8^BnZdtl*KgoKS#Gmx$bDoq6{ogZ}UrETIRykNMs zUY2~GtjO<>-rFj!flEutffk+mol-5x;Wwrl2PTEUZ4&fh#e#W;sZk7nIPMP`yh;pD zr8mvLl#<=SZU4FH>3O5T!SM50XI{LhzfX$u8T|;H! zdMOMJEIHP7?bX8HtSDBl8)a;Y=sci3h`@NpH~%y_+tDUa_f(cF8#tZ zVVvZ}`xwjq3MJTFlWb%04XU(m8ZOFR;TsvJ4idAooPC%{*?@U@)Ud>6%eGSEGDDxBI4|(3_a~gFYtiI z=)J)!M$e#ZCV%DgX%kFp<3Ob%p^`4b^n=4~1UmP?s;m7QJ`MR=}rJ)c4CH$@(N zlr{lPF7YdwNuXF}=nSNVd}-b(XjUA0pVlN@qtL8=62r|Dti~V_6|73&rd`vDv_}Za zqd0a7U(=TgWpQlEg>MV3xu8^C|xq2HdzT%W)F*5=dZ zn#PNnWB$1yGHz#&lIW@Loq+5L?@3DN20R z_uBWp{XPS|hx*r8pS};tT|&lQJ1IF-wv zTn3cbX_?-ykV2YMHe=Mc5C7QNNZli7uU1&5DtikHe0EAVc#?Qvy3R^R>0%#m}$;;xDoJX$&YjgaheXm?w?7pk+rtX4Y{ z1(kKM8C^;ezfnF)dUy9Ric$nR>)-03$*%V+K{PCq^3(-r&B|)HA*p!1fWIvY=S5W> z!sks|$Tw?oQ#ytk#nq{oRw@en(H%h z*QX-QJA?aur#?uLr|G_bjH1v0E&06HDC(NXJDvS7`SWS^Z_~NRWYXeScYpkzymWJi zsJDBVPN3s#NXdIrvwuJF>_!$hV2ro?f&4)K8viXVi6^Y?PxdKgQ3$|%lXGT~`i z|Hz3({nZ_3{%87((*VTZrXvq&=hc^4z%-<6x)}m3S_RO@{UQ)3P6g`g+ue^kLN@}T z$D;rZwFO*GL9eH@p_kyF?r7j+TiMgi47BlVtg-}x^Y)Od=R=g5fetGxVepz1{ zXvyN|Q_IDh(xF=|z6oj94c3+tr$d>JU$f+hd)LOs(xb*G>4!1(0yj%8CJ!Z@mcKcG zY%S((`F5|h2J8VXe~7kCe`tlPS(>1;*5x}Cqi!8tP6<7#p1!b#kss>btPyT62N?Ma z=-!fi#us*mv%rthL@{FU{)sQlSb&=y4r!s!j<3(aL6>3Y?|)aRjfaV%xAxB}Ex~%0 z12fCwQzDmYVq$ak=4b66Yzh9LuS>*KkJD?n-Ny(`UgpzGNP_j(kZ{ch_%b193dedT z6r-bjT5&9#=8@L{-pE-NL`>N+ov#CAuCijxdijNVvSMJJ`(QE)pPT2mlmv#w`~T=kH->fm3Wd?7K& zU(kUa=7QRVfyh#ZVEWb7HfSc~L{A*6gG*Y4*wM}Q?Uf9N*4AXudUOL5N?1c?xNHYp z0dmO9+5!9y5PLiJHcT+=;Jx@y{-L0Pxf_Hts1IjKa?#-Zd;tirI>^Kjtu zpSHtnxoub2_kS~N`Yn$AQB%>0B?n`9A3Xzb`cWDC-;%q=B`GmeApiw)q-bSrkCd_q zCnwOMV@@;F(lOGVE|!)atYuyBaQxdKd45Hn`uJkL<|YhtxNM?S`u@OKxg8JJI`S_gLB`!MC!?wV8HjL4<>5t}&BJ6{- zjDI=}N&5>SvTRIynMuc1bYtp?>E<|&ml%WWCqCPNXHK<@=CUEBZ23RHsa=QQjnkzt)c!=aE_!Y_(nj~?t&XtVm&YSn}-#-T*P)pAW zNDL}Vn0%mQ@?K2%(1m%=dS zQ+LsJ9PimjDH5#P=VH|1wzq1X$O)gyFRwJ&E4DMwF?5@4`h_ z;<(_^525CWs{U^?O`uhU1d$>KH?c2n$&f4ab)9*J4^|t8y>mu?|N+%aW?@8kH=s)(y1Kmvm_x-h@Zfb!RpcN z&WK|-iL`NiX|9Ph(q)fp#>9TlE%IZ=S)4)YJS;lVpgIA0q@L-w=#Hw4+&N;uZ6$># zE^HYBmnz}*T=k}=Uj;tH?;A6!mP$Up_KaX(=54;XQ#%5~ODU4p94B8)6bb(-| z5nW*S6k->ISVN-mO`m?Q)BgNK<=cr}DPuhse6B1Jw8utsuLCxmKU5EBP#x8^t2?L> zup*2QijY|rcxlt1jWo+%euh`bzKrCiRB^Tn9$l)>8e`kZLm%-dVL}LDJ0P~g4CD!N zOW8#U{rtL>SPCL}N*yvoV2ob+LHuS$Ix6j@Gj7QKC_F}3kqrvRG_0ljUOfAL(oj_3-@Ok!oG%=K-ifBNCw&+%bA0LeIMrU+AD zCLM7sF3U3wRqnju<+y+#3B-(rv^E>Bq|!0``v|Xsqe7<1jN9zHg3J6$zuM?mCw)9ZT9VX*iyH8WBYz? zI?`1+0nLgKlT6U^snR2de&pg)CD;Qr9|%eWM~td%ud+3V=iP%FT*Hs*V$-?pM%Je! zkCK1gadD|?opyt8CSh?= z#6Pc^+zHM@lAdtf_Y&(%HA~9IeTp7tl7(*tuL^)_h5ZLxAr$;4qrqpg_?>rIX zB?rY$_4CUow>3*%FUWR$+s}?l)rw8wuTnS`&t3gdd-|c`J24K z6}2EPj{Jt{d-~ck4psylg`XZs7u})1oNLu@lj91esl5W@{pO3E*TZ0 z8kcuT%b~<`GgG9D3I)T4f*;2V!B{uX-GGIJIRz_L0}-dac^CDa+Wj#& zvq{UoyZ=Xzp%n1_@t;0-iydx$f(^d11mjOFTbyTI0ws zAs1r#(zgF3X3d{fV?_D))~4z;8&f9yb0=Bfn*^K>WlUl*2hQrmOnrJU=x*GRMoTbD`a;3N}Sv8Y&Br*w@E7H#ifhDK*N&7YV*OPMkStmz}Z-1vK3|>plfM* z+w-#qu)r8qRJ`2aQO5G6_OYuwT=F=XEbg}BJ(z7fZ;ynbq5ldgvq>!l&nqbvsr_(R z`#sgR_DH~BD$hyHV&Nx}vVECIt@mNAG~ibUY~RoP>VSCBfA`|3QT;s0A-T@oKR}l` z?YvxG_4JQc@m%Y__WoEQtm=c=XtmIU14=HB^xI9zf{$1f-L_d3f47eXy=}XDe*P=6 z^P&`NaaC7hEJ)CT1r$NEjXQwTUP!KgC;K~K>?)aSWT+~)sq$Q!(VmG*T8l_Sqok~KsrI^WokxGhaRE@~!~-g#{-@&Q(07MIzB7RF zE3ss$vFPe#z(YTzVo~bad^gMW&=e#F_{WbLs~qrJaJfR9~& zl7P?1#N|{CAPz1n72$QfgO#`dr0CiCN1OR6jcF5v2?tnP3669A*1O5S>rDWSviIPT zsMU?a%Men}2s`!pY_G z?N6h4EJ@Sv$Oh5*Q2g;xw5I*y(fK03Ht%CBaANayG@vM7zvEh@eNKYq3bId;f{MAs z{XZm3!;xJa!P`+Wzd{vOQm&%MvO~EMl0QhLnYetqVtP7jrq^Az9>R-b4F0-_CMToH z+gZp~eE(RuQsBQ*V%(w?)V9@r$<6foi}X4=>ngF*`!wC4#&Kk4e+$c>YL8#@(u|i~ z?_0aT5^!fX*s@1MS`6M{-yE3!T>4Mo#(#Er3b0V;AupFYSLlZqrCA-2WY$CB}Fsz zX6Y|cu?DP*7MjO#AmHSBS1@Eqf6IAI+4fOgX$j~SQe4_@_ID2T9Y6#6MXZPs7$wjq zV9Dy0#_ZW}GK#YvCmP2cISFqKQ2qeoQ!RC`%0dNWku?3q;-yZ_RG`}1Np(jPUe<>d zRsP{|a*{t#0Nu8*XTJJ%Ynpw#a}{+vVI49kEKbxu6m~W{sJ?Ax;56ON1_}$D#p|}_ z8U{$6*~SP0GvD{RqvqfFj)2S+JjLRulKlS5@ob;&T}>3IOD0Sg8TGq0hpJ)hmx^Al;>aba+84N$?C z0&h}zKL(h>KLk!E|32SWUj7$LKvld=Mfd*90oXfOu3+y9wyLp+Z6R5?E33%m*=dn* zKr+wZYo0Ef9<7D=CFNPJz)u$a79tsD<(RRR##IZH^6rxUQJQx6SGqb6TwlrLCNi7hrFmt;cn@drSBnBIwWsQE zP}yfQ;qr9*zit148&8Y;yDfaP`;D#b^k~qj`QwV@m%~C4mOYrXc#4*rgYRBqBhI+B z8rqhg<3SxX4ou2vxY2_t8G#qS;lh=1s}qjeQS@*LR$2jR8elFmm9xn1&w|SXX~9QC z^#jH-?=N87)IoIFeW%OGiIlz81f1um5W;-C{E>i-pI_dHKnJ?5j2=#i+61rry0`3j zKXab5>$$Jl`+pJV?TT%3PSF;|XKQkP35tT((}*nwo%<=;GGC4#JnR?;JhsQ$7Ab9G(WHOmq}ZWgb5j+0P?tZew^2q?c-AA(jd*Z?BP&w7lwPH*bp~f}bt8jXiF;w9yW2f7|&Ae&UGZ`D}n;jjL-XWKnS@>jJ4Ed{xs4rT6!GIJkc4}}MlukD&%j3tKq?9ymvlyzY zP1#Is|Lp2j;>m81;SK~#516b!)Tn~3@$f!wM87r5p>DyGT$m@IN8;0zBdMrk-!9Wn zUo6M@d^_NcF@O!vYH(RkZg%7pNTI!+a1m$EX6Bn>(QA>$+F4ISGWY0Cq9frjLSqBA zIy@}`IF}8ZEtyN;Q|gW@JQtP$F}>r$$K2yF4m>MXqdI?Mur<9um)-^Ton-Eha=&R{k}EFKP+Zj zBtEL}O{y0;7_>{%^O1cy)b(yv?b|hZOVLN@g3vWdCAUn6~ynf1r*Cm_2*#rngZYsoUL7O`0-hZZ)!3&jUUal2EdHs`DO+7Y~-R_PBfy@ z`DX9o>42`DBT;wX>2;oBLJ0wK)0&PP`kBd}_ABP?4+Nxk`^v9_Z|e8Z2#Xi1fluh4 zcc>Jz>ljc1;>|S|E(j;#k(F=lwyT|<{Ap0`3b+Jm*1Lz1#})bmw9v=}{h@$r5?Eq_ zUp8N@?RhC6js!^JP}IF~CQ}G`Ji1&@?)+-1rdLKOeZx{i{>lr;&Rl5;u&N@)5c7FY zN(E}c9CM&aF%-V#5;iGhvjT?83X;%-e1w*6G+&Kk?h@~o8DY^K#Gdo+ii})kN4tAF zM!p*-kxh5##M7m2qqhoLQwKsIH=h=-S9iRR*2|=orIS~CbhDu%inY?Y5pCpipOXVP zIv4T#`_gt@vWBv9tc<+(b3!J(CF80kCN+Fx>8pBGd#@}0?6BP;e}Sbl_Z41m-j z`*=KUtZ>0!Y=LnWNa;tx?{5-A1{ojx~1vs zU5(AbA>)=j%kCaqEi~22I*VQk9*5R%_vl2@7bJ^>BlvUNVH1h}pjGp*k03Q}{sRZ=%YA>_By07#~bms-md+DvU3 z-+`^Hr0m(?JmuW_BTNsbrfCYrS^DcY0XWV<4xU^Lw#HQQiFt7+Bw6Y-l-H@o)$su^z zL|g6=Cl};`VUS0F01W_$1(&a?OccYIgV?mh>j!oYhpt`>@Ww0SP0ujc%>1(UClVrh z3rPJpilGv1;I@RYvN$@*ihpbQ0nmhAi-lLls~lh@VDn9H`EUq8D?pA1K*1{=>HuT_ zyqStW>lVf3!8WB2?h~lHTT;nN?X~Q`5r4qN%;mS}u7##KLji7)=9Mp(b4SE>*`h|3 ztNQS)&G|J&gInj2w6omc@Gs!*mOpNe;NV$$0wV!}5kZPGsBQIqi1{3Pl&oR+u{gU> z0eB`L{Ed(`OO1|*?6mZm+$rD+o)^evCm6`ol0cKXIIMggAZM`e3o!|F4{K<6%mFBD z-j3X#)BqL_jDfDuVIh(0Fa^2` zOc4)_o}VxnJEmB#$Wzk)u32k|(2}j2T6LWsc(NA#opoN5+wR*>ZQqp!G@g%`f;cH_ zJhD;CHP>U^3Q6avg9uYIxw@J@=e(C8;z;HVCG#F?Ev7;eKkLt1(Nsid8vSP`@=IXH z)4*pcrI$I~0IzBZSZqHGmbGfm6^d+H;uSYLp2q<{VLse*h)vx?l9gHAtl1RTz4g6A zhwRl4cOu{?qEfgW<|_-crR@^T6jFHux6cL(Mwb844`I72n||BYB+r@q?2m-m27TCg zr<~5pVwX?+im#(T-NaP4iqJt&v(`34+rV^0jbB>TpS#5xr4vmKr`oTK|LPbKO#cLxGIHlwN75e|GsxbRgiDU#PG`0Ve}EWBq{N0d&uXRi^KXJPqwhkgLT*YKTGIDy1SgRzQD0 z<~+jXx?Y^p_^pbtOc&TMmC<6}@fZjspJPA`^#a5yNr61zxh&u4#g@+lXnIA_pnhf{ zb3XVSUE2F!rgvEZ?0H~038*@NOv4iVs&V_+oLZcxwt*i4t_SdWIF0YKrpp?=9QfS< za)L?Vx|)AgIyBeMZ5tx(uo%`^{!0fSxbyv5Jf0PR>7>}+5GNeW zbT$0PoqhKNp7*|z(zFJkkkYxv-Xz^!D!TdzEg`3}w9 z#EY?>3FxXl6q>g?VU*yVbQXr&!PW{EwRL{`HmJe(z6O4FU29_pj1~ve3yT9T%|$Hd zSx*kd%Iyy8Dp1%Z&hX1X1_+{_?st{fbR>jzm8w&QhLx3YGWNLuAknC!*hzBH%XMa_ zmfMluYq6WzKTK6<3a^cQFAv{Q2Ii~Jh%WhF9WOb_j*5l?uzLWEcB6p~A@4huq4$1Y ze-*qP;UB$9*GGV8?Tx0?RQ+qhm4#0)wyLhh{Pu3Om;H{vX|MPNZqD|rZlEUKK+-tP zkJiCY+H$k$;B9Qg&)-$D0YKb>WuzLT+K9H$0v$6~5pg>X#cI2m|4zd&>J7X00HME5 z6N1j`A1}KdJ>=~e+fO$-Fmm0m^=2$;>c2xfOZz+sCY$GUGf#UQjUUeu8Mj?LFsrnk z?4y-6&w*{cxEV4p$zbGnc<3eiZ~*=+;NbVpJv#Ar=bU2;QuE#RJ;QM$G&nrNdu!lh zS?lf7Ueo9nK5wujQYnJEr$Ueb;|AF?CLK4t;SRD<8yR8!pQD#^`IEX3KL(jef|Sv>s!t z>)*I3eOvjIx?xtk<%*f0pGa}B>6}7!#akdG18nMcQs?g!lYLGm{lVst@TmKomZqXW`0mwn8k~5H^@- z9Isp8imOaMs`UjaDD*RW*0b8>~1j_pwCsI*NBJ^=m zQZ5e)sb6~TyK^5;egWGA7L4^L`Xf4V#lO|xU`yLcs#|OqgJ)t}QNBCIT+y-yo~x@Pvw-Jxw7b1io3u`%&RM6-Iu4 zo>IMj;an!}HAx}V1dwfe1d1(tQ{&YvfGq$tFSsA_S?x6fXB6|37g!&N{hwa}cn$#R zMG#|jYJ6ru*uK#{+*}a?%pSPBrPgC>Ew#MOL6BOiGl!l6_kfeFebHm023HUc$a^NT zcG}OTfA)g>7BK%S5yZ^2IJBO=zt>h36Cu zefRs(V8L1kP(^R;-MrCzIcSSkNy zmZ;jb2k}9Ct6tBPMX~pfbX#u>9;4;@UxdpBt_ed=L<;3=iI)5EookVcWHhV4hEkS} zF5fIQmGo=>jn&jO(DN=mPW(GgYrQ9vK@C}*YxO@?S25I@dMkrC-R#qZ1m@%BB`y1% zb~7Kh-tQ@}wcJjsC#?iRtD24kXPPy`o7bZl(p#JBj=+l_BJ+4mhY%V0R7s~Q!!sWP zfIP2HX+KxNmu@_tWq0iM#i03NU%x}gu`wFd&*W08q=;T`@hz9wPc4700u}VGXZ~0s zo~J*EY{XM}KR$hC$RH6ho4e4PSIO#o;qi1o36GXV6Yo5n#U>rs;+a^ z$y_!=Avj;7y<+vIt@e1;1xfyI2;uOXW?=29Mc1>O*m`4$#Rky*)Zr=d^hZRo z+XIDBgMeYuf&Iyr<07Y4=*fl(76}J0@!(GmuT#=vKW@`~`?Pr6nli^FY8~`rOP{ng zmwA?`5%mz`%bm||FHylz4&uh%2bI5}`&0LASlf0yWm%~=-0HbXfu*DQn2a*A=Lq;T z>nPQXPCe>mk=W?nd=fB;a4s@v4a7Wpsudo`@fM_>W47g*JE96R+A7BN1LFNLgw(Vv zQA#`@C`&N8YTTbENVSzR&c|WaY4%)5v-l_3U{TU^@w35uxYgVWpzVdm>%LOS0>JSK zS;(EbYQ)pG{cPYHCZBtWuga~npU zZXNKqc1g>=@JFljcif?)F+0`Er;VTYm|L;dJFSvQ4zm@eJHh0a-Ff$4l3%E80gYra zG>(m4)<|G>m~%1oI7}1?=Zb#qmRddEd_R_Kb1pacop5kWDRaJS$}zuR9JOt1nT6N71yiLcU?>qz8>> zGhi!-CWG@slH5!ICIKKa&-+&Y-Vw}ZbKK57Us|WVyM2%ra6b~7?EY0Ec&%GwalJaO zP8&F#E1)o=IYY=}XQd!5WxNgKId%U9i&%gIV*~4_kIBbF4r1$~+5-yFfG~>woGBCb z0{4RpgoP{eCAZBHawO#;-P+bdJF!oHZFu+{ItCo>)e|rzRSI=%a{{Zk3QRy=E z9VbeE@4o4$zdkgLX6nO7T~>wHl*Vo5(8VoM&gj=%$m7GdO<151+!QH|yY@g}(R@`_ zkzI8eZ^W*$w9#{G+wjTTr8)OD-w>&H)Ie$=fT84qk|WC(dK&u?^H9Lo_x=g^*%))4 zDs`7^WGzXUZGq=AN7jHhFuX+0ysLWs4Piz7r7JMaS1B!z+}wU%cK3J=<4$PKl9w%N zAjLeBvi~Xj|FHEJKvlkP)G#WcbV-Ypbc3`sNJ~jbcZ$FUq#Ft8Zlt6Hl);Dl%*K}?q8CFBz4h-MTKj#wf=eDr^Wl_X(;F;>3-B+6zq(^PvG&|`(-io!)Nc#L}}6OP{OSn-#Nfx z<%^ct?rD^scC|MXi)AXC!{c@Du#khw7(z6z@YnS^LIV$vk)u&Pk8>Z;a+|bS^cyuU zLSXu3dHv6k4LA|8V@7859%6>k28L_orFjbUD0aaiWQw-eR5$8Aw)Au8E8dj{Q@iIx zK}J{TB1FtrHkv#ksjjaK7ZI=m@lLDBhFy>$UAV|a`Vz`NA0U+#`EThac&SVPv1-l# zAcrP?+)WADs9IAj4zzXB$<)5h&e>t@c}wF%}oTN!EKg#1aBa>VHU% zi|wqZ0p&4AQD(fS6c=xC;oI0x+R7>$A?w&VpRgtIO>(8n-X(fPv2&=B=JEU+?C&emJrZ?na$72QGeId z8Pre@Scz*IT(o{-^l_d&LGZW<2*6`6*+xHH%dA%YQ#}oMOJ?^NnpET-Y?)DG@x%(zx;WJ zB3{8qRfp0On8t)|nzCy*oFvXzOt@o78V0*S$gpLGD@UH8+mzAF*h@gto zVt4_VM~UIV(h;B&UiX2{S31$Rm#{_lk9?5ze|Z)LLwyXa%)dPMRvnSBGEAS7iX~fd z5;k3}CIFL%q>H%0TF?kH0MgWq=+wm)K$PrSPVJ*wzR~MfQ{h1wFyk{?O(!-!Eq$J? zARUr1ld?lvE##3w$j$A^qiOBZm9+;(cx=VzAN15^o zj-HH8GxepXHU(Q^l4kX-6K$ncS$>zh1lizb3`S|8*{kgDp99=L-PvO%q;%QMO-1Wg z!R;fX{4JIsKH>)Xs9I}8ted>>5MfW%6OLu1!OA-0C4GE8i54OetnR$+=Y!YPUH4sFe|I>ZDp6Z=Zwakt?Y~9( zzLJW+eZ(^iE=*r#M`xLb?o@<~X9#;7{_Is;)bX(F+%Y<(>dI68Me0+ zSZSr0j&p9eU*q?zbDumW*Uogb&Po@^(!PlIt)Wr_ohFYVp_{&hOU%r=;wHB=GB2bb z?{3>X$bClhHf@lhnLc}C_0p{3Ifp$qjfd!WUcGQF zhF*phM+jX<@73>Dxo2YdUJgm1^{pqy!3#i`APS_`A&rLFfX83@uVrW_7? z>q!P4n_b%;I#manYO`O!(wsrH=$`(Q>01Za(YLyZk|?$-f{eDiBBNvBN5SYAo0qk1I5&0GU#G2u`zF2UcKMC1>FY+yrh$;x6vAkUf25wfi08@} zcslRvY8U5&Kc~T~TKwI^dfv?kM+|i0gh{oo2YI|%aqL4fXo-JXfUQRvxM#aOW)rbQ zrtsb8O)a@SY%qZfml<9J*PU{+yvYWDE~Zf0za{VYb!YLT3IFJ`Yz7U zt^mOXN3DaGS47R1=EGk!Sl7DfC2YSTp*CaMdIZ4(w7!&ua^2G4@LBAv$4;)tFNNxE zAyKigaa$7o1cO&h51@ypqS_Nk=ugQ9Lw8JA`BQk*JNml&>sKJ90Dh%)6tYjMWXs-#3;IsF5BM?%#8 z-KDa{?zE*7jsL#%y%f22I1jR^;Ue_Z`tDR2+Z$L(PviU0ZXFkOG&qR$aye^f@Yw9y zl0_QjN68(#_GvC2w?b=_h{cn9@J15~NHDInG7M0LB3|_F zXjw&j<8U-yG=Vg^0qbqdbX+0D0HC{e#}TbAdp`cO^oM2e_m)`NVD^@nrV3VI*2<}` z6)5zl`S0vfaglJUXI}g7nYm&Vyib3rB^F%ExoZJoWZL4R$rpgc#xQ8ex-8?Bc9aEr z$u<1yDoZ7lGnyi-#kC=pNyXhX?F`{~>iL6S1?UEYl48}h0h0Ks31uztX834UCzPDA zO7uw58Zbt6%sUUtKEKi=x;?F^+5|@4jEV)%9lncw&yRlmGv6 zhv(<-2H@|UBn{$>T*6zu&bo|#(k%)*pB!aQ9f4N?mbhM%ih>Sg{YOSYKALoGKn6Z;QX%v_`|+qT*xvrY%sqZX|hZyj5*ZZx4L@=pHZ5^b+7sOwN) zeEi`VU}x)H_zX$XKo@1xDu$hbjhOq~FZEjso=dRu!BM`t8~q$Ztii@0^GY+}uHqDn z7CEgXsDA&)p0%|F5tmJ~p#h{X=F&LYxiogEX_2tRA>FbZr{0XUg2CPCpCaOER?+NJ zrH5DU`~UaOH9{u$_5wMa1KwzAT_D;pU?$Ih!xdM36R>Wk#17nV`nUq5Y4!QGB!if; zS2QNZWGc3KD6dJGGofrbs+c??%S!y#d&^YS1tKO!;ovlXX?r<$?@%8!P(af!*t;(STXBA~4O z?@oD~X|#1p0Wx9-4dGA>H+oN+hd4pPYBS4NTGycfIqIfdA=dBs{!Wl{L9z|0G4CoH zKHaSAO^(O_iQ8w$=+>{xL*aj8nf!kwh8^cFtI*7UEIC2G&e;Z*Y+lD*+NG7#f8t=7 z0!lIeeTAhZXNvi%jCEKtjQ1wbB2J0f%ReZuJkNi0I^17sVl$H@1jmx=_1mXeaI(>_}23jeIHRpWPCy2 zyd*G3TeCgz3rpRX)sn^{YZJuQuU%K44un5#qqI05cGiA!V%30GdfjZj5MST@uoc1D z7P8sKO{&QAesCBXw1WZo`SV#s?H^Q5PeVVQ2bn2he@sNyP!vYcCHGHIk;`&bzd%&C zOa9c91LO5ifgV}{DVU$pSJ_Al@_%hkh_fg`0zmj%m%N|JUe!MfiGIeK?#j@46oAY; zFzURfx1eDfw&{E(en2$_A@o{^@h-mi(r1YdPw_*2JP^qQj7Cgr={{rF&M$kvm zny|W1FKo|X3(f;goLlZ?-oUw4D|L;sF0)rGCpBx!N9LHEQefk zN`#6qdu&Gha9?`(`MjdscrQMzSFtv1v(@>aBY>E&06LVUV5eUqRr!O5qDcqeU({TWR_c z^SaN-*35&Fe~I?R8A1~%@IJiFA^C}NGsiGP5P|&E*&+iTfvJgrt3$3v_NJ14n2LD)pYA3k--B$;ioPR1K1=Wn(-?yIwHISL{$M27F=n!^45YmuF5Cpy^f zN!|yZDaddiP&6N8YIx%l1TR{#KC{ev! zc9Z|qdm@KOMa0G$wVv>?f|t~UL%)(AnUH~i%ZlG)lu_qJha9X({8VrnQi}pdJILC; z#L#BW{R6#=97^VSn+(=g4;oZ_-peI6Y#l*Oh>IA-&HuevW&?KWf*J{vn8SIRbnOR` ziM+k(M#4a9>(>i^GgS)~%f%v6wr$&|EoC&*=yZt(qLLePI96d&PZBh|SRga%Y$>F5 zZ>pGL^MHkCIxl78b}x?ngX=t4^2q8SZ>e-2-v8l_SLjD~*yM8_?iScS4J>1XAT2>K zno+jQAt>#Ge4;eATO73TxHi$4aZKm@y7Pw0YA`@V8#cH!>`}awElb& z{t?enKw-A=rC_Hcfm-+m-F<=I%l9k3*v+rsMoSEGKxLRQd0**u?60gZ%U(O3sjfU* z@*80@0x|^lX=cqZ;0@hR+P1Q^A+y*`x70qCanS$dLxIaS+oID|8+E_05duf2)n;qU zTSAIOx7=tW=(7RWaN_D1yw+*bZ=Dufo#BU0fv>GL4J>U_%2@SXRiWgK;<5*;7S`Nuh?7T6W(ge*Yn!&=>BK-vWuPP|N92KNch(ipe!Jp zA>n*uG{Jj*QBLQ)7ojZvCu<|*bGRWI4b@QJjQ?iKy|fFf-dbKDiJmXzqn5H)5icMC zUp1EjNF@O;7v$nwf+YastbPZD*9r0R%@x(mh$2>Q?Fv8zFxx6;@gs|$gk*aE^#|UD zD;Edl=nmgnD8`k(05X5Zk2duswFYus71*C-GcOG25D;g3z#2G+jLAE`RXm=2wJa4*(>6urhBZa^zi;4dA!@Cy z&ph6DMmMEMbq!lnd0+_ote=JZbp}^&dwMhusd`)<>P#Bz*0!KYe{g+R3{DFF@yak4 z+!z!MbDF4Jq^x*^frRYu-<|}ILIIgqh1lU)wyiw1ezfO{I^h^sI4HwNa1=Owx)@&A zAY_BvBNUAb_LBM;_-LHmb-r;EiF)Q^)4KF>S+bbd)r6mz?;G0Z7tlscVq7OA7UL4Y zFf-IxSyfNVvSS?ZYpI?)q-@JjzUbNU61v5zH8Z6DiQSX|%cmRCEHk`zPamfRKUi)^ z3G~eD@%0q_kJpjjT}(r@8U_>Ns`F^g4%hOOFPnMG9=rA)L*r3?CR;vE<8oi%q+`ahbm8)^z$UrR%9&8<{QU?Cmagl;kYg0ty9JI?+3zv7XN)6w zrJ<sa6hS@lR&tk83iPUWaRvbxvBfk8H64M34R`@iCD%cpFwB-@iAk z{XZdSxnt&r`1w99pVU7yCFOs20LkzqkEDtQ>6C0;5=F6obmeJD9eShdz@nv%GS|j2#;ow~Pp^Rj4Brrfo z#!C!3$`8rHKAjiMu{bI9hTS77ak{xONAHHLezATAOdw!=l{5B)4CeUpSoJ2W;C?sm zMq)I3m6#(^uJ4L7q_6%))r?4!qHD_vTynhSKDk_KNI7g&@ZP_i4m~fu*Pla#F6|1` z5HRMM+%ggSZRo&G;s{Sm?B z3Ce;xy{0k%pD;5Q^LzE3-9e4Zzv%K7nO&X^G1)Ev9>8$F-_UC7&^?-JgD_7oTIxa9 zBT9}fAZ}lQ)6XCWf_$c?A`TtN(-?qR4h7;Az8=5s@}x(l0!S%$lM-B-V+au%z6uNX zJh5r9Fcv+M0Y<=ay2WfU0i&np7ZF4by-(>l)+-KBmfcXz0H$`JDGwhCtvz?hbCZd$ z0W(!UYcAVx6g%z=*!3qe>)kdVM&r!+A!H`%Poy?Wz?%ZBt<8UJ|05MihDg2WGcJ*n zU#!+~X3=a}luSK+P$LAxLl!rIuZNA+huJdbf6(%>ZgB>oWeN`!|4WFPV6`(iP-K3Y zAy}L7^E@x4C?Y4-fZjB`(rF?7}~ z^EA2+ggH1u;l9BhZfO zPJvJP0}<&mnN6Brn?qU3VJfo;I~KG-M@|R)#+p_GnYrmT;njCR*58L`fznSqTI^~(rry%hOP!lMgbw>66*Xb^ z-4)(@W^Jm8l4_*F3M~<48A~Zs1E4R=2$P;TiaZ0mx#xk7f6zQ6M9aVkNQ?pVr<;H{ z1$7uFtW^I=i_6wDR(gw9w4D*K*L^r0!{UM;&!Gb>K~t;Y@$@B5da)wez{H0oPmu3l zB$GQ-WM98|guopQQ@7>*YJ?8xH1I@g8Olqyi!h8*Jdd)WZggyHQINr&_#Lo1VhFU&UCOrgg+seUZTKq$H-vjr@PqA*6g z8Kb3@aZ-=7UVe7>#e^1SRkJgzz_B#{+CbvLT;Ux1wCY`Z$%_ zHz|c7iuZKCvzmHgxv%5D(B+kn6Cygw>4o?0tmK&Q_k2h@%*B^OnU-b1ShKMWiuQE= zxEeuEdHoTahm>%>#N3fHk3|5JgqL(heR8dqG9V0JwtL+A?>-Mw2Qi$QvTn(D`B$_> zxvR2bvbtl+Vo(Y#f%cCTNNWk`>FuuFy34+t0fm$$>*nu~pdpLceb5l;>>dF+5|D;J zjaMxCMS-3JoREJ4FN zV@k$Id1-DodS$5#9}eWpZ*8_&k)Y>9>{W#o_#JYXv5p@F8MbqCEtbRCI6txb|3cQ9 z%^56&R_0ur`Qz9ww#)$#ZB{yQhSO;5dYEEr^LK2ax-99_e%-2ove3AfBs#kiBX zzwF_$;B5+J@5Rb-CkK|vF^WfJyw$-l=a=z|M~4#b3w%{e`{RYJfzymb6P=HE=lrpWpwE=spd{;S$ABAuo&uFycMTWaJOh!K z61C#@SA8i4;{On-WaQlG3zW}-24pG@HouB6Y&!>x zdEyxGDVDt*lF1Nd&M?@CGOdiITaa81M{JNpd-d;LUidFB2MSz|WlR=L=(?NSS+Sor z;?*ui8ADsh2bd2$GDD~BeGZP=ol51e*v0H3D!)<0AxM)J{K(7Y%x5|caRhh)rmB0k z`p45a{)UoBaGMMUr^9wCfpfAg zb5kS+fUj0VF@47{TBS>HvXMVk|IUER+5ui%BBKb3<{$5&>~Dw&Fat8#NiBLZs1`OapcP{`5{P0?sHqZ z7Ar2;u+HO#EOA)5*Ur88b(nj2p`JabbfFfW{7{9<_E2m{4`65X>rK0?K{@MvQf+>+##p5J(uVC=n)bA$2JV4R<&jvBG6;{b{E=#dBxUH z>3U4-Wa)jdQij>#-tg0?U_T1@(b_o&R8V~yFEH{>gmvL^tANCO$Zmul%pY>6RV*_A z(-wQL*{QeToa|X1JYf4VxqaL#)MAFSc$-edRG3~^uiO_gs&Q5OG?AQ^JW=$QAeKez z>QVTyAGJ{tnzTFtMnJrFbMf8{HS_|4a&*Zo?sEjoG_{qW5?x|fjh7|D<&4FkAV!FjF*2u^lGx;kqepCh!j8D z_y;(1s8Z9C@^x7Sb-xHm!FC}Bq#o0IESeEKM65V5oZJLcfjiN+$^jA*!j&dUuH;Jy!O`p$NIpUsW(7K ztY>+y7cqx_QCY*>_8833oP6-|5T*W!WoC7Vo#3>D_@ToS0@W^2UoHPjhKHO1aqQ(F z%sVIH$`s6dq5AwI{5@1>l2L!L8N!bU4Te&_TH0C2iEjV^$mbRHf`xoFXAUauUKc%Y zJ5YnNACD0fZ*6~)g4RiUIt#pI&pHWxRbxS$N>V3Bp`J9mEjW9bdtKazj(yutI}7yd za9?wE8q#3>YbvrzON@l zrU?U%q5xoynV-ea0HWFXdxw99lSlTd(u(P$OHb(wrgFG?lf2neG%L*j@};p{S<7Q_AXuN*qg? zv*<4ROc&}S1Yr;fyAQ1<_>-08y_@@bzz-0R%I0KH29`PJ3?2_7FegE8@%nHnj1U}7 z)X$_(ID}e+WzGU?FFAbibvGK@@D#6?5f7@$xA_Udj6V-WRe|ql3jgiJy=DO{vm z2ON|n+6%`nS2B*^4HXBT(lRLLMKI{QXFl%R`cv{l{bIA)f$7hGeX{&AFsE6adA(I9n28RFZhs9}qe#2vW`Ixbthrqq2h8!U6`RiC3q zjQJYNz$aI=D#2e}ByXn~n6{d)thgbRO^o(wBy<=TO3dRNx)qW8riwRl>hYpHd?)F? zTqVw8#UE4N4Jn*xvwy%s?J@b6<3Pn2vE{p-Acs(-1rAD$kpK-(D%uajY<9$b4Cd9( zzO<(|mp6e2CUDv501D#YE!q2^h=b`}9*xtP*Yq?V2gzIu0~SLNED#9XZdnyWrTMkc z%rJ?C#4e-(fapc!>#*{Qw3mX}C18^>eG78Ijf~hD_u~;qoE)RhW)k-rw~x6uL+P~@ zbbPIbQs@SAXSTRCZTYLuSAdBFEKC!ANigFzOZaW1d>Wdxju-t$2ZF&q!~nC;M+{Y$ z>BC$0CHSJPJgThG>b!iDqwz`SjhDe6sy6RY8l;Clu9Ux&mQCJP-r=8u~Ee& z_6VQUxw|7i{QqQ|=)conCW4J?Lo(-?A+(yrCpkE=!GS)AOmv5E&k6#+Sg>o>!EGvl z{5Km2tP$J3TAD>K1XuKxg9NBPK5Kq1HB<(ccv#uH1cRGDL<$HOngpXH;TPE=>}F zBh+w^*)p~k@v5Mma44PKi8jEW5;=UdDa|l8)5^%6D(?Tw_4_`1RQ`X(`zG`4QP@jN zg2^4?Up8fzB-#L;5Kqxz+X|p65patP$pB&&KDU*vzCYOer6>gEkNaV;^#qL?%cQftO<_6Sg+d}9Ghy0x}8d$lbA19y@xbm^<{}vCE8_ATHP2tHO(?4WZx|#xAQt|Dt!N zCGhlPnB4*%C6|B2Fk6aVSdLVgz8S(2dF!hqE7)YIels0)8hrpBXHMP>ja#{=!kM8h zsNj!;xWO=t!aSNv;zH@ZgjP=30_#u2Gho7L?h!!0El zO7gbzafGf@7dA;ASELytYkVjN3(bRgY51YqabJ!P+XR~dibCad?&E9rbyE6>kMRE- z{klZM2~`ug!C^m?iAPPBiK*V zCika7x-6mrZ$(hruUV%hT`4s9?g!7F`34Q99lB_47k@Em}Jn=N@7gdp!2=Nw*c z5}t(woS)>0m2GUIU=z$GMv%dhLGg9Aq~du!1DqMP#_>B8%q|o&>U33zBBd+7s3pjJ zox{PgYA=p2q^e4eRE{qcfDkxa_Y%>yb5!_^7^lval$-Hz4T%!XU<-*M4ZVX*Dxky{ zs^-|Texz{=PvAV2_rQ8R#H9Zp0_onvXoa<8!R$RyE}bCZ39B{vK#>Y2O5l2>{ym>S z;(vw6bQ(&S$S%ql3|jLN>yvnfh%d8ui)!7u`=TZwEvcw z`Qz^+i#?H|lZ3p(VPa++sYzeSH4D=W_mIWVLP;rg`7jp3U(=@;yPy@Vh|2ooyLBVH z+U~H@7(0>g6S>(-I!!8}|NIdObstZ(F^$S3hz9_;i@#8TedHBdA|1IGbi0PjHC#xg zuE-ki888pdf{aOO4v5}4d}u)HByRVM4S6?~%C_EN6&r^~^^DP4-i5XWhlRdrRo01u z*cRZ*zYV8V{5bfUMZMLqcRV-tgR19)W{WvOcRzi%mRAVNgV`U}FXegf@Tmf#n^?MI z>h!-z(`(L}_lqJ<5Dv2`kUdOo2BSg%>6_tTZP@30rqp|?MwQnwIhUVa|Ig0I2B5n* zXXU0Dj_DCGS+TQPie+I_e%=M$?To|P&DBGy% zX5Q*TtU$77ap1Nb_-WBsDfVj}n5$5JA^!f<*+O!Z(ZoVK&(`Hb#$iS(s~#YO@_JiaL*tjpna?fLa_QwhXejO+0>jm4O}z^2joftb)Fiv&UXjaLh6Mo7Kx+N~4JbUse;3j*K0W$~zd+L7hy1C&oRN zUPwyWl%3470ENEm(xcQ5;PhwdoG8*OSbEqltx*$r|J6!N*2SnQOYrVWwO27SQ0dLK z@R3bul91nbmIV}YXkx4%r?{9^cigbPersN;p`;kMAssTb!;yk0;h>}K!b(hxfwlX9 zN902)RgBqhA~>BQQsV{x&(s;2u=iTBb2={Td-quF*%bT?Zhgi^$M=2&WT80P<<5>~ z#TP(+-Vs~#oAcZR`Ag4FIF|fve5{iPsj-Cf_@j?!Y%sicMh+sV1CftwB^)KPU(UsWJ59l zvG$>r+u%KixCSU-08os5+8<2OVtJU|>G+@P!$;T{ox^h-zfJ0LM5Q9hs^%;3Z4_s% zA~nf+%kD|^{ori{++ZT2P#dE@>2UtT)wF%8eSHH#}XZGnb^(?8W1(lB-(I4CS8&W z-b||w&wkv;CZN?U_evr=^t@siP?io)fm}QUleu1%gJ!TAXwI6|Q7_ci9{dGVId|}z zpvc!I(#TS3l(jR72WQe1kw1hRzntGxr_}&z4D>!Y3X7D#=WBm_IKU>T9sbcPcV3eq zWR+{c%B!=FDrZyIpzcu{HW2VOyKW-=mab ze{*nq*l^gMu*+k!P;YUQ{ye;BsVHaL_EPs9kBldzqLxJ|I^6ozXyCE?tq60WO>F^@*9TezEL(EPuM^U$it?xo_UEy2I@P;pfK|K_-Ue+TrKJ7v!)@!ziU>Bk=jo5H zO8OVPV*pzQ>xxrB^rF|%x<8++M!sYUJ4qS@sRqzJMJa)9gVU(QR9jl3XOIdTRSA&@vf9Bw+cqjaT zy1)}>kzCN3Ha-Q(57$3I3%b@tgxsJToGIbUaDj9*i~>3Feu$vT5-rBLbHajVvQH0zcE-_p0MGRME;#YM}0v`EEO$Tb$P>rr60QpBU(J^G;e zQKsw-Vl{}qQwfyR&ws^+O!!7OheR_o+jm(yLUGs4+GnX{Vgvfe%H*)e5{w*{MXg5E z3h9DB0y`C(B~}TpV;%fu8}9UmOEH9xrh$W?oj+A|_mO`$V+6gxDwF{c<~Y2 zbP9%{Gj-johv)!NY#4#ed=wRPP-=42TUe{)8+f0eXh%~%)AQMD1z;E1+j#_Q-KUSQ zgUPNACEudeFY|uKMc|Tbx(w)>l(yo3?{VusJwsyyka}o+SmM5b>lsLyZ6^NUcKHyg z(C{G@s-is`sXteeLX}E6L*NylTM<#8x`-kC2==aa5xXo7s zXt!A8F2-t8`uBhe|C5UDuw+rsWBWQO!}aFc(z%6Y5boz<;>tVE)qw(o2iTCu@NeB( zDB)1kt>0;sp#3j*mwj;579W=5#5xblsNP$R6FglgVTPx9f8+uv>po;wF5fE&gT74{ zY)3Cj-}7e5=jwD+)de(;vIo+c4!vE0olV&+dIKl&r|H&6u+??)uKUUA0ePp~%0mIz z*l#?AFrS#Nn=DPm(X}LfS3okEb2Ty ztgZZTl=S#nf5LlrNC=STZTXm{0>^*PxjY;Z8UP1Z6CW-F(6y&41wgHiRj2vkI?2EX zL>h;%K4c9+Z`eWY;^S4jbf#vdeKGD&pu2UZbLayA00mh$qn4^e?Jv9?wyHG z$sf4LDD%y=aLDSA$AS0qUC?g<-~(?Ldov@5I6=l29GTg2w9d)kT$_9QpB&$BKym;F z;%+@`Nildf7vVD+K2|8WC=^q2h5=15e<<#|fO~sg8q*rDDQqE8+4>leo`M_Ab ziJ*XpqXOFA$yqe1s#;kBFzgoonbwgsF|&Scc$#4VqeZ=fq2cBjpY(SoF+7 z#cU6)%JSXy#}tdekVy{c4#*l*7D>cWPtKxCeAO{zl=3D%Md3S#oPAj#N_tAdpGh^) zlua~hd+kraMc3n-QwK>jG?V&g6v0aWhs1v;7}Bm3Bsn~$8Kc0$GZJrtAM`{z++gv zz2cO;WC0)CK9+EdkawAxwld&l-kgxw^*W$p$KrDz0v1<8z5CR}xyLzEfP7kw>)H=2 z%-8&IfsnhH65hpY!~4X~Izh!3BjvnHxAaV<$Qon%ZkL@c2*C~&2cl4A^C55s?San) ze+0CX>>kfPshl=I8nkwuTdy|kC~Zza91wEd!y7{G9iI0(`=@6Pb4-;u4HUiu8esT? z{93{7{ojiYuv#B3Zqtfg^7vJ>mHD)S&tQhkw;&<;WH-Hv@;mCSs9_u0U(I1}T&K$WXU(WedJ= zW&XfrR81ycK~ae9?(e{j{W?gQ9V%NUh=n@m??fHiBA%^%L=Rc+T9qnP+3uo8rf(l> z@7nWQop`Unrac0dIT(zZV?(H+X zm^yliSlaxX*f+gJ%*AiR#YfDS2{qi85a9=y$TUl=rN2w`Dv3B=C%iA$;BBuu99v6Z zI^*?b(2rhh3ecnByv*e%37W%!w%$GccQ#~apm&6fc84jh@SKmJOp zTId4lP@mUEp8(UOZM=|oVaWMbcfsW(Dd>FcXPdYzdSLeTL}tDP79#Q#g`l#)Q;|{v zYkA6pxD5(rD>a@XPJ1Enybs`s5r2D~t&Rh)b`fN3*Zg>#)Ox>`cIb81ZTD~lj)&*n zbt$7xb#WS&2m1nDO&2M_WKF=8Yx}>jcoV>NvutngKM`-pohXzZoQIA>WT+ zxwx{Nj0+AjH0%k~=hn^S;r|4K<#LDn<0Bip@u2q*QhSyCly?1R3jT@DM#MvZ^P>7A zQ6kcP_*+K2Tm0A@u!Txhw4B2}EG5IEQl7YKHeyo9h!S?3#gD4nX-hO4xJ6LNoh#Kj zVJ73Jh=@-axlT*8733fN#Ve;8Y>p{p>+){*$zlv4&CdFQLbXFrlZ=+!TEme3QpG=* zoz2wUBzO5q4z}ZR<9!qf=g-~|l-HA9?Eor5wq=`x$Tgq`X3c{b{*HLX>`fYMIWQ6W zK2+OOM{F+I?*SBzM3V}Rb@Vv?>$$`MD+}QawM!Pam#>qlCDA!mCkLN-dtoo?9k!X* zACl<$iYZVo*MkU5m*GwJnOmYewLC6g&-)y;M3}z#3qNG~FNnu?AYlgM^2?(TPC#hW z21iQNSxgq>CFaLP@#qsIA6$&e)BS<>tTWn;{7U#@qTm1|`9BK|mnY5jSbrnK14nTdq2x4~z>A}k6I|WH1c8R6DV;gTp*;Rq8lc6#b4#6xR2W@)7Qi&5% zI6<}|^*olfskc9#B_HP;3Pxbqhu&vlDr;aL3|jqUbduQd3GjYgU)PE1-fy5;fB=^;E71#)qPJVTDSbTk z0nI=;d!Tl6eNyWaQ2Yr?sHRafX%>@xL~%~(1M=NfGiB+QKcpr+dw@w{sZCJXF?pF~_(HGs|H%wl7&y-x}l zm|tCA@$q^9(^%XAP|fO3WXl&J*yDbXl{^LK;qWOrKFFJ*czy!{1gY@n*SQMqFN46_ zXoTDVQ%f>vHkPlJ2%Q8){Q*COh(MWHyX6MNb^qshRas5v551rkFx|lSx}Fo^v6>7` zsFD#p>}w<^d*?kHi4BscdvG7JR%L_xLH)V<^seeyU#Mqg$M2p0*E!rQz%{IEhX!Tc zyi}347eLcbSR06RGIF~L| z?Z?ouip?Fm?qy3l0S|$EBR=Qv9`KzfN-Q)>*g`o((q&lMS65H zz03Gm;uXhtt60MKtKXDb!FKY2NTJ(Iuj2_Ibt{yfU@eUd%2C$$tm%stCYK=jaR7xG z2(V3$cYz?K{EPcNIz1kk{R&%)TKF?Ld$Rl9@Vv^~)UQ7oDmqU)mG5H%Z+3dSk`u-XinZG$ zupOOZ69g*Pl?2|b$!DdmMJ`j`S7B_{7Zdxx1sp&zx9I+8^8HzGrNdJ)c}wR0wR4gb zsD_F-U9?p6CHjA621zuqi)ORl16HA1@nC8o*5+p|Z7JdH4j0rfTAVY{CHPT3flz=pXfOLZc3=Ps9LqB`YIluEi z_kBOFp6hvaU%xk81AJ$H_g;JLwO4*tG&?%`u@C!4kaVCZ!sIFa7lKO(+IUEw=+NzY zx@<3I>Z%-3aB@FYPo&iT#>j_F17Rn?Cja^cxE`i#k0o8_7v8*=d;s8;ti$MfIDQ#4 zZUF68-2H5GTBhe=5Z=%a@bv@wB3-uUm8R@qaE*n?nE4K>`-Zizk@udT z39 za+&!9SH7De02nt6zK7ueqVDULZ3OyP=Zb`^NnEC4kS+=2qyzQClTa|&z#y6)$(oZO<(b2B)VBkFH-Q7 zdVbf43$VWhTCT59kaj&^#TR;P+flJkv7m;}+R8rz)^ zn|b6ZpVX@A?>0*##-?M5yGX#P?qp*RC_019sd&BP^`M2x!k5MCNXTFI=_E_HN zU&1;j-6)X5$elbg1BBP^O%gvYm8Ql~O$Ipns+N3eako0C1a5!E!O7~}eJ#>e7K>QG zu)?NpE&luNxv%3|5Goqy}I$8M3eBMoyI!P+pv)N!s zfZbhIX4c7H_job^M9!-qxWMhweVFzzmg@E9S+fKH4*YI!@qRY?<{*?E86s@~Jg<*_ z;@qoFE|F4nf_n=mrxdDl=n z?Z`(kBymplBX2cWWsbNyJzlA2Mly|OX#wJh|7CtP>zd>*x_-Q@l@MJK`B#O)`QC5l zmOx~9L8E{Kghy7d$`Gs~eHg5JOzU<%&IL0}@~={T4sE6i^p#C*z`;geE?rd3{T%nJ zawZK$xbj00C;=qC;BR_%{G!xM+FFXMDwK!w7M{aT6`mGn#Lt9S44m~0T8pgPtOobM zjOHgPM+X#KvR3jHU0U!$j_`QRGgK)X?pVDAQYG!BLRX-@ZEPIhv`BGg;0Ho4nvCyS z1Yg^^2CA69-bJ&kL7U3mmY8Gwb^_dhvDA74R>yRs5#oO!Xh|EQc`(W600iuE&=w@FKKU6C7!SSE9Q-5#cO{% z$N=>|07P2rrWg=a$IJr^Zuu4bkpK3inEDtJpMRHtxDjsho0s&NOIE`|Q1x?FY(fI# z@5K7@p+Ku_f6!YT>Oa6XSV>ws+D1+Y{duL*$f z!rQQ{fu>bgl|0QvhBqK)_j4C4q@9!%o$Ce27k(8y7=H7LirfD?<3l3GUAM01TR?b)t*^mlLNVdBbzUaDn(yiL5DM1-WdCH~nnnesOEr@8rmsQ`a5WhaFR z^|PDU_e61I>2I5c8JUBEd2bT{E`72MdP={VH^-`D#4jY}G!Zl)+f4-r-hKY-=ktu< z2h4>`IWaLQ+pTz7OBAH${P(;GrBw{21v3V3|8RMvyM>2AZsAg5(r6WYc@I-EBO^x3 z0UQr=+8K$y@W;J0R@m=orC}B1*?iNUAW-ben9uW0?Bh1s&mBen%Va_OE(EH7yd)Gv#lXp^aWXidW9pRh9d@8Z=ER44M8ptoD8Z^ zrDC@TJIQMR>yZecBVDl!f!lK7Ebo>WKVgGIEvgHGA13(F`_Un;);fi_rbeE(&um75 zF{MrTnd0VSC9Z(DBs^uJ`9*Xz$`cZT;5;M;#=w0ncXA^3S1_a!A%SARJnLLmxQ11X z{KP+p>+{e7s4O-3K>{5ykKN6%z+^8zz0aW71j7*GYHbTR+&7>e*Nr zvzjta!YyD0Bu_^hm`=-t_{x(+$>7yxsEKdxZ-tifs7!t~m*t4#j0HZs|BJ)*BxJ=D zP`V$l`15ysVg@&}+eA01E5i??e(;9bdd;=)nwTcF{ZvZ9Wtvpnz6`(eYM5+*&7%=`@rJf+FK4b>4A?NRZ@9vUHFpj$*w=*@}a{<|{ zN}vKAv{)5RZ;@wU>-gq;oK9{+)i3rSH2&ccKGS_P3YD_I+{T58=@9A}L*_kncOoIA zjLFx0>bpjJ3z4puIXdVxNdk29)S-7MHJqgQhs8@D4uRSRU|pn5*t@Pgo?V4km6f4t z(E~UJXM0ji$D3H-%4dI!F;q=JS2iMWEZA8^RN*ETW!5n5l7ly({_*iXUZb~v;4T33 z&tPEd#r`Mg-igk~mHqLavn8Bw^J|85H4EtP8@#;}^RHDgY3Lg#AbR!PGX(mdT^nFi zTe0BEvvK}n!|VwNTT%h#>3^+0g&M2NSUEBiM+uY|GFYK2)zPat{AV@P{sSgTeD?_| z{&)zqbCNFRQ5MjYsn1KNiEx7!046Q*w;b)sRovCTMR_axW8jb(s0sczy<+ZSDx8TT zVh&rR>^nir@Ai^F^gczsW7G`HT&Vku>l$#|tl2U6jn~2K-BY%4P)hv!53jdymV~v( zUn$X<%@RR6=(1Q(%m=cg^KWDDF7)isg)lc`<@Io zI|EwK(2@ZL7zqyLkIg@A%)D>3SLaMQj>8Iy{KyRmBRb^v@dSf*OVQ|}%Ri`N)#v`u zMu!@BMem8WhXWi3Q0j*r6gN90CZ(ezAc=n2=s94ZQcp0J+QDMv$A=fCAT#>kFXPVw zMIY$yy+k=>)M_>8oY@FkMl<&$e|jh*PsY!&wpoY=4SezV1Hm!mw;{kvtD z7vv~RV%3@U!sCb$j z)%<-fFMATqm&?}vh*2*EtNR9O;}sGeg*5D29XKE-YRxf!%f^2`v_3~C(hPrilnx%} zV8adiPws@bhT_Z-Tk`$2rp; z0x@X?<+t~qf5>8qy=|ixIz`=)$-ePgjk;rAMK`*QnK=nkuvxU z?i(FCFiOz7k|T{tG?d~w>I+$fwP3<>8Fc9m`cP?*;$p|MRh~=D9%Ok2$A*gpXia zb0zJ%p=hv^7AaCp@MB%-oT<78Q(!N0r?Vo12l-k#XLM#ZE$m*y1xoEF{KjLeDumZ_ zS#bO7pM8jbc)Jv!t684Ow;}IgCz;{vwOW&9%LKG zBi4i?mKi_65*tc#vD5L7kSSg=eVV#3_7*E3o$)b1H|PN92cZ3~lM40XqkaBTm4%RS z!|!QvAZHXnUO=dt$d48FI3xF#tb~@VZkiBTS<9O1bS>Y*)8msE3ICM4j-M##l&Gs? z1ahW-e5Psg#3%~u?9=)6S>{}|A^&rQl1RNsd-Nn(H&OoZLd`MaQ6Ps_5VaFKKhG_m zpIn>+-OvZY$?UAE4KR=>HHLqASNct+iY$yi#}mLJXyD$6P!vG`6apX@b+Oq?6ytii=PGXjnLs zs{ry#zmWXysRr(NrkxWguQbGFqiZ}TMb^2b*QP|?MgvAkveLhLd0&mHIC1d!R2N zsW*^CY=sxTjYn!sY;{s%)~MC_m!NvMi@fXA&@FDSC6ipr{&sAv-vV9lRI|{1Ai-W& z#Im(VbIPvj*E=w^h_DJdAij8?1bt~d8$ov^Qf&Yr&rxVlk@)$0BPk+(B2$z-x*-oz zON$o_YpN{wi*ZO&EX<(5vxfgkh@)rSGk-ZWj7Z2%gV-@CPs}9|rs9i- zu%X)y-0p5K?L*^kY8cndV1ee6%lH=ADe_%2dzF;E`nCQYS!2v>eX=y|(XYIDB^}qN zxh0(1XaF1-oT7ww8-N6kq<{pQDFC)-3U7x3h)>qDpRX!{_$_;B?t00N_F1%Kansyw zr_yaK@Loa{FttV6n^SyrnDT>U%0$Mi$+n8N7nkJVZc@iZt6Iu@5ulQdSi_S6Jr-Yr zsD?{iEQ9l0@g_d}fi1eZ6zC3n#M@=-I9+T_Y*8~z|E>5m1uxu8peK1If}E)5xfV7` zuH_$c5SLyFMc!abxG;ROUuBLKGaV->LszP|00sb>7#*_vJe~_47vcdYabdpb*kK3$ zcvQ@t(y|m?Lqzx>$w#fmdGUL_tNhlVQ|CZC7T3{HggiSTRU^3-&l&)2;_{MHN)h#3 z!qyvPx{ELnns%-s#{Lym4*Gw9AdR(VnB&b7w+w-gLqIGD7@M~Yic@mySAwd)Nu@D> z6F#5&R!4d*7w&f+ohIfz;n%t2KX<&R-T}}BH|EOKPb9v&4FpZT%o|ZHG(3^4Ct*;> z9CD4^2AB%D^gaMqzs}@zlKz|&pqA9ze2P{Mc8R&ex}L)|*=ty_-V!dZT|7HkvXj9j zcpcz#J#-Ru(mZGB8I;J5ud#dxf= zpV7nCn$aEUu07Adt?#MbXiJ!goH6ZDQEC1?HR88*XQ z>sLyBpk3qpyy{N#=looDo4W5DgD036L@Yl8m;%F^N8VE~%N-^gFEVWR4(_goo?eQsgt2*ar!jT38YDN0u>=6QK!6`K<&e>yo$C>?<{ z`i`ALr3|38GT%9y%Fik-CEVrH{cHVJg5{iMs~Wtd4(C77Q?`f>@lG$)Gk%fqUm4!x zPc-s%(^TDtDSJ|C_#h5S?}&Q&uc;4E6-vC9Je~ed{yU+0FIux$$+*n?I=s?O*kLDG z09ksZan8o=YmZpo30O-OXq=Q%JAw_AdLHa1N5nVb+qC=IEQ=>LUoRt7##NH*+4E1D zj)o@V62CwlrH^1$LC-t;jlH(3G%wYyXiS$!qNccKP-vXcd`r{zLegUfu?PP9y|1&c zGjn=YxOK8tmG6}%DYJKZ8>teFj2+I-%;0l9f?(mlR>AW8F|@Un*MhR^D28AKP_>b| zIFX(+GR$=lUnk7-M70O}5%@V=>W!SE%E`Nlp9?;L^H;%;1oJ0j_EY%k4mQ%&cbab* zmY-(3eMOh&t0}^c@!$5fm%+jD%>p zs;D|3IUer+s047SqTcJR?RK+(JHJUl#ZBE#uChy;tMo=w*uy8BX7>6r$-PyN3z0tW zQ?E>rp^>pZ+d#yG2K)N(*ogkIQZk7s8QP7Qwh!$%o2P`xYk=go`wy^-JMg5vRH z=Xw2Ne#dL+?XG01kEQn-~;DN}xKF#@)|WT7<9)n4WjOM4wP9}o(t@fLCe0tv`$W(wpI|G8qW|m1}mUtkWkidw9e)VCZ$d=;qa4=Xx1-L|4;{S}z3Qk3~S~rrqxD z&NQ#C-JW*Y>o1pbvscazVHwMUY+N*Pmi|!)(VN4T=2b8$;XgYc2c13T z9s4lw&fE3GWsKwVq>F!!&%k`#hLB&*uT1l^EibpThA?Hr2JThI0=q|imjKoD<<1B7 zsGu$ygh91$`zf82=a}QrzBo(cu<-ooGMz%YUss9imZa}O_JFVqM)9|h?eGz0gNAY- z9SgqNqcn$hJC<)li~Y-vdw|;=XW84zD1lgRSaHl%3}oco*qf!kvcfZAlEyQEKz6Cl z2r)%?@(V5La@pR&vwWhB$-wqlJLpzTOJqLbqkA&~!cIo?QaN@D#lli&zTKPcsad)^ z=?mK4Q^RJ5H}uBN9N4eiaZt6(rB0JgK6}|J6onGxd3~qWTZw=*Yz~!rq2m#yU+P{T zT3W&tB~t7fD^3 zIZvh_A{db6C%ZM*7ogB1V3M2mfYGoToRf`9kUQ*SebC?dsrhX3kibTI$liEV5m6>y zfr;Tudb8zG@XZzoWRB;M3cHNSHrD=W-lHBkl+)eS)CyU&q*23FipcpwTz}ly?6_D+ zIuX$1SE|0*UEt_rv~ydjhX4u!Laf*;fx%pW^Nh`cD$I( z2W!6e&W;v>2`JCmH^&3Z58hV_^ z%AN~36e?WCf+8+z`dU$wBJpZjQ%vBLI7a{hS_aV~mJ&M^J*#nB`e;2Q0;NeX9^WjJ zfI@Q_Q!$YZSaBJ2?$YDa8k{2^J~WoC+|ZP+zF%W5)~=zi^@6^Q8?S=ZuGuJ1Pw3$o z!3&4v)eo*Knms%2x!UVDzkW6E(u&ct z@8Y)h&oLBW;a9Bsosuzg5u7so@bq+?-Y=jMF@;gAx0Yg$8_(|8X~EJ*asXppb2KW) z9;4I{hYIqLmxzaa%|MF9Pj-ceuHDvb(8=?24UaR{rX_s zC2c-bRCfTV4MR9%gQ+XEga323=gP~qF|L}DjOU!@dGO{QOxLkg90W*`O!Ow9Caz^t zW?4C_ZBba{xl(7S%E}eV(beSLr4b%_F>lK)D*f)L8GS3`u)f*S&&fu2**41i78vdV z=~>8cFXx^kztwMR* z{IzTw!>wy#2z8V#&X7Iah=cY~ABmuNBzHKcZM0>WX^y@JfhfYY)%L5fGhx;0F#izO zGoqSRijAxlR8DBdB%EH%v`S+q&UIq92W}jzXzWIyT+W^BZ{*VOdSbV;kH2qVb75jNZ~*z5Gc#3G#8@eoumNbW;b{ zXx57=K+H)sI=O)lsa|6|f>~IrtE;s-8&PRbE!xO6rVi!ZRl{}sb*q9K%w&k~q>{VV zzkTyMQM*`9+R-~_<&y;w50s{Y!nIp=##ylW^EaF}p86cw!@#g>I?=!z+tJ3hPfOp) z!~udG@&Ru};&LK?R$6@Is%GWt?Z;yTSv(OhbRYP&aalfXtZf53_-XU@NDZOj_e1Ov z{#KZ7zL3gcy<5zn*9O$-rGF3$Q{YbP&%>xBWi^dWMWY@9?}Kh57}rlNBfiRDco!75 z&0ZJR1r4@eP2l-yu(>XUR!xASR#trKsG4}x;@oYN30AkW5XywB$2Hg18e=Bm~@^Uw;-cTKVam|aAy z{G*NXhc(LOMZY9sgbmuce&wv}tN9ph-FAZ(lUxhGh7eDuT4z}lo#G-mpIIiUBdytD z)D4I5Zr5Ai5NsZ{qoVcdJLs0sZU0d6_^WVC?;w$Fp?XDYouM_gzottM%y6_3W*!Qr z2{qL1OGs6HMMxi<>yu-7F99c&{CD<1KVCpaH_@8 zt;}{a8FSWbi*g`8Awe5e62vA*ZW?7#HiUG6oFJhW;)8%xsh3R`cp(iy*ohr!R7Sj* zjy0zeli`WugtTr^xz9Y$*lK&hDg}4_ z;LRu|0wjC9X5Lb~k9kq;>^Ed%o%V;4VD-)6Mwq(ePvv}Ei_%Gl5X~`;XSo9eyfKfk zcMZYeBkQv_Qi1X$dlh)SDt(v#%jp4j|wlzExB!p`l;EHDjB_Bk1w#D<@UyJ z#%_MZsZ?Es4~ly!gAqg}@`)AcQp%n8Q&>k3y-Nh-k5j8Uz zo^-f_Ey!02U}jtlNkX%n?jFyoH$MU+>eEB3=gOpF7ILKPjd8zwbx^+!aTMzB^#b_y z1ubCs(Ip85fR(r~8jbVYxI38W`CS}}Dx|Hai4<84ZwA>MbgCE+a_hBkhhvSb94o>l zUyb|bO|QndBB9CBtfiupB}G`%9Y7L3g3N||SflG&s%kK|wVXr6uez?LSU)R_>+e$A z=B&#W+`0H{g`>$I;KTTG`pKW-k2i2D)|`^K*%9T|&aH1cQO8xUVsLT1n_P6XH{v3@ zI?)+WXERZietrHc)m^%3d-+WR<>OlaoZbuqa}ia|VJ@khH8_?~+oNOfGE z8PWDf+0MQyoiyG`7vpufDnAgO(LKmv7zOr&*Xm*XB^&p6r;0G4p=IXA#*;i1Uac1M>b+@d)L&^0U`S`cjd#idt{n8z$K|@4~F77qy%dr|Mkn6Z|MNWmD?B+$3@Qktec_y2R z;nh_K&$am3m!8?{^T9Q!O2h71m%=Rg^X%-^!L_LCSvS z8;_ALr6so%Ron>tbM(uf)T`26@g^BF;p5HK^YZyIC+OcYFOuM@%F9_bu$FO}Srrlc ztt)7tc6xN#k~Mr`{;zY>qt(TITdR%rVJ(GnPP0dML#kZA zqquX0$60Ve1jDS`;q-jv1R*jm&Fd(&aw0&t#%*Acr{O`sn#=p<-Hwsc2IM^*s^;^P zFHfw73)6)oq+hnK6-hN-BPhEH3@)~3*|_}zRwf5VC?Ad&c;?J-oGTlM`5omQ2wx+T zcsG)@XGQ(@>V>sRKUL3_%cXe1u#ei9DskTHB7$MB~ATyco_ke!lNZ$ z;qlw9rP$dLe`Rx2SK`88RJ~hnCA2;5a?v`5qmT|4^4L2l{X$^Z*k`9jdTxal?Koo` zV<3^kY)jOe*h2W>}h@KUhQk`;nC7bK?nZIaNYZXNyb5aq^ z{WBrUr(%3_#u`WD?2V;&;e7N)Z>La%53ucTEzRKUmYnQS3Y4aeJnk!!+Pk2W>o*8^ zwTxR&l8UH4`KGx}G2N{lrpzefQzB{OKJfL_N5yc)Z^@v*qZ@3Uit%N^uvE#YxJ7Gm z*ox$S?_6)Y-k=EB0zWqHHB;@G`^xZx-5_;st%jQM5|TS2Zp)vte|s>Bo^0oRB0$C& z=^f4QMa*uAy3hX#aVo+Z(Qc?Y-Y302>YlQ*G#=1gou)Ae-2`A@Ly%EbFFoR^Fsf3vGc zsu)rBa=n4oG+TwYam8(uKoCKIja()oVG8=|OkF?oB}A$G@t0Oy{L2FAlw?|C9`8Xf z(s;6pBe8krIx^w&-Z%xY$K%!GrFRQ=gP}~_rD+;&ZEXQ zlnu_B0w#k&cfl{S)gGNe>TEpMgHjIPU7$1KE?d9j5(7j$78!As4fkvpK}+LTbEENA zfd5WDxB$-dT4;}_YPy^tbSkDSj#Xb{OlsQwSxe{Se;C3b#8-H50TX_o(g?&&pE?z2 zjnh=`CNqA_PxGp;8u0Y&%_z9P&jp08hWg%R=8b!IA{uJ#l-NDqU z`2=kVR_iVNjFjS6Tw*b7zH_J0W8p^(s6e0H>jt73RPaqToQl!%@IsvzM;wTBPrd zFC4d4kYK<&tb65zv)q1;?Lc0o*TO8BeR24IVMc6=)yWS`3F#HE%A@vddEr5iST zb%tz6Jv`s1ldiJ*`w%?ExHy`x+^E^22fGFiSM`o~x!1{u)gMt&^(0#lJ?j8lxOaU> z>HdoIp8lbq8$TMJY zWr|Ed+6iw>e%+WGa+wg`784P1846NQ6yA}1Xwx4%P`%l7)pPB?5?|BWF$a_Y9>0@P ziym#wv)ubSXPcloB}r=2u(((M1dvyfE@P#{I_=w3MgcpURq1JdM-E-wsr6R}pk;17 zTmPgVs&@@4l~Q~5@_N(@eHp&mn`+{4G1jX+8(rQp_B&r(y)^=^{x@#={YK|D3&rhP z<>x)6$KbXc0h62c3~*3obfT=gk=rNbwN_6$?(m>BbVYl8kxl!Y&3kN{Ej?fv_!2>L z=CCOyjBA%dby}d%U57{LyEAGvuJ_8kPj5IxCa+X%NrAgxGDyd zK1&9T0dVc@xYT{^^XT+%sI5`2_r8Eanf%(&OLe=&yd4qeeV_ytU8)1j<=1mdIT5p0 zF6T3UY7wuGCyyIDY2WZCl%CB^AElF~*Lv>{d$95N)%fj{o1HwB$VV>~fL7-lxgA-3 z%6?)xRwSDkmnvencL1G{@Y%{^wkmbFT=`ioA;;F|Z@nQb_vP|1pwDM%&3y<>wVm>V z#HRBJ1*o=1w{qU5qH)`R!kvF;^eWwPaK z!IIMXvK1mQ26AI#KBSKq8w-; zb=mkH?s4EAQKubS5_pR9e-a*eK+XkA2gjsLSKtFe%||nN%BobFD&-NCl-!rL10Sr6 zjgG$8DKUPToffvJHV1u%H{K|TANLs@CaG`2AKDG=3(uU}FGlx?p9D1c_Y{XH;26=~Q#oh*nmbJ=Yrl8=&Q3vPM-%XpP91QbVBFBl3fSKq5Zd+x zJy?-1YG_6a8{@_uCQrMlrd&&76N)=pMzys{uE1Kr`bs>{v&+VvLfpXRpqx_cfAA%K z$1lr=qIq~q%IkPtMY#CXcLP1kij9^C=#1B9a-!7b>+?xs;}YaoKg2#o$QS>ief|nW z!^K$1laTrML8myef&V+#=V5H#aGNR;%AUYes>!0xG<)k`t}hV$*zb`5<`5n>Qkd{a zLs_%2f@YMcnKL=lj7soi;#x7s0$PkaCW+vDCu?#;aEzl%OWLI;csq{|roOq~EwSZg zSRUb@Bb--f(?wu+>7GgEH@sVvMfOwcJBNGKZ@2nEJiE(6b-s&2n$gY2i{nRiutN3W z>DQcGa__$r*(%p&p0c)cp{f|9J+f1YcJ5;9J+3COR0ZyUg2+FTP4le9+PU+7S)j)9 z-P}rVHOgC{G~2nmwWRslNWQ;w$D|K7MU7e4sM<%qzXFExvLMeHWgkxtMWx~Bw7j+} z*?lB*S;GhQ(&R5E%j1WyIw@x{uj2kTb9>-L$wA8rSyG;+z&TuOo@B(q_6bf8mzLr4 zs~J^I4K_c6(|6a5Yj0&_B{k)XCK!`Ikwc8;ZE?f{(DBqV+RIh5679;iRVUz+o6gYY zo6e%wP%QmO=7!ka%(!(~Vv9qgR`Uk7eVYXt?>gZe;g~u8LESYkBgy|T9kzC!6Kd}n zYTR$@uIypX=Gq-qU2K0NzHGb)LtyZhyK2|Fx_L@LaUv)(#8yRb(7de&WEE=(io3QJ z(rd6FqwY;QM+{jhmYSbhG>`7W+|*pm+YS_>zGmd$lxXY_b{oRhHjKLPpq81oZz&|$ z3G1M=Y3sLp^?d@T{CLDHhZQsWuNL0ga8x6dU0p;_Q%xX929MwDsf^Fr(+J_#v9>!$BqSKUs zFU>M6*jBv8@ruSzqvTO#8+#HflDOM&=r~&`9KQH=jQ#zmjm8{rBbUv`N)FsQIHF^Y zP07x`nm+(7bvs|nF91=;c;o>fPIo;F6TKkb6ZbF|+Ycz@=8Zn;NY zsh@AjSci@jn+*%7bVU2z@?`oozf&jivykE`51Y(OhV<2PnOQzF@gXaJ;|sDYvK6Xt zatq{sKK@RmsNKA)aF+Bo_Cb5;f?ez8RtX{DOlZm5Ycn3!6R`gUq`uc}) zJLBEJ=4Tf)7soyy7M_&oN&C)(F$cbyW&TU^eQ4ITD%5@$kZ4N@VQDW3LCm`OjCr6q z9eqi8tB0!j3sKD2yHw~9wQS_6br=To&40ai+`%y&_b6*HB4E@)PFY2jk=OI)meY(BYal;9xrDMvgr69gQ zmiqeNewfrJ5`S}2n=y;fbk=er@XGQC5{#wIQfSp-u%ysyWciTPhD>hJ9duY-5AZg| z(rcuY(K>KVz6O~L&)_J2&mTO3(`Z-j&=&snlAZZKa~BI_&eeY1YOA^pqBop|SbH0? zSKbt>sQN1ii{hcYmd+aYxHsV#L#a;lhJ}6)k59XI=A?S@QE2@3>Nn9Vats!w3z~;7 z)@a$s&Vyekl56d(G6g|8E~EbTr7kDR^bKwDdRP5|j=SZ>khw`$$(dq4i$uM>k{`W; z*xiS*(is)ZXm2qvGG0q%gHW8tPJJVXn#+QeT@reqw8K@b)n!NB@@_Vkfz=9%-xmB$ zYRvpE;@Nw%wjXX~yvRQmG1c@SsF=54Wxo2@g~1*3a1Y-BCaWXVuqqWsilTqjYMVLv z5;xvjeCP&33KBrRhkxmI%|th|i=nM}J#dE$@Imu`*bjU8%i}7!s^FAq-|k+h)&)l# zmI0I30{P@evLoy7TEoa<^Cfi1HOJf7_qbE5@I=>Nv{Xm8E5=n=4|j!#Y|iNq$xNjo zbzfy6O(?sDPw;DP-{VC*lj)PcrKH?M6G6A3f5BZ_Wxc@#m4s%B02t0+%LR0I{lnF$ zT@2D&9B|t&T0e4%k)7Tm5Y+bDKiG=8PWziWt1(|Qz}Zivm9B->(P{x6zk~7j zv1}wUL2^8$@`&n>jCB>hQWTBk$iESYO??E>9yU~SaZJZcr4&HydUvRV?_hL{^ZR#i zIlVt7&02}9jWD@}u>8nB53{Bs+hWY>X`hv(rpEfuz~H>EG6X8?L@B#QDu23jd3$wL zW*J4!71;dL_gR2Mou;A`^SW-=yO~L*HOHN~Q51uTed8N-R%DcNd_xuCFvSR?L?GCL z@LP<-xl<~KL!X!dzaq&+nsBM3Asv42|K=XEvrzp*1!D31n=LJ~O1{rNRm5f@OqGTB zv;4&a&)JmUqo)m`vs;kIDQ^W%;m5L{_5;9rxyHzGFz`P4v&<5(vz$%m9a{hexjG z>7G^hEX>#vtHqdAG7~^H*&U{P)L`E6+u4FeUw@p1Nj-)H#G~Glgez~CUA%TBeTPE5 ze*{@|4#kCRR1r- z{P&pt|0ZFq4jtd`?#i8~ zT>L-2Z5{Wy9<~Ow^U;+423y?t$b6Nw2RxEjFM;yeT#0%sRG`JQ_Qf)cM$Mzuw$USa zo)X_A@PCA_P!5igszdu>wo7JZ>`=0{4{lyZXMjDB)E+>_<~Eoun^#IedqS;Fm(e!R z6QBtFA5&N@eO*D5dc8?$OD`%@*_O7azOX1Igh`DOj{v&TXkEdvfzDb2F;5*PCA0>eTU+fonp znEuwQL6#c&Hc;Bq6-66!vSGE$vH^w61DY8@xQf1y1LAFaP&u+_MNPHvL{bqMamK4>2{nBf)PwN1!RhHuqa;XJP) z9P0=v5(c@Oxm>B~qE2dP?SDI{3r_F80<0Yk=(j4W;cR-GK+vk`Dg$Ba%D)?#FQ<)b zJ@AC1f zWNmc^nm!WZnxysHVz0Y}aijgtN1DM5(5h`KATqdi|BSM?alwtcxJEBtFxNp%zP6In zuVFsph3f6ZyFy>v3F-`V=_!u~zuxNZ+i9L`6lUgxtyx$9rhxvfLIT4tJ`zlT?5NoM zGY*&D%^NY!Lx#~W7AxTNXF0NkT;w0?0U)E>DhdHeRZy*{EOhw-q*@r2e?gf3TeU>T z`#GMLVkFXCf<%^KP zk_8!!XUiYXpLKSc>tMxg4VFgRSr+D*Yk(qXngFLnIbRg-nw& zUGFU$-c=CnJEj=v>+19IpCOa3a%z^zDhhZp`_|@-x}_43YiKg`kLnTvT&oFwfB9^u zg_h4WLrYrqoj~f9N`wcy<57Bdl?1l}T|4ZM-fIvEA|3_(t1UBFN+hzgh z2c0(fpJ%Z_IyQ>%KmG=gVCkQ3SjWG|1!+nDm(q>$`^&=(*=75Wj{yCs@m~%v$OS%n zI1jRxz2-9|i11EnUyz8icHJ4ieE$~&kjS|GeGRIXp zL2!x?DqU{*OPW70b)_I_Zw-^dxsA#{dth1&r|xEgUFf36%8y7UIlJbU!p?Ha>%B#> z+jSvuV_SjFt?^Ip3u_7xEJ$FvjpG9`l|C*(;4<9yd&WpxaPg0-O5m+cWbPzcgFTz*~%`m=syO(5EMHQg>ri7MkEBg4CnLI zcZbHs3rGuon$`a@C4FG{1J*T-0SOe(P3jZoosrDHslgAm>3b9Pi|pqwJQEfJJ4_vo zUd1Lazx#cM7muq{9Z?~Li;0S*5EE>1c3pp$u8Bi}1Y_6M3hm;v9QYQMSjA)I7uisg zsLLC3#rb%J$&~PkU@fizs8*YN8&qp6uoepf@#rOyuOVgA=;?W9t7pw%|Kt55a610n z9eSDvVuWIBwuSR`(xP=t3G^Q!KSWJWtJy<|g*Ax8$I=o6_<8KMk{doJzr25KDU%}s zoe?9{>z9X{)hX*7D^%qNfeqSzcKEu1JOM}$c|9wm?Vr!LbRYO*^8sB1e*z9s{%x-I z00*)9^Bv#?QMEWh{TC&x8Y+;s=XLa{`NiTvwq9A57C%;e?6GB3s@(E(nc2Pdt+d8V ztT{x4BAeHHdxC9OD6%D>)j0>c&*NP6N0Y=M5a-UPeX*|MP#Xu(a#yPt8kzy`n?Ssj zV*(o32j>#}Ikl*1yugI6=}Z(Q1Om~EfXKFz0r!FC--j0R$PVl+@CKmjVSmOA!9&(u zV8+1E4$%Jl#6ln?GJsIP^xff1`}Q)z2`o0F3T)IJ45ACec5)AUASxh`uap>(Z|iF? zQm8&QFkzth&7Pd#^2NH!RV@5W$Adt4t5JV#?==05viu)V4~;Bf4hI<7uU!L3SrTz z^6{-5nqB>*vqqbLM5IxFu5gqFFvX&ZjWMagV=au&Em*Oh-GA zgE&*Y$XbDf=ja7}u7}g3D;~bsdcoG*k5s7t`EqQmE7da)Ipfb_@Qc(6JbP)@%ElxIbJx$s}3zdq5p7%)-QmX39{{Dx$6jkLmzuAk{jD_gXVw6eGFk< zLsvaPAY9V_-#)(T#7JqjSe0_K`=;-=@NE5EslESx8qDA9mSooQ-$Q?h)z}#5*%%iY zqt2t1Ro(pgJlIqrEpgoK`@z$RJ{n8eA)q6evkJ54RlLx%p^W&Pyr;Bm&d>I#PW_o1 zftC)Hs}%DT4WeH@^mBb71$!=!ZFI(DU-hWra}Span#)?|JZpDr@0?dO9MIL|2Ft1T z2J`NUtq?&qfy&@7g^tPsck)KZ@2=MIa8|SE!fDuHpsI$L`KGzT#AR`YT>69nPu#@5 zm*I<41Lcw4M+pwk-LSvM2u|=~j_p#klTqla-O+V9@RES8!WO9AzY9Eh?q-f~beuh` zgys0;kO0>Kh~QSneu#&o6M*}R|0w8lQX_7r>4ni>_s!MZk*?NgqcT^}@V{g%n31@7 zZ7d3vulXTGiYB{~2W3kiT=3F(!bb_Z_>1F-e64MF!Y4+zyIZ32H-CmQ+g0cPGSX4g zP*>}-#JU!GgN|nnI!9E@=dcz%;RQkc)h1hShf zJYH_lYPW7HUa+rnE6XOdHYJx``Cc~4e@vjwRWE@>A-4E&W~NPAVI6FkNUxKF1GXrV zWAH_{zuNF4OAjxc*nUc8plG$Obiq?9SHRQfnwoBvx`L?* zpAh$T)u?})S3VgOlQDFOD5LF?O=t2Q?2Q2-O-Lx*G z2&Va}JJdQChjl}YW8$aswzuaw{C$8Z|L%}N$0GlWAo#730$(HHJK|RP9N%LCqymA5 ztZU_4B=8m~4{hEg>f@^UeUxG^UuXACriTYO#?YZL*A-x-5*DVC9Yv>@om!OYXqRO0 zmv)10x&`z!xQ|{9-m%0 zE2EILtMuyX4VM+mv)l*OfN+{;g(C(!;|3!flST+v*pTe7sAkM3hkJHkY*BR-wCJj> z;*30;K7u0p;Cr-b+rXV7@1mr`$LFQ=B6a0f`F1#{0ZF(&RYRF9cNM#*|Ce+a|F#H8 z5NEl|Ccb#yfTK?J#orGZMc(t?Auc^-57l(!lsa4a|1@{qUrl9s+#T1^5d>!_ItatK ziVOxsk$?$pP=OJo1`>!u0BHgNh0seB$8n@78bC_G2_*y)0)$8nSe7P+9-=~sN^epk z2?-^8nb~u8_dnR5l9Th!J1_U$@BM!7_fzi7U|qXetG>(1$YmaZ+UTaDa|`rqP}DN{ z#q$@!yI~x5kOyum+@pFmnX_Q&*b8B!m7yKF(EO@gpuo${&?8l%&BGJck(0^E*ai*9 zYMIFp3y~r($lfL?_?wzcg*0I;p@$OUfGrTlLsE+lrlIxWN8eS+ggB&S`Jaukg~ktR z8Q7P!L{zRW+WPKsf2d<2f-|gZ)f}rCNd?(&{N(xNv1Hd?N+h`qQW_eo0VHYulYT2> z)*+W7NPg+c564@5HkJP@GM_>}Yv0Pt{!wr7SzpZ7%iB@X7$K(!V~Y_7TXAf&X_wm) zn;n!O{Y zT+EpfWY2nworca*rxxf%qWkoX^3P$@6_5gJf$?0k&m8hFbfDhu3=vTjn5LXqVMU3a__2`5`pRIvu- z-n{)fb&5*N;_cXPsV}q`tGR<(b81Oh-vZVK3CX2ZiCetcY#Tr4?tZs-D;T}RlpW>q zu09nI^fA0Zgknsrv|MUh7<<#QeB>~9vXp>pC%_3;$>e8T6T$r)`ql<6(652!aZvlp zK%&{L6y}&3Uv;$RntkuORt$S^G;HagIhaM*ckb)fJ5oUK;tMj31c3m(1xYLp+0!*u zy4a+Sm$W&PpBk|h9)y$nb6ju`+@>|IJ*@WRNb_?J4Ps|8-$-$8$L0DX4RxD#L{Hnx zvX=#)<4T` z@8OJvFGou!asX8`CQ>7-D-xxdG`M<*ec3`p>3Qaz)N#S|u zfnU~|C_h`fHQa0=$hlAqf61BMB;6Km^D8J~CV^b46jQs)fHkmvjBE-t=i%L$-XM=F z$VC-1tmwt#nvWKcTF^Ttp2sN#ywdrroyd~|7`l)Ode!U*bbl4AW-{yj;G<$V(M{tg zgD_G?_M4f@<1<%h!f3jguYWB$#o0gbCn zv#Vv8RPPe_-5LE^kZ1cFh9Av6u{#47yA5CM*7-j2sBR9)JI`abvrAA?dD|I1#B#C> zZqaaMysCXFz8hP+d4y(R*h^8CwYd4|zk@;l7Q2?JJY|1H+`TeHJs)`bm+RwBzAzUT zGCh8-ji#PHA4an(HIBme)^})T#0swLH_!;8#gj1q2-GAuaIQhqi1~$k?-u zBKwvnra@k~Gqjc!1d19TIyg+{$4DRFNBG$U3WBG1cl2g8ehrj{P3rWxfLXmkh{?u4 zG7v_4h==z+ChtU5?XA(PuFAGwt=s?jXZ=>&PTX^2sCvwE>5#PXNv`64#JqqXQ=MSW zU60UZiMkz^#4zjuE8_dLev#(Hy%Qy2*GD3);^eC)!6{Cru+!JugDQ52h;k5Wl)N3k zVF~m-%^QMxUyK9AdKLcDmpT-_M%qbvI$8o+wFAv@RUegiybmV67s%GtPk&fpV-n8# zPHifMw%{iw#HnT7zeTOQ7pc>>!oZ2Ly)Ct$-p;0!#PY%Qk@4XmhbIM!Y;&t)rahV* zf@Cj`B`mKGkTLoC;Xq=kU-wpP?rtm}&=(V{BeN2af!xUoE)^pg5;%?~=RVF%1qygrLeD?w zuF_b3Mn@LwATJ;a3_i2KoTs&578dw&=pAWFvD~B^)x7q$<`58vv%Ka{nKSorJ`>L+ zh+d2Xd8*2ogl&}XZ9<1#?+WOxxZYJI!=wvU(X}`?OM{>Ug;vuW!J88~DL=%7u^ZDO z9Y8ImGlT>oFq5Gf*KRLf=%)3j#+HzVJiQxZA5Lm+TI(M4@ca`1$a!4iK$BgkKaEjXUeFb zUTM%e!|`AsEQ(gXkmT|3$GHwp)@{L-s@OemZ=~>5&motHKbA#`K73i^s}|HvbfsYy zGjXC4?$~H!I6XL;7z5>G#egGs3S(B7wNC-m7ij12;a=x80_N1{`NjDJtJuBdz{tad zCOb^Mf$vnjV>qx@`IgY+^U8+lJ0^|hffJH=Ca1+(QfcM zn6Ye$^Og41?nXp3csdko!_mqP7PZz?<<41{K;4e% zD|qz1yHj_~e$sj#|C>bl|I`IaoSMs_`M$;sykLQD8r<@?dOvcvU7p6A``vU>MvXu> zQP2iCBrKNPiL@OoaYWsMxbHR+spc}4GpxBkpDb#YOzqv9UdT^aE>=Ju(vI2e)-eJh zlBbj;!+SC;(|2{L|Y-WPdisTRchiS$H284KBcuZvYhP_NB9= zAl;?W@Bk3PAa=os+zCUKBc3$P^n)l2iu|ce2uw~kPFx;bSQe_?hZ>EBFRy|{65NN14Zr8 zk$AqkzjbYXOTqt*jZOQkjiEu}8oOM?jbClcf)<7jvz)5?r8~!%ylvS?t228Gl2xcs zZLzbnQ7N&-YhwdYvX}qpU?hdWEgY*~IdQpha=q@$zmwuZ`eZ-cADpT$X(wYswmcWJ z=`5y%1)T@PZX2|oZ0qKW_qxEqVRc|Wlpc#`kEmB>(tgZTmM=JGm^inv-F5Z>k!76F zLxRbui+#3AGneA)6Q*14Wt$RvDCwB{A==b=Q}WMJfS-V+?$&TU7(-_pg|uh57MiN| z`jq%#hkSII5U>sb?g{|9Z*1Jh zHG6&!vC^ibFJ}6_L%JAl+q8%NyHzya^Oft6cE#0D#87I;)OmgmY<94s0|OJW2|7zH zf(K`pMvV=oSxQ>A&imWs950pZIrdX}Ez_yU3pH)Vkhv`i?aq{i=XEFY7WMR26NOc;{jmr{^Tn(!hoM zFtA(y0=iG5OE2}g{;OalN8f(1Sr~a#l3E&*-OEEnQ72gX*fP$$tod8PZ*I)lQZc&MC^0sc3UM13)v+L4h56%8G}Bi0Rmud&-lgEl2~uchKo>z0YxWl)6Xw%BZZShP)f z5T)5dG!uNQ17L{1Y780A4`%8A-W2`)^mqTKU#05V4`t^{YINqn_v*bnH8oZD7FD}ov-h9&`qx_D_pLwlovH%SLz;(pcz8sLZ)7#_ z@NRG5;XUBIe;c^N9hMc3hxa$0qO7#mhxENAFGFqj>)u12j=S6oaKXBVjDnJCp9E-iBMMB_J{Z$o&5y_A8@RY%_fLn?c}x;J4zlwoAI zPq3<{ML|BTr4>^DK7V{xSXA^baS=CX|6)~H^)r*3H%jYZ-J3tH`HCN>S88!}L0^T` z%`lwoCIBnzW>%&@xFY_nHoRxq#Y=8L>ZxshRU9iR9^N-HTWyH*!<{60PeVOD(++ko zM$=m)N{{k(k4EfMIrVM&Z^2!DO#*GyhU>^tv^ZoYV7*OE6R=pc?C{oB`*Tq>me4Kc z>l1r|wxn#?3aR%qr$6R}=Ui;|?-cA;SM!bY4lVghR~YW2FqeUH;_&VCCsN*_czCbu z^~u4dbWav+;QLUmq=W&om$~K>1C7tIS--~4S9&L9KJUwQ)`uuc8^2!bb~IsSv_!7t zyAov{XK($zp?d$NVd;IknrAs!g)(7pZVAw~HU(jcFjJUBQfqp8P@F z8Dc#SzvterthIHq*TT}ZL?ByaH0qg1eiY6pu4AveX@6n#!MJN*goS0|uV0y>K4RGv z#@9cM%TI6PeWYk^d&=D4pkSE!ce%8AWSnHs=eNek(qJEFqNnC|KB8JFZlU4+Dsxtq z&!LL7=>j4R+hq-cbSkOe+HU3?5esI_Owkc)-R{UN zN9v5^*m16^5hSXVlQ<$U4>At7QH`!W;r&Wdp6~Y!%)7{yeHqb}_qC8UPp;EpxdeIhPA4PJl<~U#bL8B-sCaKwD64j`I_*GRSwRC*EuG=ds`*oWy zXWh!Sp?BNJM}ElvAntzE2hE5oN$3EGBs#eN_HaxQ@wezPnwrJRuQ}RI*m83;3_@Z z28i9CrBQJ%58pG>p{5p}Q^LdtHW|qji<)_bg+A0BlcKycNbN^WOUW4p5@h3=iXhGe zJf^}1mNOr@p=3@S?zYQ9BkcStXOgVi!y}I2+3Pd1fp;WXAQ&{_Tq)s5rN#UyF&*|S z>q;tpX)Tz-QSD(`24wzf=k(aJ!~5P~KpCZEWICN-eIa0+OwctNMpw0=sJk#T6eccy zwAD-h%2M*gbl=k9+=WTXmqo))v`{vqk@aa77apFKB!N7I5HV)mpk5CQHmce@$O`Zu zpz~aVKtpGI7|>gLW3&nRoE1U+T`t_J{(&s^(E*O7x=zXIum?J^(wFlrxC1|9jl4r8 zJ>TT`!$haLhBy+-($bl}2LR!rcA@($&e7EJH!PYmmmr+~Tm_AIRe!m1X;_Sg7?ehbb}zlBz)g3x$?tuT?uhhZfA?t*==@ ze}_|sB&JZz|Iv_};OBLY4!-BZv1uo&vek3xHMwdkeSIzJqi9{Fx#6h89d&s$tJpKd zSU9ydrjUzNip>Ipr+mwQT1F*h%}s~*ZsOsAx0QKb48S05x z<#z;oU%Hy;vbf(o^k#V-RCxEbv7+zsZJEL*enyBHiLtrV&?KVw;YB5H0LJ8xU2LVW zNYe4?8>8i>zP@3_!~YcA>J7qKR?ZUeGoWP z2E~GUUT6zIq?bgacu59aQjVXSGb=lAFTY$!tUT2*DGFjSrgJY zETo!zeYSU3%uTe$t2NJ(G5X;+|M6(Rqa(^~SQd9VZb%}y)#fy1y}f>$zc+6eI@h!3 z0{;sSugqeu4up`+bLI+3N&-Ec$|p;CY=NXI1$`IscKT$MJ*xB6m%*$QF^gI8PzzJ8 zrX?lWVI~W-<{BiRcgQ^cy(Ga}7D5mf5kV&rob%>;D`~uU@=fqFv>PDX=`K4VAb=!*9MF_APOQWCicwYtiwE{ z6Wd0ORqqoBrl~}irb~LD=5x29#zIjU0@izx&DD+j^s2Pj*GAEI#}5YrY)Zrmf_wX# zgH4Hmb*U11xGtHFp}9oo@-Z>Rr)6xa#wA4Eb+?Qj>-MW>A8FmRbu5eMCp$GZ^^87# zyv?{B2%Ai@iyo{Yekx)*@fG%S;9*LWr?L?J;xcEW@w-Yr%#cCadV4Y=(o-$420bL$b-Xs0*i3#JHM_LUqhtJf~qjC$pl)qBqx9Ii`@} z1p!u1a&n4?Zg14o2sAC487bp*@$e91?v06e?bpl5k-_H|!AnJCn={-WK6Ty3YfKCQ zS;cY-+d(SXBpR+p$uegdfIWP3cVh2_uEW+XJh#6QbB=_!@ILO6!S3SW6@9$Rq~xGe z|3W+(hhB=Hi^u?SU>fMp&FV(4557%)EmlFPsj2Lq5yRG^b$<*g@bE-M2)Nsa`v+3} z5k^e%$c<80lAz$<7SKGC^Gk9+zIt@dEPngkWrdM8Z zwO-qajp3MPdF3opU+z`mKkiB7{&{8n2MANQ4#>&-wB3k)_EhwRe;T3u`=*)<0ohy{evmrK8&!1vYPu*ETw% z)lyD|=w3g5ay=SmQSdi7`j9y7<*vh|h4isaK``)n3iMBYT#JreIXDp#Rv)13_qU$U zzt&ba-3}B08?yf^@~N!lB{S~RR)dd56CN*)?7@T3vaj&Wcn$!P>8jbyL-YV?c*s#A5+v5uTB?@Z|R_|m7~6X$+tE< z>bsO|$k&7#qa=_|$iBv1t@hx3<1+ zEl_VC(EH9zqn>JKofFB1HGgy7QbS2w9T-bWp{Alfq1d(P#Z-eB@&|)YNMD@f|31OT zSM_1E9p9r4?Fr?wK;X&+J?q zFh=KTPiID_H(%$<aI67JCEh@v4;-S+0Kc18i76=u)Dn(^=6f8>LKJKA@qM6kv zWT8OQ(G@#d5UTV=$$)o=8j4WGP|Z{T%?KhA$z-y#g;09p)73Nor#Ih1%|M=llXJJDW>1n`RlUP5@UD$|)5gqF6B(a7suXWrJRlX zWUrKzYg8=|-$32K4!^c!iVUt$zVF~-#^y0Scn}tNq^!%l8LPuGWJ&P=@8d?*gbkf6 z?e_e%{Ysa~uA5P08mrn<-01?YzmLzfqwB{jO{`4C=+#ErOE0e`U~Rt5&GS_Qu~6@g zLB&fTvRC5$-{Ow}zq_}$rx5*gp~118+o+Uw|DBPMJ9;fN%YR;7M~4HLRO+yP?s$kG zpP6h|MSz5M1p+ZOB``0YTSX@+&L|`##?G!@+x`(ufJ3+7A7oPHA>SYUuncHx>8+wC z-Uy8;CO~3UFkk7-`2o+pRWx5cK>BzJ^XGS#)cICc()Q7mX28~D;Q?w%Oz!BffAPQm zVm`Q>q$HNGk{AA{%j`K$%ho5wcCv(kLA;U!RvLiCh$$_jHZ^VSggSQu%CV{5$6%5a zp@8hh)G5+m2i(WKn#u;Sa7$UhBY&f@rv@)BE=q`tZ;bdEw|RPakmMA6`}QkGQo{QT z0?iLEdEBxScXek2L;Lg@DH)I`ZHWV&B)ht}#0Kz0g6`?8d}n5XhG!eMp(8_*FXjZQ zEb>1%=~wnGU!ev|%p#%5FjPUCGp8j;a7tsxB1wJ(XP5UzPvnBgRM_Kmg)1pjnp$x7 zOsCyvd{H|zsNq%(#R$C(&DjoXAs*fjZJWWq*tociw6v4MUitxynk3duCGu=7j+kfX zsEe$otkkAU+g7-p=`;P4YL}k9?w-g)*CcVOCk+;-gF(-7zDA5voU^O5+-z!}b&K}Z zI+Eu(p}!+}txoMa@00LwrL^m@1t(X0d5|J1^crv#r}^cZ)okNGB~UHep>;%a7YIbT z;)CRKz$4;{IMbhVUqKp{{a(p_w5tCI_PobhT1v~{a)q*6`uLlnCq3R_K(VTXLeuOP z-Zwbd#;k~|i8!MjQgm3Bj+a`dj5j?{-fl3DP)hO>=NsQ^?1Hn_D0ow`z*2h=okoAD z8ZZ)YSy;Zir{BzlsSeJo}7am3$ZPqsL4ltozTqL{360 zC{$Zpn+x>p#{auKv_^fH^!QQAD!;Q*UzaByN984MAcPJD->M@baWx5hLHN?sCIql_ zgsOomVRvs*+4`$=?>P{PWL&=oHfMS#aSo)%&CAQ-h%3-|(HvQK# z>dWK=n<+dQUUPqX{MLXd5NSUkF(DrG2pEt>{<{E`<>s;gaQJrn|KzJ+M{KP=KDHq*PY)P*?dLlAToQ`+Q0PmKy+&}& zMg+C1rMC9;T+IW(AO5ldQxh=Qmv|n0+n%I%cXOMsG%Z_fJ!n&ulMCe3x!eT8IPloF zb&v+s3%f34WN6r6H&m4n1@&>VR)7E-^DA0kSQev~Y)#k_n zG5}X0@p$czjLRXQPnC)*?vcJOr+@JGescMnj9GX**yyz!ij64uPE8m*Y195za@nkVPQ z)L5Gh?{zEIT?LPr@M%E~3TJNP{dhSASZ7a<#Za>IYL5yV7gy8K$b&ohj|K(?9(U}l zCn4kO5+^2B0ts-}Sd8t-TXspra)tMpxCR7aI4^o2Dl)B5ky?TsUf&hO;HE(Cux4e8^hgfd9 zK!qax8lcOqNWa7GUI&M#3=Bd8Ni8ici|IlK7#GCX2N)i`KT-1LochqgmF_xDFEXZR zO9IdKzt{J_AFM215D^18B^7Bh+{Z6ZBNnS&35uJduRe}j^7dq21Wd!-s)j?!$w^8V zQ4aWLa`JWHgKmx%8a2kS6b65dIT$U>&mWKsT6tTSmS*7Ogfs7r3en+xtZE}vt%6%} zd4c*V791QR3znpodaf7X3)fIMJeh#fM=J}62|FM3@4=n|ei-P7W6T0rPG!B^cWfmw94M0^)3i6j88=!_&AwY-78 z+Ar_>@?a7rFhtZ3&Tc%QUNrG37*V*52=<%CB!(pYx9rL zW%P@qMu5>p6$~>fsj4PkirGxrW3k>?7G`Gl7cct8$NR^}n}E%-w)T8Z?_Es5Zdt>i zP!P09mrGE@pwS0QD|EX+QlwhCFJ#HbkdR8!_Kj1=&v|8Yy;VN9>&3%@{f}U^KE`3e z)f|11r01Ux(#gkWtwQ_39ZQ`69rDq(l#70rp2T_g3Ztf~qJjd#ZIwB%(Bj|T=f~_R zVduvW!XhPTNL^O9C!PJy|2mjGT$-;dNfjx;4iCu(UBvBDRznVqU44IiAwt>fINYb< z@Gxz2dpnyAt7ttA3! z22Z=;Q`(Z!DxwF}!tOgvMlBu^zGq{JT(pn^5{i7;ME_peuQ#fj0|gc=3nZ{}b16vz z-VjU62ZO8Z7r=H70HJ?eD;HzcS?K3lre1?u)%)TpHyeH~;#5{R}Wy zqJFjx*Z*xPws!rFZf1c0H5{Yrl2 z{QAJt031pzb%`m=@^6Lo2jdf8+bs_xkpVwH>&}#7&-dnJ$4Lo zoU|a5k(TybL&nF)2My~`x+}eX8yoQD%NMzD@#DjN_(SxO50N1o@F?q)g*Jtwqa#*V zM<*i9)YKGxus2u3J=uhP+6=E4oTEqfH}7K?r2MzmS(AV;Io4DQhA672Bm~IFI5wM& zCMTOjWTe@j@B3wpUjG?DCz)hDab4Ia4qbOof&LcaCF?#POa8=*Ipq^rQ^38vJS6YQ zm5lT*KPYbZXS0x?->|dd&C=C44NB2jdMw+{k9KwebZ)w28WffO+3t&^8in}M!vR>$ zh-sXOV`B@VD|w75Td2SG@%e}}$*JK~;pFaV(^m;htsafdY|C}&9yZe1!uog5W=FLU z%>puXF`q6)QoDP6xP)3lM-^_>GuUM4|Dr* zxmMo;d9O;-mqTv!p0F(U0k^SL%s;u-m)$eix;t~#6R+;t6BlLsy`s1T8w%mXLJPMA zQPY3p0v=Fe+UnBWo4S5!>9jdvU@w!&qj63;6z|P!!nuLLeA(TCt!Jw_?&c3&U6PWS z`?A~WcrRTa%H+5kw;^9Jukor=$NjpE_eufrlPSFVkD%0fMUNb70ph%-BmZDu1wwHI z&I^}tGcZZ|tSMDmWUF_5);Bg5nG|mie9z!X3s1rf$&6<>$v;1?`uqEnwr6TA)v!X6 zlEwnP%nUMzXvBDf6asU)ZPru;M|2fMs|C`ce2veBWmEKK+BFcmBiD9@jVs2?9m=@l zZ3b>Eet@3ChxWsIdepjwH6ET;?l9wE3cqC{kBNxmGQY0xdmN<+$Z;drky5psfO zukay2qGnhX*B2zK<>mj}d(#u$+6o#UQs|!sh^zRk{k=UqyZJrVZ@}x^8vpnk z7FMsY@bCyOu5e&1c!V1lBAjJ2(zO{4%iagQ^zArQ3zs|BmwSN{ z*tI=?(Ye6hZN**ZtgX4;c*4N>4_x7@o2e-&&ej*P%m;;qS-4L64KHu+(8T-6%^&(Z zz_)3nVyXhX)d}vi_Zj zLwzqU2Jqv}L$G|0ZF?2>x>!~8(FqUynAJSa*(ltKmO+zpgm&9uKEy!8+!=BuDUu-& zkT>!Nz-{aOwHeI%pyVot^RV9#R~N(df0H~jBkMj3Wpa1s+?<&)tOpsdwLAGsbzb}} z?{^#fE<_3d*mwBhvWXE9$HbCnyZMn%pJwK8oq2CpM=P+T);&i_q)1G3>b5=j zhh<`n8!#KjTOh%hrvl^<3>05JhRvZI-G;3k;Ztxasn!e}nKS*Kr;@Aty zelUmC- zs*(zyt-U;b0KFQRkcA>A?44x_ReabP(L|Hz1?x{8wU>gBoy8D%IMEWY$G+D(L&kTH zxNF{b50(V)J<}iX+qz_y*{vtU@H>LV4f^={W0{F*)LMMTBeX*c9svwNNK;mSahCOf zPRD@U#gfXPBQ2r(xZgNnk4(0!NUG)w)CH=|$4t}5*2YHAak&yYcyBy2-r(DA=HShq zFODn$@xk_%;gf?UKDj=lS!!G$(Bu8V#v!O<&dvHvpW1=}D?>AvXM{9`U(Fz9v>1(3 zO&W%7q@_f;M5M6+`?lHq<*59OL$w6}Vs~HBR^064%D=+J-#!AyVgEl}ZuMU+A9~l?NTw0 z5$lOj43M3U(ZnG-9^iv{*E%Oa0YC(#3&7GH9v-$hF>tYLgxC!Y48)LA&dufqI~pz? z0$O34ocXO8a+QDpa`o_#RqD#E*xB{h4`~b% z_szG)(Ih_oDWBi~b2l0l*6 z50m4$?TfxgF)923tOOiJ&3eStd~W@*-Bncz4$amv5if0LO6~fKns0T=$eP)iw?MFK zKi{t|>|KQ$C-$=dYw5+bw0=5F}6wtX5 z4%(52a!9XXp~yJ+!kDqr%!h&$)tJf~VL+uc{YpM>QRC5*o#kIsK>qw0Ai&balFqI$ z22XvRnj=7W?tRTGU}?v0a8~>M{M_K!_*k$|y*IerSx z+}2vie4HjGb!LFgtJ@EkGZ*AcNG*4da5a%?Qf$xOobAeIdc*3xpZ1csGy}+=G!$?L%9bOu_Lm($d~AH^ z%!v#srGt9bXBXwBzn{r)QQe7~M=P#OBh5QF$=i; zs_=JjaGo1DT;(Mp$u$Y^gAsB%IG{`d;BN)}vFns-5+@gvg{x}mA@==00Gepo3{(OF z^Ysb8T;0tldmH67R+?sP7}@-1JfRl8oB@0@E;EBNQ#!)(|R8tV2@=D;T*ay{V~8$@lL%<%^tT5q9D(YwupaPEUVsV+!Go{mE<%Sb(Q0 zQK$e&sL5(c(I?DMoN1!cLB3!4FF@r1Rd6vWnXRORgcw*3os|LM73TbV!BMC`f{`#f z!DlO*8VC;Fe#YT>(&la8KGc;U#_PC{`=w|hJg*JP??NRwwizV=jd<7!Amn8 zxVU*j^(FM(*I7~kYJI$0x2~V)cfm;fWR~gZt&2;}rI^pDq4~u@0IsyAM#%*&GRJoD zM0|EgEIp8q8giYi5A_QT5i5!pAjM=3dC;GCO~okru&`J@@FYf_cg9ZC1h$xjSdnx# zC&JW*9u`TQkhw?K5F`T}9f1O%c$Q7}sI^~R9;rn*HhZ}HtVXs6ekGi;vTJrf(r^7R zu6-?R_T?_;`BFHbn+UY37@ngUtDLR@UT)VTg)}x+5S1=u-)}jo+(6$82shsrJp?8` z#JTdTfx_8tgn;<8{J`I;8wn4N3R6y-qD#dbKX2Dt0t}_1j(*vf%81>4OOgbUXVR~3 z;r&Xjd=DWRsBv(go_=}vF81|Rd~fZ2o%!2%PWE~`N$HWt-f)|vw}3>*GcEC)`~A*} z_0RLA-5XWOkT$Wbx+ryS^89Z5Ga|enb#nhCm+$978Gt1fl>QH?=6@$|`>($He)WL< z8Q|1K1%bp(9r(q~P8leLz$1TF4gB$6xK;wGR&98>(UOEjiy@4E6#&aKYyo*GM( zmLppk3F%eZ?9vVGmX^Xt(*=>;`V@E{q3-)T47;2nA}P03;=D#?W@e`AY&Gegc;B6K zKWdKZ3=_fft_LU3&$W&RRTAJ;vZ;-tuvo9#x*A$qzt-0?(iT2scV}CE+=8qraEp?e zG$_7=V6(m77@*RM6I5hf*Z# zFWAainz{EY6#PG6$G<|5^#;6;j}&spBc6!xJ%3*7d0-qGx*0_;Rd0(ZpO~1C{^Ed| zWZf#MXd|`KhgvKCE?&*w-sB7q6Byxk-`AO$d2|b&;eA4~BMS^~tcsADwBBMkb*{z| zpa(NVThT|Xdgk(*^JYg%e3k}#x|uCaAj`0ILg)7%H2q4yXA-0*4DaDSS2K`rgbT)I)h6y z#BrBL=;3wE@ZjKJLLr2-vHH~1eIRVnu5VT!nLR?hTo4u(xqHuR+23+QZJ}(R4pQ1Q zMAcoaIHxY<6-DQ`xxr0%m@j@ogIjxT%Npc=_PZr4jE|UD4L~8giyjMBSnZY%hdz{b z7w0=i8320xmoozAkDiL_&8&`QN{~@{zOC&FxIW54qg|w=0>=Aio14V$-Al+fDGGq* z6XcIgbg~zjj5qNoNwo^It5dqf@m9P+N4ma~a#pEZM;j<86k29_jr8`awMluQlbv&V zCnsH(TXC+=>WR3Uya2Oo5*`+hjD0GCp0S>Mn&5~&IvS<&|33bqu@t$te5JXxLF?EG zkaZa{?fzF$PbKtqbUf5AJnlGaL-eZZ$^!EC90SC5#}(*#>(fPCEzoQItG&@lP%7{* z7#BYAQ*ozXKVVD>g(_+1N25~2w1Ud2s??haLz`(c6(+bIT1P76AcyL~GMvYrUchQh zi3bi5hk5z5zq*Ccg=JV`9CCXHB*8wO{VLJF zb0hq|b8_-|Iv~6+Xf|Wlj75~7;_gQ41^N00&=k>=-$O$YtG(ut4_1%2&j3Q~QY|2L zb#ISRCUkGC!4apD)&`5LXgjyGv|Rco{Uwm0LOI!~-43>oyE^E-y5QtAhs48ziD?A7 zgk456Z=Ie374&1)ZU@V&Q^kYi>i$=|iac#+0YKVA_@D)|?6W35-j0K7QK7?z7=b1> zWr7G(UhY~`YeIg-IIqnZI7*m5Td*9>!Iq50(57~t6jTm$d_GER zD+V>4VY1(9i~vP=i0es zP+;YMw1X$hP-TTmDkSx`DFY0w{raArQ=KBFGEhP=GIzJ7JpJtj{& zN#C)?OSzs5zl$75lNwb)%EnNN(EC>*cCCj!X%H$>;LyhEun-c&&E2LPY}y%An3osE z2}80gCHb=<``8(%-$i)I(eQ7a0s;cH5b@K9z*l>UBwH!%{0}AqMttW|u7N3Q4>l)r(tRFZ!aydoCYX5!IbD3;n zx0I&+yK>ydk3}`nnrT06dgf7-vF9?AK}3t8;}eK4Q#faJ6k|AVb%ELLjEac0YC&W) zA3p15LcC9Wt$vCshl^{=(kbUEgNy#a%y91B>v`?R`ucU3GkPEq_nohV^r$e03izpq z5xoe}b0r?M%90)I1t>H&vihFu);p$>wsm2?g1$-@lwl5lu7}fv?gPZ?;aVKOyQq=I zgb3CjQEtSlmMMU=wX~!pC7np8W?V%ZU^nUz6nz}w=_{~pX&pnzp^WNE-&|I6CZCgl z=;w6efuSM3wj@m@^p6z&toVxNN7c`naH!eCFXhOk&G0N2`AVmv854MHzcH1ZO zacOI7Xu*=0h=u5N?$M3A07q*WIoYa>88?HL18_?K3(jvz3e;vH8@0N(a@N@cE?31( zi+(av@fBR|n&7;zv75b-Ej1{eZzTpgjB%0TI}?1N5$tGY)=)?)Y;Ha0m&;PjPi7ND z-LEcQFjH~gXcE7eetV`%q5=vy@559A>T&Q`f`^li_O&wFav9m#zvM0`oSiQ7Bq^Jm zuLG6n_yJ>J9pvIOo}HUpb{&;Hf=5L?a;bk)Ky9iQ%;`h30KJA|HyEnr+L9(;!G|)t zJh#S1q0n_=Nnv|r+nb}~J9v#KqedrV)!s8Kw%^dqSOs>(BX#H5=-~BB z$7LKfqA_G1%3W2(8*tWH)8S|04miE~l}dw>6?xOj6v zmgN>6kiazbv;+RA0qL(46!G=z*Yx!CcV7r7xi3!}+7mRza{?u=j`>9-j%UrI`_EjC zx5h)sSO;=Ks>aX@$dR1|p|d&5EcoSp^eeAMpzQn+9Uq1MHNXyJiIM~Omp#>o*jkIiHIBUO2ekgCUNlbxq(7&j<;?5z@Wg-TCE*KR(^*X^AWs zDg5S-?KS5-@v7cXPxSxkn*;;~L2l7PP6zH< zlDay>Xfu#3M^;zu*g;utSh=>O;S`*0?I{a@em;8qJCxAV0Yv<|y1E|;Kz$~_ZVS~l ze6PJrJl`&9cnk{#sOUisZthw@7u&?=K zwy{&HvHEMhAXUZKn|xb8w~8FV&auW>C6i6fjcih^x<*DunwnfUaAEb=ud%ukA1G8# zVaUZem)e7Juf)dv#yI;`7SIh+}P4WNkO5ls|yHq zGeGhR7(`;6+~2gcY1~H5!XhF-`koN~SZHE%hcP@iH!e5V+|)E1n241a-}}epVY;rialp*d(!|IJI533=D)|0gU;fciB838lfx*JS zz+0e)_q=>|eSN0O6Dyn5dIkorQv3jM#6~U1?Y%~;)()8Z|BF&G_B~4u*h2{V3ZH;| z$y4s6Pha-LTf*z#B|0;q?XD1W;w&4=XjU@de4`+f~r;wcgUUn1)$!{%PlwX_= z7?Zdq2?+@ff8Kd9j=TI*7qsPpfalO!iEaw*)H-a~_EhYmD^t+|^l6bc<4{e85LN7e@LqCfg;S1!BUG}6P3&BmviPVlD>Tnb94?L&PA{K_6uGg)L z?k}YbfObTM38X3m&~`FrB5j*IF6IYSDPQjGIakPMJDbNC}_i@m|9a~)pxJ@ zRl%WOJAm$Tyyrz@85ptP;$XG$OPa6dGD{ClS>sRbgFD&bU0sNezOMJ&Xm<8*b`TOM z?A-Qc{tLU*guRGvzuYh9^ zF%0&m7-p&JJp_Bzc2G5Uopr_}(49s<33D3WP?;p18!&3@|$HVE{ z!0f}%=`S=4n>zjYEor}V^tPW59FU7TC?L~vZq|kLxT;zGM1(xC4(VW( zM1`OoF8p^J!v$>+u3vXZg||Loe(CZYB}2@*xxgv(SO2}M%xM1x#NM|8(V-`p7K90I zDf}>HAdI3(38g3rHwKLMbjMGg|sXuF~z@+EDn2#D$ zH0NVA0JhLP{LvrGK}tdb^L*cm5qtXs(nFK;s8pW>Iv^CJHJ)^N5iIB0708EVonso! zgoufw^YUEX)Aj{$H*uWiKNbTbK5zlsee0RtKdRF=aZXJ|vVGT_M5cdy#_xVTQ!Jkn zz-_tw+pYN|6Q6s!+yBM|)XKoR0k@d>ruNCrp(eKK2FKyh%ki9IxkNoaPhU>8=lW4M zBDON=vUh%StFq2(NWE3(o*B)+!1wQsXUDWWVI^i&NGjkF8%^JhW7MZx#+d7Qzda-F zJNR>69+dXkpw-vcFq!Jc*tSDk=ekCq1PISfcJZe8W-9om>3{V@KPCnpC4wbCn3&k3 z%SYQ)O6?y~@w>)HZ~JL0p3cdLoiYRTRBcJ7((D~FM;E?R_EE7G+s@2d7Y6TWFNpGf zcEWjH-@e#tIE_c*L-RI$Pdy$135T}*(_2e)r3p1pkZmj+@ZZIOF_cdz^`yS3OAnn- z2Oj}*whEw#0xdK6$$F@Un!Nw`Mp?j?N4(8`kO4mCK~KdC@~v*i%uKgvmbVTL1^Nwo zGS4*=T~5zdk+~qs#nd6f$5RDd3TV5fdrN{I$3@rd25Rxi?t-nHNnEN|2kC#?`1xL( z%ZRM&XPN%2r!+};R~=LI_R6MdNTB%>W@$Ul&W?u%$Ws8$c&{tQ^Zh6~ug_1hTk@xL z>OG$UrMJM3D=Eg&u!U#19>I0BpH@?1oUo_;U2OrU^xX-A(($x%wzgLE*SFKi9-Chf z+_U?@PEM=lCj%2^P0$Vh{;=~R7JYtdbF&MH!sRKDuW;zRuMwqR zyJAs4uTy)(w9_SArF)`KTnp2}2KYWcWlF#Pw5fI%_n)(f=65kCxD)uicl#CKpxIoK99>*}*2i%?4Ah?7mq%dM#r&M_w(aMwK`)U%_!f4>`GA5E{Lh*Q&U5h>hY0 zOvH_fA_8>l>P}gm*(K8*<%Lh5QooXsC!N-Kjy+VLwGy=UPGS$#B2Qnw_IthmZD41f zEYqAN>d^xasVb@5a@QsO#QAQvzz1TwS?-&_!;RZj(d=8$xPop7E(FxdsdQ9`@#h~R8ojQOfZ@l$Hv@~F8 zh1ymm5B@v9iXvw-hS&5KKtGN6yvI2(ib)*hXmau-HUX|7Td!!qY?pqE%jML#$Wc+T z<(c>0d-GW#+V$!87Dd3SRN9Ga>7mB$A`D17)Fxj`suH~qo7az`O4DUl4@!=OrCNok7TC`96M^$EmdYkj)?IXFGx28TTR04gB|EUQ9ro^;j3DkOgJpca|iS^Jz zL4ihK5DcHo#quYAb+Wzd1h>uBD}AB~YKU{(&2CwEyMvbf2QAz>>3Z zuoUpc{L!akE`I+j%^QPOrQ@pZvx?=_E=A1@PoC*B-wSvqdY5`im23b=K!t2)CIO5w zWU#j32poGIw@EyY%q~Gsolk0t=Nj(_I)jZS(@A~<4Hf;2ppND;JexO4*heawXDm^W&Mqlj1@rQK91L!FuhUPOa3$JxE24uRR3YFY+lCfk+GlZhQ)?Ce~ z1&k}4={1>P%hkwbnmSlIlJ?7zpid^M+oY9gv7Y!|^>ddew=F~?V7TW_!q38c4~))e zQ-%U=;c3|d{Jx^1BHuT=#m42OC7?{hVHZ)6lx8`SjzzT`$nLu3^^vX=Pg-^fHW^S# z8iO<}!i~cw@Ks*k!^bX3P4n-_t%4?$)H5}0%s&x64Eh{t>apF;HdAXcpW9S`r;KIf&wRa12U$)J4as?q-;RD8ga`sARvi&BtE1S)b74UX{>bN ze_4-`I}xiNpj%ZD>6}EKS&XEMtmI5Y@x304k>^vo{67D@YVVrM!aVe>td7;orj>8( zYH(+S3ZfsFdql`vKb(@gCt!FKut`OndW2+Cm!bj!X;Pwx|4P@zXoeVTI49iuB-RVM z(iOVBO`S6>ssRZd9z*!Ug+?{6GZ~qz=kl4TJe~_xo6lYO8AlL#P1^Y@Bzi!I@*N&3 zs*X~1jIHz3R9URPa@SPX{7g7!HFAGc+bnFt40J@rJ^bPpWbahIu^gHO)a5?n=HgNT zv~v>?ML-xMB9B6* z$~;<`tHbpx;j{AyIX{%+wOvH43eAJ?o=-F>Gq7T4lxfOfT46hhA1Vp4*VOGQ>na5} zf*mIF0if2w01Tef@se|^3}xtS9h$m_Irpz*-Qg1w85N3=W?ydux$= zRI|w2?%(U`(whh!5RIMB=cubAO^K8B8!h-N64x`e`lYB?Iv+bi)n*YV!dqzdIt=pomZ+KTN^N4mHL<=j1ia?6F-mZ1WuHjW8Vzo)6I(t_XVBUCmkNWv(8XXPv;HLR6|R zS69JXTaskn^1Am_KKdu<+FeW319HNe)ob2YsX(ZwxD0_T7P=*Io^-k(SO z`S1H|N*Tb#goH?dSuK9Zj1$!E8Azr_>eAAmNJ%t~!uc@}-qFsEfu8<8W@3y?NwVFBN z9D}clnb4%!Z+1Q(gt>-$Mx{b^v>x>cqg8T%ks^*v$P?H@LfTcpWZIvbkC!Ow~N_SH;})vdI&U?E9*KeB@_|`|3`dLonyhb5ou|Mtu>#LnSL!hs^SUQ*VP4@V~_-;w~vDh4ZzYu;t{nvOmj5| z#ayj$!lv5xg5U=aFxRmyUpMfwlLEZ{wx_$B;c7yG=z$n!jhS$FVI9C|fv=e`I93|H zz6WjvvUV&qv`7~mOqkC?ukz|u&n_lA;NK&A2(D;WmhI4o0<0oJ8EFB*6$-Iwo=%H! zom0yiU%=XSYoPganQ|^I#VX;zU{W+IB>N)_m-ScvsJ%Kq)`x+V2y*dC9t02 zn%YpTsw&W`ayc|0A$(C?$1oyt=>Uxn)Hz6^RXy7(K<040DyqBj9SeGkgXcybWvO_ZV_4cw{9gmfj-GN*n z1UzdAIGaSK1)UukeJFF@o*wUC%!t4OT0+k{N%!@kO*V66Oa1Y^l@k9WSnP(I)$4CZ zn$MurCH`@>u&7`=C(H$!)!Of52VH9({+JYP5!VGt$Y})FNfIRiIl>;m3iAPy&0G+^D+Af~0*~AuVbKXex zX~|d#t>hNCO<%ONQPoTXAt>6Yj&FFD`=6p~7Gtbw{dVrAY)yYDtlcKJMQu_J8**<& zX{sZ|D}J&WjcI!&kqFejxdm%BMAVOLlz$!3MR*xyun&z|E<{izjl)ac2$J&cg^kO? zOiM&6PCL&M{EtK7&=qnRGRJch%G21K$G*NeTY)@W^AEW{&{PFI=8;aLO2XT?>=1xA zCraMCe(gPDeS1XP`1GX8Qmz=6mQSQh4V~^S)0MeuoTlxl1iiv!5eAWl`83v=s#6aFUT#uyHr53?;Obu>j=zX4l7gE50Z9F%Ysei#}0# z)(GKixTO$|cC_}Xh((^RTya4b1QgVPoPA;~=cut%*IoaDd4%vX+-AidwaDtHit@?Kr<>>83f|r-ZHC)8!80q_INYbF z5;Y7e?)uuTO^v^+x8FcoLAn&qhbxT92Z$~AW7*7&bJ3XDjTkoOik*#io~)g>MT}c6 zERgb$33;$<$`xU+t>~*lU0NXnQoa+l*S~J&qHoGJ~)MV7eSbUA@K3569N76 z(!8pJa}ReM_cd3J*j!&B;jxY?n3?RGJ>ImrMPX=@XP-Rf#Y-A7Z3FYsF8ijl*`t2V zZL1lNVfPK6<0E`y+RRvP4s%dNEW?fljQI|`zY|F!)K5C5JpyJ+-sDFkX(fx@ZI5*O z;u20~n^!ldV|e`XhkEAR6ze-qtXxj5Mg7BILuDc&=%w18RCk)}Z(r5dZq)eLHa6Aj zSHE$;oNVeLY|>Y=fjP*I?uhsw!?t&!wBr}37#@|G<6WisruG4^`kf6tk=!$Eo}5^p z0eI~UIsvQorU-=z>XnW=6Tu*G=zYQDEevwZ+Ul$&j$)ac7s{*kp##4VU zR||Li>>75*rm@UW4SeY;~eiN6vSWc4*{8{cQ zK(32+Ow=c{c(Jv$DH-g0^%ElLgpYF*lwhP^t3#Qjb$0n`A&Uyx43wFz6T~<}FK-Rp z7sgWch7Ht}AlpYbB~wIiJ|xpZD`{*-uxMAO3MCt-Rh zO0i?-6*&=+CSSnoygF=2T`~>DeerU5?()ZXDki{ zeZXWPT8_Tz5pIw>egNMYdbGuyqcCZfYpG>D9Xte!jxb~muR#_n;CZ!2{ z`uRwk4x{KtGd>yd*ox106H73W6kk7wX!86A$XdE`7^FD>9qMau3v+TL2pux9Z~wx= zpBCiDqT|;5u|b35+Rc($-yU^}U!Sq$tYPMVk?Y9J!eS#gP;pRYh=?xuZ{*&@GE3uVX*uEIPAx1v7;=aOLXFnwqSA0xu->Fx zczP)-V=Ug7vH^73Tz|xXa|d0~-LG?VI#tQp&-|^dtTZaW0|SRvoRMHS#Y^xaWpH&h z7s~p#YhT5U1nU}-0^R>@HsymQnL70F5>G@@a=hutN_#)dblZ++(E2 zZK9G9IT1)=z@MP;u&~T|(%?jwyO(%g+iu-^`*J1x zI4c1U6QA+rIw~*%xp!y4+T%PuMNW?W`{yl7Rf7GkQT4(YKNf`T18HRw-+imq%7Ce0X z1)*+H`=mm~9(0|d=7Vml#jfM23_F)UEE${8?x@_b8+X|>)?y#SrmXb0iiM1Jv!8CR zIOc4&)O~bN*R;puwvHprB0^wq%~ObJ%jrab@dN9M|(s2_im-^wrpRA3a8PmgncA`j@ln_SAS)HL^f0DQl@9BNhI69*>u8W z?_Zyr>Ke}-aBPQpy04=iRc#WM8}(TVvhkVnYMyzHWz%dq$doyq0O2u zU8KWFQ2xV>Knki<^g!AyTn_u>aCE*OQ$y>KQdLYGJ`u`~+sk2Mv|kaK^Vk##V7W~+ zIZ3IvZh4i;fFPjWI-Rz(rML&69BD5!Le4PbUqKzT@|pR+{%Tr}J%YKr zxlz-k;DfP%}>I&1CgI&6XDv`ij>ahpeCr8@UxOx;lY2fOrJ5i+&k zgScq|nlwEt4ZJar+q!)pRdBSo8;H2W;S&#{uWaywJ9&M)=YB4t%>dqiNNQ>Dx;^?w zz^p&cCgz1+Ctn7c>+ZR7K`^Ykt*{5x9K6zNNE1S1-C=@7L4}_u^{yw3I5z^W3g7J3 z`OBw0FiF;uK7;NOsAt^&wrGmeDZJsb-`DcCB_e4NN0ORM*t3iNI&FUg)z|0A?94Rl zv{_3E_b2`D47Qm9;IdiRDjqBIM_3)-%6WF$vr(I#KO6%lDxAzWpAgc3bh##va(xRa z|IZx(Cd9c3zn=wOv1lh+s%m>2GU1s6B&GIv*3;|A#ghNTP+c>1Xa>(`hXBQm< zk$mlR`AHj<-uwA$O3QOh!Ti#1*Vl)XPY`UbW2DvEGsesqJa{xZPbu>=@OcDUx6*$G z%}B5vmmRI{m=Y62F~61USRfwst$G?6*Urg49u-Gln}VuE5#9pTsAYyBGh8|Lvr}4wM!Azr?@H)iX8 zIIy^v*H}cdl4OfxW%qvOQACr+?yRk9=#k3(!`0g5dGNR}h zSv>B^%yz3An-{YyR3hPIBjj9i$j5i66&RbhxeHx+;};d~l$2aio$9^jGp z+rD*@QiD$|?$TE-&nZAo@|(lvl3~XABu4TFW%T|rY$m4BRFAj6ft75t3*?Gh4gGd` zDO6ceQ8Ll@OSu7()~=bYu2=klw*g!_|A}nmPi>T5ekX7#{K&rR4gewN)5QxkRh}rBuoLXKM()*6?AO<{}^&0 z@YM6Rw=ehcsj*b8jf`B_+uK`T$29l&(}4V@^Yken+Q9fnc2<@c;Nvda-`d*;Nn}Pu zNMBah)L#w;_BJ&_Iewyn>|XqlWm&2Yd0i+EDFI}I!AaR#|(b7Cj3H0zUuj)M7d zDwZku;lqboXG&tK`0BptgNoYPi}UjeN=hK=gXRiMXYUIsD}CF)0@n=>Pwr5fTos7x z5@)QdTLoe!D{Jf1AEE%NI0KlpG%BmEZVrV)mAo{FfllSx)Ni$n|M^e;?>b!m_4u;; z#UKs`xv&7>Qtr@%hNdP!gYRR3b*mtcj+L3YXJDM?M+X>S4^`W~eftKQC}m}N4Gj(8 zG6TShxgW_)A15XzoYschy1M8Y84I(r>LP?y3DrqRQ-Gb}?%lg!5WSd=_$@OpFAx0M z3>QnjTq=#%W2&E9Z-cMmRt73QOJ;CcVqzXGZ!+sZ8D)5YOKk}>KJ_RZo^-UfE@re7 zD9+Cq{KW;Rssjla17jgI7)^RaTwFh%gyaBVS(4qROdud|{^u~$V*|sQ-66iVinn57 zY6=8hfO~K)IO0DB0D!1dQ;FvZpuiXJDzhJ=Lb#m)Rn~u_hxUO$1Y>p8@;>8hIC2?0 zEOWH0GEcI4`%c}xx#;9g`K6IUs@YwP9)h3Cl(_G)t1hv=GZQOg4rOLWjy3dD&Cqx= zYsk03p+gitkF(j;psHm*ilCt~TX!`E3NdYVU%_8w;Z zz>v^RI@gmMrqqHm>l0cGLYGX`h~=m?Fp7m2E02~|Jp@@b)h6;UNPrBB|JNCm+SDA? z8ymN@93YMN#4?;QLaY}nNImNjf0SyXqM|ZA5K{y&fP4SHUx6_o)p)r-35sT%SC=NE_g8RAqXJxtwd~SL-3f_)w>W;HYZ|tBwv$f$ z%JC8KMqAf%yYU@c0r`NT^pw{bol56&Zyxp9F;Y~vHyBf62nWbST5Q(So9#7lU5 zZ0cSv$H2(E1&wC3_neRMJ92?n=Rb7d3K1 zf7Oht?0R{0m=fc7c1jdV5QR|RKexZ`lzSyS$m>vOY_t@2M?NCL6I4ESDRrj3n@S+v z5EdZ$Qa@tG(`$=k8KRrQ(b3km`^sdQ5H)T)dm2@ibyQH%t7X{Bcy@xb-*I-d`Xg5r z4^h6)^Bv_kh~r@~1ef4hEfzT%T2;uDz}px%T^}>5FNW#QylD-c2hpvaj9n;G925;! zL}}S%57g#@trdPX(j=`jMDF2OR9fyBR_;CLpteT7(_uz%0tCxWy!?IlrZLDk9H_7F8A12OUqPlH~U3vLaVV3eaMx?Se~it zSPj|vf@@~vCT`J_l@-^OG$^afWn~1FYid8!Bj}NFHj#hdJ$XW;NLRqzOt`^%M8)op z+r-2|mgI!lUo%8%=F^;mWkQ*~JzE^WgPgeHEdT{m#KrVg({t;s83}>!P?&Sq9&*}c zlYn51MVSDBWxEq~)irTGaMoy0vENl(4m4sspCR+Zi#CtZEmH{Wia3Rp4jN)?X3Z#^ z8;{^a+gF#}QKlX2F&{tK47QSUYq3(v2-6PaUOap4UP!!~h!OE2{M-ySrHq?;O4^*! zpP4(x`io#+0)%IrH;T+D`sZReh{wzbwu?v$jvPfU#&WJ#17IxduGeQts12sCg5lPY z%HR*RadBq4n-A2t*qO-bWrNTK5h>&;Dml;%?S_QvHHpR&&pun-L)iV)vk7C?&xw|a zR#FM)ZDAl@k`?ND^tHVWPnV_6^PtvxH``%V7(Z@HpdPh&RTzAis4I6drkeeZmxE{H zj79%h6zy1v7sMc3P9hK6{k3}S^yRi3JO^^#uT|+a)arwFI`UUCik?DU_={9KE#^jn zxtF1O9o<%$BYVDR7*?!xkqS=Kt>dk_dZvt=;*)c(XHD3T_AGT+4gFY_@{i@9S7T-) zsq#6qLXgQ+BbrYqIA?ts+j3iHe|6eBT0W_LwfFMk@jIP{6nUxSJLExykMWsnRmBVJanK? zAMMYGa_|s3$bRrea69poAO@HgrQMx26T_XhzORk!g_!A%U#`_QyTq}4DAt7%A9d>( z``L8*ur{lli>HC%B-JX}e>Se7L{M)#bi~DxB>h`QtccLMfB8QAZ1S;#gy8992|SEI zb&)5htJqrzKH@}5oH|F0c()y3i^}|-V5lp1mgO?k*I%zoqEfFjvYUF5B$`lFf zUjDc-H#U*nNd@hW4i~Q6T`A4>JUABe52AvH3lLY?x}kOzczpY=#_U9gb`n@|31tP2 z+A8sF);OFe*%BUa_-vs^w%e3POs%X`L<~>G)6xv)P82Hi@0X{@Vb)mlxXy~>sI(ZP zc|OnOkHLi$nIfsYYS5;*)XQB9ve3xAwkQa;A1>hlV`=;B>AI@4$^9c1FR^_$9gS-h zu53LLt=b!`BJcaNzpbR0YmG#uQGnSyyRI^5g@b*BoqdUTsCmlNz-&8-oPJ;6h(g|G z?qFc4QBo^mBC@_xLv3ddvL zuy#u6U62(JN#>iWh346}(@w^$5exmO!OkY2zBp^t6Er$l5U_n7Ox=DSb|E3CDR3Jp zurJ@5qy;@63d@Z_Ht}4TY~oiFKKIydx|%t(&8LaKbf?qYyzAO|Af0|n;^a;wJ@j;s|}2~B-|RVcLEt^MN2|Kx4KK%n;3O8Is2i`B?&yVD!w z4@V`t7_-k#ioFvQ&aX90*dAXd7x4&gBA!d+3!kpw?9+Zuou0rqJ>HllPSbx)dUMZd zR|G1E+6oY1-$1X1d0!2cJsao93kyzh7$2U?)qOr2yfjJMNpsZ!zd*;I_Pv3mr5ttN zY(=6jmMBgkaeY%R3G}H=-7B;AlG0Thu(}#4MT+MYUBQCzZfR$CF?S$kdT))k9AVS6 zTD`UywuC*z+7WiQrxJiyO{e#8?*X9X2G7i>t=x-M)fG9eTvNnclXh}4i$yOhlc4kR z8%NxWT@X z?JRhdcgW%wcB-EFRN1QBFHJ0j65QS0V?-j0tFt=Y)Qy!A*+mDHt3oEPd zD;pDLjC&HQE;#H*2c`G7U++0Ib+JCBFMf3^t_qz!IC&*-0~QevWpk zD0yS4ZGY&1Ycku0)18Fp)!xhgT<09?XT%+>MNQY}^?G|1GPc5}URHI%gs-^E=M^Yd zzD~(XetJUMZRaOf4eRXy1*mGe7iDn9&M!HtZ%xNn{rmIy5D(icPgjjrvbkCW{v4Gl z!rxkorpAVXf?tzD8e3ra$m>uvviSV#^wtxI>Cu#IxwvfV_gZiAh$y8E{0U9!?%s&| z#7VO}Mc!YQ-+aX8C%b+QGw!&Iw_nqjOE*00C>9u6t^0q7XIU9t?`|O7vW_eS&yR;x zl(~2hTAGot$j>P{ zlz)B5y5#xxm7@Le*VOj=dxqZ4KMB~a-kBZW73o;!u{VPrlqe}T`QxBG6kzFAQQf}7~tOczWzoFK%a|zm>J90B; zO!p`3dKYOXe zO`KZ?h0;^yE(rJ5*p)93=%c|NZk7@)K4Cu5g9lya3l)k-;zG2QfbO!G#?49*aY(MThcWtHvwC!0{UZ7aGC__FT$%C$T8 z_yLo212*+LJx5;japYy^WdYCdl;$3`dmh3ser{0;oV`NNRaNb0sM@ifPvA4>IX+CC zIF#`o*?(t+zTPC>uTx2(G|UpH^Wno0ZSP8`qFge|R{; zzCVfh_7@ib9@_Ube-gum(@P)F;CcBk@-n9m*J}AwfJro|smTZQia@=31~`a+s(!80 z(UdaBTf#qnDCg&Q0V5zFCcrsp!L6(~LH5Pg78!6!cz7h5Rl6iUj&#qis-k9NqYx1Z z11_+y&hpUN9#%B)v&Y57xx2dut5}A0E^KUQfK=JoSd1!yHtHX;-{KLnh_=2ySvg}+ zN(|C>J^s1A&Z3bkG*&S&E%1<#@Yk!rhh|Z&F~q-lU!C&_4hl57R;z#w4fx-N_yywt z!2b{Z-M`t&rPnJ^&)Lp#OY+mBWVSXAe|2rdh3-pEE{X@mH zv!`WN25E6d-0mC01)UYegN}7csIi4=Mvv>#@&Ieo0JOXR zAsi;m4Kmg=ID9F}(#1qB$S~69y-a6o$Z^mR4r5VeW;=L{_|l<-k~e*W^PpjehaG2M z;E+SO8iJ}_H%-ZCPtyKIRvAQr+>tOX0=GwV^>u`JzMs)|o#93%dQrErzQaFcxt{st zrz!-$`4Mf5@1tVu3wKW_dP-{_O-5wm_@)B7SkIud8Y7k0)4$!>$gVuvFJbKKi(=WN z-0x1BC(03?RWbF2m#-8M_JGmap0^d64&2$ZH6G3Cy0;QIGF;|mlw=H6e0wr6BH2nm zFErwv@q`g%mAzNNoM=KbTZx?cPkL_*-5^D3 z)E}t4ixc%hk#{ZUol;^W#p^Lc4YeC=$%1QpjJhl(xLiz_k8%%2PzG0I91ZXJru*C5 z^=HqqxLKi8e}g3^ug3B}#z zxHOLon0&mb1Pu=ZB_8x(h503A^kPAJyBWx_aT}_b_FhI$#yb?`MzjP)%6`1*t;dgY zbe2(x7JP7-x3-$wOhiu2(qv`)VP~|#@;nA!6)r+APb(Mb~3U z%oM5|i;ydx{n6pn5x$aC9pc}{GEca2BU=(3zgs96LS)wOozV_Il`vU$RA9X+n~dLV z@f!RpuhDfn^g}}&$$pw3%uqg5D9kueVx`~WTs7nt25UXz-`!3>GDKg!vJtj>st9gT z|N5Uw*V@&4fBBm(+5uPmZ-KfGM}bVhJ<81u@)oc0(}YL>O9AGgrj(JAD)$lXAyWfz zsDv07SB{2;Cc}A(s$yx`1nl;Q5oFNU1A*)Fr@xMV`Lg+*im>n{n0lPpo12CF^4NSo zsF>#>YuDDyYieA6`_0R#p~T^p3^-v_;zdK8?pYHAtBYrCZAHAW8o|ofGrF*}G@Ka_ zrh@u1GyxF39U8;w($n{Mb+Is6S$nnRp(%r@SsRK=h{1O-{J)z_{{3m^UypnrVush$ zA;{j|aZ*!o(vn_`Na>8Qz24qSVr=n9`Ru#bG+dsJ-Dc9mZ$_9YE1-W&V$BLEEJxZFk%}eF0^m7%~;;Cg_EUxUXad6gW-+eEH zd(7cBL~lV>&JSLsOPFG7b^GygCtW#e-xl8z<^~dAn@dI4OTt{Jxdo+-$TeUrHF-nn zPnv+6Xz=$W}@K`E@jFnX1*9g=-6QX?g~Fi?jiRPh3EP4eLlW6;SWvX8SWc& zjI6GBtH_7Mmi*nB-eolfd&6P6uI`||7N4>=$ZMuqv)h6l`;5NZ19TfHBLdw-f@vtWe%Vsps`^L+68EL7xt}I~#mIN? z{v`MKVY*hl_R+*58rMR|FZVV`mE`0iVdJ-#>GGxhRw+T?f@>5L3MxvD~~W==xY zjy}cQP!JjtldO|Q@jI(GX5`$MD($9(SHjOMPWJ{x5FQ!&IO1{z8=u}(lRjTJG5#Q9 zZsHNNgM(Yd`oZk?v-7}>s!<1p#0Ygt&yPM&v`rOj)v_|Cipu$E^;eE_rAa(5oK(%M z=&TWQ?`C&)exCK*`URRPL_W?R&aOS!ey@YG&iUxJWdEmBwB+G&7vKFjL}L$VclC|T zfnd|C<`Q0fug0(RoRn(*5k;$BQp&>fc%isk^9H5+cbXSd?cfEKSlGvSrX*8wYDf-` zVeR?fw5yL;gnkd0d$OS@5LoQf)HJqJLGWta`=I!n4uAb5mt8o#hMhwjA!dlruy9P; zy)`%6Qp(X?jQ(bL6K6kU zIwi8vvF|9!77s7!xqbXRA4>-h+U=yVTvL4S7*!h(atDvddEgoaL(kz#Mrgc*-MWB& zg?)ef^T~H=NFrgEz2}y#x7ZL{N?Z9XwngPq;6*Fc)!aKy9{oI=S5i$|3yv7Dnl}?l3Eh?X_c87wBRCJ-OXg zm>~5&IVLQ2%BiZ8(vrH`kw0M2))dI#K^z}dG(OR* z;G+J{Vc8QBQ5|;<>LYQ{0m4kd+%1YKu-1_Q7nl2b$vy3hf(E`6zN?U7ES&t{KXwbx z-*7I67~|J|2ktWVocjQsm)rM~Eb3^VxRtL)4jSI#@lKg=(^IhEILo{02hm-(h_0g7 z#9l7K)pfl$lopXRV=DHsvNKP}Ipcdlqf!9iR~i8C2Lg)`IJTTB^jp%f3Am_&VN2jbisXt8LaT zq~GEbf-yOzBKe7lJ#bXQkDo{?1c^<<7vDLW(L40rzcD|HfCj1ciawB{QS$-gF^+@#A9p=_FG`Nsu_u(>;Z+z*_X2) z6y##EIG;q+Tv76a+SL?`K0-<%mR4yR@Q!y{`N0g1xb0Z7#oE8^f6JWb=WD45^6Gun zUf@Qd6hL7y%3Nk`_pS-=2p9rkbe`Wc=;TM{K>gxppAC3JGkMbWdM0+wz{6bRAAJv7 zO)d&-<_~!oJ32m{5+&F&*n%@URB&OEd0^W))s>Xf?|=G*Z+_O-VS8XyMzZcR-#qJC z2i%-rn(te%S52sh5Dgvl@Rsr5Iblc~B-59~+Td+x>gTB_21cuf5VJ8NFt9B#i79`{ ztW<(=Z{Myz{rcfG2E7()+5`oL2+d@O{>9zy5rYo(e^p}tX_ErT7Wh*qCd@$nxEjs* zL{?n99z4c@Of)oYxVX#^JyHPpZNS_S6CE8mW*+uWqt}bvrR8Oc*7v`T#$=SLot~V4 zi!<1Da(47Eqy64ZjqH?IL{4t*Xm?%@=_Iai%zP#oj3GF5Ve z4W&xnuR1pg!K^cDB{76r`66g^tPuSp7Ja-o*n*nV-`ohwQJJI$GgO%uPm^#K5&}p?02mN>ank)&UQCX8psS zOo%cnG9>aV4ddy088iE$zV70CDu&Q<;bv~)Z=^&;ZH_TcAnmHu=k5_6F(YD(Q20>Y z6YKjyjL_GXd!kyN`XL+D&g5>>+J@V`vAZ(24gXFCTkTD0fst94{1@e`pz}!Ce>2)E zV7Le}`(R;p)O+IE^k`E+#d?EE3^61&_FWIN>|3=wOZ{GdX94-FmAIv6mt{2TGf262 z+BUp3b&Z!<{v1drM*D|N1WZ!zD~oLD3>66=Ba)d9tIHRz=Gu{3hX;o7MUPAN6;6t%-aw@@>7V zz3rHp0Q4Z)2J$H6yR2$)+o? zqQAAdN{hFC-M8*jx3o~)!b^a>Y_7tOUA>^2d2nyhBdZ1-f)pPCo4jz87E_*4QLe|187POWc4P zv`X`!##ZPjxBmJU{g=6}-^ZaT!~}k$E{uI|Snq%P_MxULE}E{uw=zl7I(Bz;{@JIf zJH#UOGJ0Q>`dP20$t>%BpBAo_-6CJD7h%ji@}$Ym&fwe8}L)}XS!(h7@+iQOSu}0 zVr1jW6s{*bhLXI-_bU&0P=Mj>OHdZpmh1UHI`8&=nu~jf#1}@Eq&LB)EVUay`iHKT z&KN{_Q&LEtV8aBy%a|gnk2`mMn*xEv?RTkD(dWE`Iqk?qf`N5;S`*82U$^lzc|O(g zpO>>@lYUhVjg*=par)EQLw8~E6przGp9cRpI=;Vxk1yNfEE9##^3EOWcnB~DgASW@ zvDw?cU0yib(SA=Q8}MLKst%q#w?&nyH@`+Ce=XB*H5dn_<2(c}=_1_z_l~liY(e*x z#7!OqnXq23kb`dlyVtP1B=+?-o2!0gzb4ikpL_ToXY}_xW`z)1g0QFF)=0mDvni=H zzp7WL%MWvueRh{ytz?Nz1FA7`536nDJ!T)_)j3w!yGXbfNXtHp73;(ujp{^wqK0TGM+^yv;r)xcB&krJ8td31yravaD*C&0c{ z;GW8LefyRV#G;tuAa-Vk$<-C_7rn;AgGY2z3{wWs({&QIba!<8@`<#M*XG{i@_#cLLpnwl_6`nfL#>j9 z&Y+9{n7ayaCk0WKRdgR0}3 z!{`dAwo~)Gv;{3bT4@i^i+HzBl@~H1V!R8rDZUvkAgM*4%5+%WpeWf@C?$^S6<`j4hC* z=<=q5$Rn?FL&fs3l^p%nt;E$D!_82R9M+kZ#pxQ7;pqmv#?6u)1&Vylkl#8x$7~Pk zn#a0eP{E_)B|~+(Ye|lG~4Y?B9j$WqD0|zZs3QgdM}%M5iZq+m-HGAAh*t z+CqB{vDI!8$d1tY#TuHTxL0e+GbIn@Cp|L0PeAn%d)iX%-nT_%#>>vz5linPA2)5j zP^^bcC8D^gOKOKb(Skl zM_$$Vu%chAq^obXS2OK==VTe|?BH0iQAG4I=@0)uR8nT8b$+|1MLuN+{C#}&Vs#LA zy6sJ`i)4oiM=?BGTjR>Y+FWOShk`fcq1UkvE962nDmk`1q4~l>^SL-8&(zMb$(Iy( z-ndJdOPNEvgR*{4|1p&qQhK{iXa;_9Qe%rxeC5&K-)m3K$@JP$q4L>kjRKU0jd*NR zFd|h~Q6n+R?PS`gDFb%=B?Xw}Q| zH5$&QlZ+3Ro#7df@bPSk<&=#u=rbbUTGiCZ2kyzECg9%38xx}RU~>%AD_D_n7r$$I zcRDOhu6c87QzzczDMd$4Qrt|{=JK*ujJr<1p_!-W?Dtb&-@UWU;RlL-qO~^8&Ul)| zO=EL3bVa3(QtR~>4K`DknJvb9CtG?pO1Z4U<*2v^Y4fd(#8nm^H(Uw3$^#t5WZoqU zQQak*n=AFSuZ_><>}=ew3{#Ge zPNZ!(buOH(iM^se(kP|y@eU0BT911-#4)Jp=Igtv=*_1LxR5&Gs@Ct}(UG1n z4;=O%woH~njF*F=-%Kw&Cl@(yy|D+oYGDBaJ7*^XzuP#AqN&Yq>*$epT0K9FyceLw zyO*)?>R_sxc3pt~@V0Y-bnvGptG&*!IcEm9i!%Lk)X|S>qJemGH(RZ}j7FJa-R0rB zPZb5vj(87Kp4XQaRcDD`*;cy`?htY9M=0#UZ*()@&o5Em={NagV&^b?$IHfNH7ZT> zsiU;^Z@Hi|yd)Mm*kOIXp6g`jm%q>(G1A%*@VRpHnVhXaYt}tr{~eNZ#nyh^LokbO z6!LJX6;4ZjRuMU%T7T+tygILk`x0t~&ioo2Q%#-fAT@`7oWo<08-mX>4Z~ zg(>+h0@M?;jcA|+(ec2T(-lP-Ei_vDF2_i8pkhRP^5S37)IGG+$63!RnDaC=en9J0kNK_ez(W+{4|7{EG_+U{O~{ zB8NOxKJmlZ12w4@e9DwLI6A^Jy~4J1Z^}8JCLy71%%+AglEXqEns!^O61_a#+WPDb ziHYY}=QE@_RovU=bga)roV`3Yu3m;)^VgQo(9X86%%^?z4F0GrIh z0_Crc=Xl9heZAl!IY4_1tgJmherN-I|Kb<+1^aPR6nT1HV2(EO^n%<`FuZlWcv!B-c4TD4%6jwn z-_KT^w2{7GF1j|(^^10g9OFjX4v!23t5n|K6#tjtBMi^)E+u6zC+DKCZ;4`*0C%0* zeaPB*7W38fzmkvs3r)@cO)k>Ee%4Cte3#_xrzt54YU4X>l* zUg_OR;hdFAde+EXVrHN@(K&G<{+Rl+5p|E?icXVSjd2-O=7|PEKEGkRr+y`w@v;t{ z?C8WiHEkG*=jnX5L<8oK(_mr?RDpnq`ICpQRBND0v#;QlyCVZrvry6WP4!^?2eK#R zCyvEPb=9PngzT>>`nPUMK3cO8bm%8yAPIRw)W*g7u==XO^4&M$l~B?M^RC7VNz^BS zXtHibqk&I49@#GX-iuhdDZ*Yh&eiIye}EjY_p~hT_@d%tZP1nNCn<9a1=6#598km; z+d;>Xtwvhxn?%3)mh81Ph&Nl3H(u2@bu1E-Y}mp**Ly;xs?y0HuMSiy6Z*O`$7Fld zLYy*gb&uWrF<`ee_(DFdY)mjpprJ(X1@rR0qzCV6lxjS|!&Nj-3HNc2w*0ss>xK;| z2~!)h#A6>=<|Ecto%yD`{FJjZ*@Nf8%{w`jOLX`L#@$8bPFA}M?}$r|Afar=IsuC{ z=~crSTMs7-#8B1!9lFk_SB3%e`P-8fWV)k^c6Eo!tTt-e(e!}V{9o+7XIK;Mx;E^i zA}Sy@iU^{h^p1eks7P;u6seJp^xlh#fP#SZ4gyj`kw6H966q!MDug0J=)DCJ0`G+9 zS!M6N)?Ryk-+K4@^ZuE`V~ELQGBfvio#na)?%SB;=NAr5`;R|>>!sE+>MHGB2?6?+KAX*_TLQKiBu9jbLOsbM-r``3HKf6baCg^MBHJ~m`>GK-=T@my-w>M zX}G-Q^!O(-|Uf`~}jwxNe9NkeF{KVPL(Ou#SsUPN|2hHl>-KWePy;&&qQvO2!gK6{f$o7UfpT z5V8JBU8`j=;|xg&_+Z&+A4*f`+S%7hV)?CVpLH6dXVv-8tcSN#CGzIZ4+cV3)w~*n zCQ)#K_i%PRkG$SJ#KzUfuv@h(zhbj8Td3!Q0%GcOQh~qglBw$C;kJj}l1$K8B!VW! zZf$4ANQ;M8=mOr}>-V$I$N!ZVM*Z=4+9Q&_dTf}xvv@?==Y_4P+90D?hPRiwio%YA zgS+qX)Y5W-wRXw0CbQ3@IS&tm@{oD(g=8s$W3L@O#z-e5?-$_G~M@Sy^&qv zT86?9bzZgT7855ihi4vM#vp*HJ45uE|K05yGeY>ixUtljn3$BL*F#ILz!72dQ`2YT4dc;oz;SHh_FzFXnCUS8CJ_aJ$BO82=G zZb%E1l3&4%qZ#h>8WMZYm8bhophEoh^&!(IuNvMlMSU}S7Vov={I21Zj!p=0tn9hv zgNK_l(lH%e*JC~r1s~2lC~#`!6$CEK&CPvmzHiE{WRcsyQU_?Kj}^DQNy#q+$}0;n zg{kJ55`a%&=e&Ax(bYSOc8b_j`r#?z^8dE~t}~E+7kTnF@d{B3+x*&IyNwMv!J3Gf z0r2Jx>)lwL<8EXD&EUOT*<5cQ-({9&1%A@b58a$%X*^dq!iwb_+acQ0|PBQqav3S$*6Bi`W|fdq@j&A9^btRpr}{-152*XQu3Hnqe<6zHUU1~^#x$b_xblSr4jBU-)$vYv?VZVlS zTeXKOOinc^-QR8y>Xo_nrE~@2V#$L&kgiFRLD}f=@;>ZUNyt0$KpyYXfDv;f5b$IL zlOEwa%rqmEqMwdwEzNIXbuVgi^8uWfApp5_ycl>+N3}MfA^T1r_e&$48`k#iqmx69 z>rY32%2S$4Z-CuHc({EI!^N&yn{=SiU}4U@?K#=4eAS5>_g{6W^h*#1H|8e}SRLf? z>UQxP;LZ=d|BM`aUIuMZ7OG0A;5dmkN6ca$jaN{I?L$m3(LICA6s8hVzIVd;!(c{n8hF8 z2Qqb@eIjh2<1f(+Lu=o^IoGx$ery~WW)JEcXcgRclgWP>;Nnu+cRSWB3*uX5AGI+~ zx)ET%vBj1*&YOXQGVh;-T{?^sq712IJfGcmuE8lSS)9*Ne6(`n`V{xK_~l7^@SLst zo}vxVgOYVqk2k9=C%&)2`0PuOBNR&akhcE{frHgjeA zbtU#=^@Tv-eBYb?rT3p;(4FHYoU*jVd?PT3{`#bdn7IjiDaTC)l>~gt?v`jWp2B?O zxrKVGPx4w?lnVk7>$A}P*9Cc9%IjXxZj%W#)fnNcIqQEdScf*>l&IJ9TG(!-AWPTP z;zEdt0oBMwg~sN-^Pz=`gta_FXGqHuK8k+M@ln>Gh>Vba<#0QD&PZg0UuMw)pZV|T zXrkRDA(4vX4-mA+6!Xib(gOq^&~uy`hD2a}Cs?V2)NVn`Tk0zNf9qJQXLY8)E!HnI zR+mDAM}{8OO|!8qMGXg2SKJ)2MQ2TT?JSuhmy90(%ip!>aSt`)r9W{2Y)VPp$@ZSs zv-={I4k!H@fov6ermebSJ#{-LX-CT?)h6avyDgwaB52x6C1R!szump>`QyN4Mla3+ zVl+rIGg7y46GMO1|LF89-k(Yobe6JAACoAo7~?V>e8W5cVdcnSd>3VHH)aye zqHecP9q`C`I~i>NtJNf~X3cOa-T0SbA*l;bMQ7W~dXxQvlse_QDM$>#$2+jMS;KBh zb2AM+5x=Qxm}_PH>eQgxNZhOFhjBHTTs|8Cu`?+v?$MrbaERy@3#{{#;D24fyBb*2(YpA3->Oj}$OIjlIJ4*% z=PgmDnG8XJyr;$l92zeJw&uQ0KyKU-buNeK$Lbd+?dSe*e!D*%0CPq`lb3TNlf|S0 zHeC0Vgg8eX3Zwk)Y}bgFv?ycVC%pOKRQk#*mB**NR3fi>SY+Pw%WT(2HJ#Dnks|c& zyXW99&bV^2Eq^D8S0IlT>K&6rxfEO2+ZCF6Z}&kcjjc-L0fP_#AMSU*YEK>@$;k;b zaamCW(0~14_JIIoEHCocYA-Yj?2PDRaMpAB3C_cwxt9BPZs|GJb{nS z{cnROOeFAKK4;ZV{TA48x@u+(F1aeRNJ>ArxL5vr{uL}o?H|4-qJ4C)vRZst$b!S}z?lbHzr}8x1Mv1)|rjcla z-Q(9GIU^q*2|E6<RT5lQL&h9-P%V+)wb%agYH{sPO9~SG zVJnT3+6nitcc+=Q z+^o!GFRm0tQxPP#zk{llVyImv3R}^zvT^!ix$1Au!`TVNLmCm>5TV zjWC;*tk{c_BOmVR3Lx8k3E#Oc_Ev|Bm21ZsodAE$pCO#0D&l7f%tBBuu4k~3H-%fw@23Q1GtMmCc&LM+Hjq40ca_>IoFZ6-N^}xjlw9*QSryH1}`IR z`A3iOiNm=k_1X{V3w1=07kRa!E-~v>IRirgLAE86Uat)7O!ey6^a+rtmT%CPgB=PF z0s~o7n$O!<{rbr8B&uB93B`6pHtsfan&>w{vHOB8mB7z>Id70XM87$PKX4Q}G+G#D z)`Uz@*G>rr2RZk#TTfpmytIHkq7!=wh7>&wKOV>vTA!Vm?5p80(6`&@Kj76a2#`9d zGs4J;n9}*x2BvVt9n0c3TdK~xZML!MGa+d;s3)FX1~KdX($PIR>NP8Hv`jw~K*XCj zRxVQpb?$`SJM-N(#)8jGW$7Ieg(ui3CTQw_2qB;&RbNzWN5WLbYcGKZ5(%2(K}*1b zXc26g;g?ykv>nS+_L56=A$*aiGFu zx=wcHu1t=q8E~jztL_FBsv|a_*dQTx&3Sz8lt}y!TcDCS`}VPHFtOc2?AO7iv%euv zi^<*vA-cT%Mlqmal?`q9m{f+^eU@8Mm>vclqjVYKYhzPvqKqG(?wpd0y!slLiU^dO zUlXIFTb@d2Ha&hCU2#+i6v3q#`r6vY!o3MM^oWJD^|li)BTgw^vokzBU7yLg!v|li z%sn=i8$=dHaUokZkA_%=Tt0s!l>tYd?0e(lRvdH8Mag)DS6<{+ROMFZ*?}yf=lL>?E?fr!A(TKW$F>dA4>cQt{=SM8B z=To;>z`e`bQ|D4>XkULMYv@$9{AI%(ol_ou1?%{=m}HoDSd;hRir}+8G-24G$FRPj z!lZ!E(OS5!c7k=NiG7MF1WoF_=%XHk6?yrYzQ%WeA6A)&73+V)wIG(C1|Inb`+_rY zEnb1EMqBxKgvVO5PlDu(KHI0=k=j#l^HtY{-WIRf75x>lQ) z{gRPUL;+|S0(O4@nxO0%?brY^?D~X-ws)8^Vhl3_MQ{s*GKen3HgtjzXr_6fc1?^mQzrKk z6Z2(qcq=p3!(|l9&A4e|9CiJ6^HJ8j-M0}v4Ucs8u#-K8hwrp#;EG6xK9NU1ru~m~ z+HTkEVtU5~%zIweLnZ3UXJ|4+rnkuvKJ>`LpMrAUTP~b&?hfv*VXH?>Fle+)kTijS zg_4B{3>)4uM2Oo*6iOlQ>+JsEo!o8LUa#;y#!%c6II9>Yl>r(@s4yh2AtlZ3G_R-byjz(`NH z)tMO5x3JJdwm-SuT+?m|^67?Kxv6wyuUx4x+@SW733{r-<!fbJrh3aSjba?2j z*|xD-#eEqgA4xy2o0#DbS<-Oe)0u?boC`%8PG)niRfrSFw2{yeYsCQ96(&e$GJ1GQ zxNm+@AXZzCNa8U?mjjcZ=lB+=-^)J2dE4*rd6kFJn0J=NH##xXGfyP+`cZKO%p@H~ z7Kv}(efYt+J(=~w+<{6_&H8Vdy|II0Cf~|UA4lwVQBv$otghD#vr>0nVj9e1YC14Z z{~q28I;wpUJ7kYT8lj&PKJ1rw7FSP>qR%q@v|SgD)n!c6h3eRjAGf+6dU<^WK-i0@ z_b{%|^%ArRCW{Fb*tn}tgLtnrahZpky<(!9%1|Zk26*1u$_jl<7`OHrY&I7NcfM(U zm+dIfKPrtm#NMRU*12oUd(f%LW6a6T-TZ#CczX{73g z9$YSNaq3Me>@0Tx<2T#OOgk5vbJE+oDP%^VpNfdQeoS-`7V2s5igN~rj$ObZVn1BB z+E^6nElaqAINZAMcr^G$%eI)Gp8KP-)FO!9ZgaoFg zF&J$SGBe)*Z(FV-8{A{n)rl&nCD)adG-NVXAV%iR9s5S7);B%Zqji9X!`|Gik<>1F zT#s-}3ea{R-#=gmre!DGAiq$95F>Jc{Ap=DA(V{C$`( z?Y7Ys5DYik@B^+Bjp$MFSA4XmG@`2*15qPxiK7Bw@6|I3&z@+?>%M*bIBzhldD95E zz`y)<>f`@sw((`|X;w@4U&OB`c!@aq=KdV-$u^kg=3LvIs2ZSn3AmR_McnV}5^%gA zKJB{$3OJYv0lwM$h<1wV8i(nWfPG7J^KR0g%PIPUtWvnzVMXc>p=HhKs@diDJ-ov& zwtp_7;y$J?YVm6^SbZ28MAHodpPBgezb`v1cG;9LBU<2jnz;oUdOHAX0!y&+y_mN8 z@hR-~@a&jB9tHfXR&TgxlZrI`nq1Rfd$#z? z??6if&At8oIsn81{XhkBQ#Cs%s_{*X$IsKR4_eB~#m8sE_LgM{nHS*IU-azP#-H2S zi{gC!s-6*ME_h%B`-}Rw71)YC)z==Q;-g-4sy1ZxeNZIq%;01QGF}z2PQ=Gd31np? zR|Qn>G}~$t*TtD4Y`46$L^Y^rW20M0)&-#UC_-S*RGVdZt`RmrEX$n$6_ViJ)yn}+ z$Mka@odkOAs1r_LXu46o?w3D;+$kEDb5kTdcb?Whf84s&D;j+^y&Op6tj!M}3mGXh%o9MStb>R4}-w$~? z_c+W`;31ZI0RYDP!Z&NFk8^spogO0hQyx&8GknVTaSWreJOw5G zILd&7G~i$hmd7l?R@MlK9Hl?e4v;zEzx-Xo;jifkfGOV1z%iOp7neYac^v&_B&D~vSY@UFLikoMBtFmA@^cm2n_`}f7kKm{CSI8%NVBGNc9%My;5dbZ+tcUb) z?91~#+we#TPkP}!Y`l;%;5Up`5W(KVTluXrL_TrVpxbcS@!ig`Ldur2+Bavi2#=_9~xL?*eGrL`(3L+-uHhl`!&lyiE=BO9{c4C zd*ml0z?t7R5m8x#3x(ZI=jotlr^Wt!DTN=ish5G+D6)(`pW~2oL1uQ*b#loJQ)P`! zvFBzr&CqjH@Ms4<-ybNgdg^<~LJ))UagZ(Tx(e^&-F)!Wy@j)*GDu zf>2|u*}6t;Bj0~~4!t#avTCkh=@208Z^RQeZJk#)rt?yZhqD`)9^@{XN@-Hc!;4z6 z_c;H4^>G5=cesv>ShWpwtiiE9sy2xk{|)m3E)P`0kO!vRVF7)-P?s(NW93{|T{ka; zx~;G2YfrG$o_=zi@r8h147koiXjBiLxsL~3O83Rq+GGXJR?*RoR|X&}$EO}91vl2k z8)sGKA{L+46iTuA^oA=RqAw{M}T$OMRoF?VP?)y~tH$gSv2z`L_MZUjx@JuUCYkFoA zROy)HrrzhZ?>WouR{9FV8K9wE;$Rgg2LO%y1^>w`y3OA=?34o_lY9o!4e+Q1tZD;^pl3}05=tra(xF8ebR?;GG7@)>|69v}}cVmExQhxpM_stv5-H!R9truIa^vo;(3|1p&7@ZwcU{O61hH&0dL z&j06o_@|r}cW*^KxO&mdY>^1v75;|UA8Yo|0`Dtzisi*U3;;(75w>gCm&gSFcDmCC zEAjLz6-@%*_xNn0s7Ot=^_=3|C53@)bb2~Zoxi=VZqS$n_%z7F2kB_5^IhcC)nFI# z_O}1{-u#1ERKWvrbcLgFS;MQLC1U&#Fu1&#Uf9{kPT!%GclCX6-wTNGq@|bm1LFW< z8+~;DrwHt?(b)f=f17<^?K#?o=*OE!iVbA^TQzn&_eUCh|0eVqzqurW;IMLtL7hU>0>WO z>2AADdSq}s%q6?#DiYwnEn@iADx+yFzV1ji?eLVgGvU05-PzBX-4K~%^mDwc_Y(O9 zmy^64WZ@Tl(YpqT>#jzLkV=ze{B9@+dv{zjse*K{3U#smngP(1Z~m5;FY(coY~qo} z>W5Dx^B9nx&V&I zu-G3Q&jOI}ABbla;EZp3hme2@Cz;ApLgNzX5y1$OppB4ZB+n=HQ;gWc53S97v?0R{kI%6h-8=dIh7D{#9JIfS8Oid8`)Hc57jo>u zMT9Hyp?20~RmCgC5S>H-H2R(>yF~hI_UuikAE|^SMpvIZ2Y0bUanDSiwJDfdi!duH z!f>Jn#c%s>dF^obeyM5ON}-f;`AP$5-q&3c6xAjqyDg_cgg9Q0z0NHDygNHUjGYff zY)hEd-SaA{i?q`{zPRukYHBrH5^QF;>QPx`z^w}Y`omKU0((DSY2uMulb0l57FYx!!!wVq54kr1mNQN)Mz0u&lOAzN|Ujq<~U@~zC)UU$jo zt$DIsh3MnpZ4&ZN`qJkB$4yRMJJAc+uXrUPdlKGX`4C84#Ep6>uv}khuZAvfyJr75 zXdT$}*Qzeb@$$9ULcPxNvJfq~#(Rz2m(bq<@sLL6xS_3~E$5F^<#g;+-1>vu^{Y$w zo;g%7A3s61_uMk{`vB_e`x6%sA*xS4fo*|U8dW}NejmT6M;#C7q8cCenZgk9n5YK^ zI%@=dls3qQ?-AX&x$-U17Z!#$UDG9}Je4LnUmkX5#Kx_pq!3JPXjj*EJ_61ML%CXh zS^%i>rE<$g27ID&G_Zr{+CT(vV$ruHnGjzszLmDI78VxaBHAZDmvm`!*@M@1BTJuI z7W1ee{a~UvG@Bc-@#9@s*Dj1}$y?eY7ndZs{(;BuUD$>3afgNY_@%UN!?F;!IIWhf z8iKdy-uln*{q@Yo!osdcLc2!Rwv^NX4m-i)(8FNm!KW+98`??DLzAwLWSm~BBeM_v zSB*!5WdF)1$(yf-S6s__g=UoXzs9|xQ7wlV${m+EH!8*Gp?J9H3Au9Su6ft4dVFKD zoxXJ}1%{g|LS63J!k9;oQKZi>p>%DMQwOmoVoJHJ2)W#{MmEVThd|hW+%DYiV!>Cb zhdpjfx{*-=RAePS81{R?N9(sKbXr9E%pLaQ79PSQlD4)ye2>G_GW-kN_b7!sd;qa$ zyWcXwq2(r9;TW`7_BB>}Fi$QS;XA9!E@leW1Fn;z_`edFlz<9XLg5c5mpO61$UiV- zJ=T~;nFuccZbJ(TIyW(5HC?WA_bM&@?o_o4de$jy>2qzn#>MOneh2XAR1QHNp#lt_e`fS~wtn0KJ_<_I7W6U6 zFDS^_hVfp%1n9ay6>$HpUf)X&Ms0WO$mw&yg_|k4ouB5FiX7d_umPAI*al3|xWo@4 z@^GVk$W zzD!-VNOOh{@9O5(VN7+1bdHvvr@Cd*?25Xo=jb?iQd8zO4NkNAaJ~|t-~5JiwwD-V z^d{<5nC?Lb;FqO79v52Cwco|86TDi!%9#VUW3F2-jJz-*fT*s4jvC|Dg_S-ibu&b##;TQ8L|` z&vbKF!|1K9sRg@F`TK0PfgBtoS4T$Y8P~M@DZX}9vnd&H3Wuw4Eq~IOqmiCf{dCgu zoUjA3Vf#Us)aG@x@^g8Z@nJ#GiDK%fHKVVCDI8NPT6C93JGS-DoT*QG7!3Lw*)$x@gQovh5tpB4j>LW{|8T%->smJ1(=lXUTtshyF|QuUBwLV{-pV+ zAZxaDSSvd_WJGNIXhD(9k6zdToX*V9iRxK^83*3{bF{Myw*dKv)15U7*O-c{s)&sY zZobffzWm+Y8XZ5qzw5fR=Ys0w=$b$Lz3ro}iqtwrI-nz3vATcI1+ZjG-w*qTdUFTR z-{#+}H_zvRC!t(ELzz9Nq}-{46fC}fjFG5Tmsmckvtga8;nGGTUI*#3-x9UeheeS*fM`@@PvRa;U^UbRA&yoaP#h!+X-~yO+vgMrx9`=x}x(|>hYSH{DvRC z)Et(_AeSyb!_(WtS1}^XU8km2L1(WHMr3{Fx4l4c>PGmIyBoMlhs4HzJ3A*>oxm?i z7|%8LXuHGi@kvv^(%&cTBGq#}`la=JZ(tQ@iN2~kp`&)E40Xcm_gX33N@Cw8Px;L8 zkFz2@4B||tZ@ms9N2okfrMwhce>?f&Yu{E{QnS@Anuow(!$B)pQl;VtSt}M+IzXI( zH00eRTgqu-`0?6yj1N6?r0b^Ud4nS^`F^gOg*k0c7ssUKGS)u+^7=bl3!af z;9NhNvz`Jl5x%QdM=p(yu60Wb(Y{UqM?4e zUB}-Kn3gA=JL!&KAPw7v6FI5%9Axi)~X6B={sWOI?8hR0is2Zn9G>jAyLe(G4gdK(U+ z;`usXsK6b03mw@02R;q{+xS$2_HX0UHpv50AG~i?R-wk|H3#z64F-Dh(j%=AKw#~n zuzRU#d?QG@M@_o?sZvpkbdSr1kUPZZu(y8uSG03lov6RXrO?&d33)RpSNo0n{ltFy z-w|ri-$$s-VMa}^{|rFY1ipO`N{9M_!=oWpHl*Qo_&A!`CPbWmvLUPRa#MS_Mev5w zRDND{HJGdLFa|@W9DHcbJIo`5OXV(!>cr^qY0#c|qsccYr~7+`MmQG!?U5{lSF>US z9*nNhDRD(RwB8wt)20eV(;(y`T-_$GW3(_yD*H~-)NdmMS)~jOb@UCfp{Z@Rwrd<7 z8c@B+>Y|9#m(gbvUQ#NS$vVOEhfl9AQ)9Gka_bZ(xdCXZQditZmj=o3k1sEA#~@UC zLw}xw@9f0%!)xV<3h(t~!(^)`lmNO^NpAQoltZSdL{nqH1Ax8F`?_4zc{{SM2_FF+ z<{wFr3Vys{f1#}oV&42?&*`qpaRrc1=nDnJqW;9V1WSHeC=hUX)<~46cRGK5DXp8F z*_wDz3h=2br~C;V2E!33skztySSxFmB*M!|OYZLGMqHXq#KhAm8KoX3bphz~16Or* zwKE3*y5Gd!H+`(CnhwZHBTzF7y1FSmarL}k>hb**-|0fO=qfe>e8Okw*|%>1=hMf3 zgB|MA)T+^#v+JG|)1Oo0pz|8BJ(Ox~>>CwylOwY-wfT+9W zel;t*N;%B;`SX2lII>NxsAoO5>GLcILTV0r2!y?>NK z0iwBoNudzCzyFVb$-gS8@;F#N_yMm&K=q?q$+;Dz|I)+;efrO;7f)T&{o2%Fb@u)F zkl*DqPaI4IH7|2z@-z@~$DFg=%FWQuE%V7#`{$ayt`6Q^w=yc(%i=}b+cgVQqQiH@ z; z#6E;R2GO4^E)(Q4`x@R78MM_1ms!hFP>JbCWxHVr4-J&NOlo};1N>55933CILf@8x z#Ju)O__z!j^fy$*GQ*C-vRKU6G*z>NQX9`4L+eg5X$BUytzsKj=&_*Nx|72SY1<{f+#g+9f>r->FfDUJJvfy|?$h&JZ@M4yFMf zc5Q&qzhxTelH#m%S>~xLpwMMyFF6P7%6}gg|9C0tolMZJb9VcQQDMJXE*M53*+9^Z z@{GE9{R%|xv-`~}juXOwPirWRNk7i2ZiM~%GSDK8ofAkDmz_OUXZ~#rRcQ;(wRJ5d zd%{wgZ;!w2#soz?ut}$N-2GV4*&}=r%iytkuQ$zy$*`1B^k=>AIwUllS7LB?D&bek z4$Nr9h)^^<@Y6Z&r4pfMu+C)ndSXBE%o6SL^=a+VulX)J@zUvMDTzJh6l0+_L}hV} zw$ty1t1maT3Q`$q_*jwxq# zpSt0?jnvHbk^Tj_>4Q133xFJs(`E^FhS+&E2>ZzGJ~mU3dv(xHBManjUt1DsA;rR? z7Yu=mYs)w0ozX{8%oa9Ys^9RzHm=nrt*NeTiZ4 zFtl>L5M~2Lf3xT~QVx9m1e3gA$FlYE5248Iwl!)#1hwmE|6OZ^YSem zxrSv`g?k3KrCpEo%ad2{j<*w9jz=6cO>Z6YO8Mb(#`BE)WeN`8q7PFbCf6lsq$Hf+ z>n#h`U@wkc;L@D6q{q(QtaSivf|cgFmGa+Jd?4@%TZeEgYPL+|I6s2op&za{*KOLc z-X5ih(e!ERxIi=vyZx2*siho<%u49~!53kI2>;lj5RGf}FBfHHWfc(|%pY6=mVv~& zvv0ru{DK9-g?A$Ll|$xa;u{-(&CI;Avb7gDy& z+nH$!VTsWtnvoxfi0GWo3i%vuM&8~5jJi^2)r$ulS))G0u4l1xdsk@5FPyqU(p1}U zz$a*E-@V$mw9CX_`~PXJ_)Z?iMM{Umc}r*TUU?R|F4jMOTXKrVg}BszxJ9Mwp5~d0 zwLBy_+}MZGpcj#--km+->k@(2U9tB*ZX<0<0ZEOSluT7|Iv0+5 zJtrQqkm)FNm4o}kT&!W(W#S6^T2Kf||3lrz{?OU%a=x>T)jg#ZUJqhD?QCIYCfe5r zhkco`gv~TNZ?;h#&IEB0?MzHC;P2iR24f1ktZh! z^WW695VtO~d$OiK!>r%pLp+UdZa$1*3BGb%#kBrO&CgDX9oRM0I!z0F*}rR``)hmM z=TGg|FP;bJ#8beOrb=`1K!zB4^_42^PXun8$BF{~7i~PzSj%hX)*U^<+y*ag`Doq5 z>V9WHe_{`70qY0ph3gF9OA5b5X`Qw*#;9RIXlex|cwi!*67qzah2mdKV zD`;10uS@u{wb<7E8^1>R3}qV#!LgyPvzMoD6KaB{@Vh;)F4vqWWf_J}h(J!e2JAKv z8!{k&M!E64B$yZinCBQxaab?47q$ZjF7a|hXQnWdpDU57Ms<*0!^2-#q>g3H;m1iD zv8hSVxzrbv+xQDDK;H&uNRd5?jLB7EG1A~@e%fN7wnuLPRmgkio*kXgH93;=WA2vI|l?W zbIh2E%DGIxu;R|E^p`Wb3XS0QGPu!<)GBYZ16x7aG5|)|@BRTydIyK+=&uHMMUmP) zXNh~VC&<<8XoY{m=PhydlhH;@O?ry^f}}BD`^pCTq>q{l%B>|UA8M zU+LA?eNk}R&-Kv|0&MqU@(Ow6^3J0D`_5ev5$xr!L` z-0;700d+I6*sXv6zGi^lZl@vvXa_WdswdN*o$U4#uMdwX6l16l%IuT0{@{I#AHIYS=W)p*R1Owq*zSo9_Ld z_G;CdLFB7FPMhLfSHL>gDL>T=n1~o{bvfF&5j?&J>4cv4tzQU{%F&LK-?d>zevfFv z5Q1B+Lm_6JtSu6amu{0#p{Yrb)PJ$SxmtfPW;SmqLDS=B2rJ9YT_Ut9#KzxH(68iu zAv`q9ooV`eCin0wF_Y`WS>bEmx3mbZb5@VC+TbXQw`kYRe6qK^4Xs_b5Vga2h#{hPM-x1R+E=MOOV+`XK@#gCr7>YMCNSz!R zx_&k0m)HrA41?ULHk)DOl#=0t zQETmS0fbi02UxkDK<))P@m(db_xM9+E+E@+bqd zp=Qi8v#AzWqZOkIr_)7UryZ{TvVsbz7k*xWuvfUxLtX)!R^>G?u;Uio6@eF+a! zYEC*s+Md2${gG2&0OWq@b+saetp zVe_{)H~Tr~pOQWO99G--W8-4?WvU+>^AxVa)0c{;7+m3%)7r8st)mh%hSPtN2fc<0 zf5`~(g6hobp+$LSURrM#k;6dOhD1U%JpRE`uOA>SI3lD5=o`ssMayiEXq;+gVMUnC6o&9V;-Op$ucuj8O8fI5}ILY9XI_Cn|;;(9*=Mw~>Lg_W7;w{q?G!7rbF z#Gr8PNjP5VB+U0hMUTObz?p1PHQ{Pbohafg+OrF!XyyfG0n~sG@9q0^Oht{1D~CpTf9io8$nCyE=YDn%8K|%|zOBc&&jk!?s|8 z?$~_iZ5pgh33zUQw-ua?pVp@NM8-%OV4yzPht+nN)_2~|o3W$12 zRP5pO+@9&cfqq{Vnq^WV?2v3ljLf$w+$R;$;-fhaK)|04Z+)azcxz(cch{w3#&BzH zOqyusb)7|ODZ(!$HLA|bn1WI%f{b(|pu?jRQriWtNy})d1C4AZwmAkd?J;{!(1bc$ z8~hsBK31)^3h_z`BbYiiYkz?s>-7znO`o_fx!#W7LxQSp0Ms>l0S2 z^sMF+d!333JfWmg*KL#m${3HSoItB&w9Hef@3xhWP*2%Q97YZ1^}>qzR)T0hO`9Cm zp#B>=Y!{`cZdo2+#+bNEut1LxUg_d=GSaJtHbicYYAyi?Q?L;(#vl6{Ht#MJV6o9t z0@Y>l>Rziqu8k9lL+}H}n7`pbzn9y(aeJ5I%04{fWO%EU$M3MbvWq`&t_^hb;qqz2 zlJM}gdXrl(V$WgM0<6fW$KowGS?x~IsH)yP$)O9ON2%Mxtb4r#g)H-7v2uD>!>Ly- z=J9iUNeyrYQFz!JN#T!kj#JGca`mZyCd>kmBtR^**FO`Lo$Bm6_2VA!(7ION-5#x_ z9*6d;TdQyCx8s6QE3Y$^5+APnA}MK<+dvBgNl22G>X|pUF#4&qou_{B zco!D`yljZOc@D<6)J9;`izgM2ur^gu8N`S8n+6wonSAdTX`niFj)jeRgtc9ixEQg# z^oLGnO4HEHc4`}o^I{Actm#L*T(F87e3G6UHi=3vF4&=R2OrrQ1aBK0|Ezd<@(W6# zpN<&Cjp4zrhqINB8YayxZ@w(0Fn( zliX>7(lowz)e}=gY$p_~uUo%Gs?;)TMn~b?&IGW4oJx1fVsnZR5|eDg_16k&3k^mG zxCE8H357>6Slwo9jKl5L97&+&we^J?`zQ&f2^m)3hWC_^U>E&8RR z^^|uOE`dk$b2v+agDcmjON%Q-K6XrQyqVp>jzbmWN9!tZaiBd$!Vmr+k|zK^#Xdd0 ziR`fMUPo@vlrgu(_LeF6F}p~g5`7vyr$k?C31i(K5VU_d^N-ABI8yK7B4sgI6ypZ- zXm4sg zS@7A2X~Sh+j!z}yj(?MuE})L9un>J99}6&!G|MpIl-CrcRY@$XQ$Jq`#oFI>TD;89=QvLhQ(u> zf8sdTQP!_(U2DEMHr!wL*b?L|)wV`Gq~V5R!qAd_K&hB?7vQ1ClmfmzcxW>KbajM~ zVQwIN<}PtxsHwRyU^l|lKP=R@y97!Z@$)!DaC63agja~9+I|oLKO{D#seCQt?m7A& zxX#M!zCYcM=L-`xPSW+@M1PzwVU#!Z;L(wLjC$TzA7U^_car1Oh(AD#6P+6Ixk(>n z{l#PVlR0^p@;sR}5}70GMG^|fj~BF-T+-WBcJxRmV@$8o$NqAGl}b=~^C~rM2}a!-itU(7Ko&K&@5`YvLA>a^F1-+TcW@Bgu4 zX^i}fV)>st3@(%fpdB>+b6WJ?u{|(TpnO2?qYstBJUMWf+3~3l4r`LPX^d zj!6|(%3$o3bX#Yg5+=a@b*6#nU;1+C_t@$!6Bd_KWc%ipQ0KtViZG3)+`hYAkucVs z9x&>i5#)fh%Kd!lQKh^=bSquc}B7zxL+?tF(Krqukxe9fd|uH+%zLRsLP}{2URua@8Te)tKl037m=eyJ zfLozpL1*8)&qNACTTdQ3!lnq54+*;-BwoAbi3u&}LG6Fc*=Qtlt-_wPJkcoJS%Ba5 zUP^vZ?>(0g$^f zw^4RuxxeJ+3$!W1#}Z!+Fdq~C&St^$`-jM!lIkAT`i7-GL!WvHfN21$n&t{N)o(NQ z-zz;1Z%O9tND`c)p29BaJ=Ne}^q#wfDDYo{4YR*Vxs{4=v#dYN+8MPSBe}rh$=Dy6 zWCRMba(>j;u&-;aMJ7RT;Cgt&sfOJwFnC-ig?O`m&QqNaR>1}-(9Qfw)fV4Ze{?U1 zED=i~X+&TQV$hrvRBIn3$LI7LGWLRmy~e-dS3r^Y@yOW1zon(qcDVz81@Y`Nn1B(y z$fw>aO?JDtM9;tq54dIkfyToEIyYmc%ni5Dva9&EW zg=$RuJ$NcM!MJS9R1oisk;38-S-QFnq!hxsrz1w?iw|#SwJeh5i==BK69kf6e*LYeOt$+OmSY7pjfL z+5E>4v{j+4uTuN4m|DBzN*F6=A1%l?H}6JjExP{G@w0~op?$1&4XCPLu1{bBF;8*) zQZ-yJtD;l-c@=Q8Zrf8wp145dguRJkm2x7HPaP8^AEUg$I9gu$FJ~*;eP6Dj!NKT% zGd({<^LHqThU35IrvFz3PQTvIEkU$)cvj=I0vOfIoE#9>A9`JT_dP8w4VMrwJ-(M_ z9wAa0n{|^uTCP6s?k}*Aj&*O6pkr>MMK|}|kjJT7!2cO0xqJs00Jkk*RZ!R3=K`Nb zcbM|u!#61T<;h{%9rnc{)X4lem_QPJeXO7PvWkzXakls(*m0*LFMV7i}%up#PoJSPO=(-p(6 zt=)R<7O6=33uWa#)cK4_TNpn6HAx~*P(0umwzQD!cD*GQJH=3#9V(8J=71oy_51NuAXy z+bWIAZ<^FpnoEBk3fhW?4E_w}(z5ldwX$&lvC-v5LV~&9W%RZ;D|9lIGeU@YJG;B` zs)l>2lsmMeQTwkp#$=PI`rnl~DZ{;2jizeuR#Z~0NBx-LV|Y2uCht!X^eKmGWo5@~%u~|L%~+6m^(4qtz9L2=IHI4GCux9?{u6XJKV!VLeVh zelhykH!Ik(N5|p5s;?81Ksy3HYBsBtHsUlz&1^M|m=AKyoUd;BlI=Uc#Nai;9DSqB zLE9a*eS)v4xhc#!vT0)j)95r#>kZ3uz*s^ZWo;a0;}iG7Lr6;kxJ#G>GG^p~9ZO;n zxbShiR_U0gl9E|hnQ0;C)@?5BSK+naoY3Dk)_?0wvoWWnZIB>88T%@gB=(24Kio^V z`dR$bk*((fN0g#s@%fCeREl;>H&dqs^UV^Ph@JTzH+NH}0~m#fAWDR8g%$CX=CoC% z<|u~%tXa+AH=UT(p+Igyq~fOfXc{Gv^2A)CPq@Jjt+aJma8Fse$U?YCOpoz?^(HvA zA?`s)a5t;9{+#R|P{-xOM|2qyz8y+j#O)#J3KZiuUM8wtaggvk!rmE$x2}W3C(gm> zU0<8#B;CG2quI(+$okCM+6|$LsqT*z)ryL~4|}qE1f#1vgBDUrD+Qc?J`h90+9CxY zQX>cLf+cqR2fu;+g}bW(9RXI*a-3q~C~3B8JtPC_WZh*3?VI};2H!OB^OiiRUb)yq zru4)}YqCglH?PIi6{Q7HwXvGw5XrioWRFn{;zDggZKhytlXbp^9W8Zpb{!5E)lFYP z-}Z1aiyTkQtIyVQ%{aD;?@tdB@t?9PzIaeUHF5*6|L~J}*R8XLhKv0!SyJEScyj{k zi?%jWc@eQ)7D2^H4~gC&!QxL^I5>kAMnBQu{z>kLifS=^2_r$28ahQC!$a7N94Nz) z`9QWsWWPC9#;#jgs8eAD#4X`WBZGrZn0hTzQrV}b{Ym1Jnp6Os7U2>X|L%8|lVR-t z(ij^O{<~BWJ5}-UZW2$xD*%iKMQ}a2922GsOiO!EXTS*p2Jiv;^_)b^_wP?L`oZmY zsiF8&lnF9}({g5_f*BSc55dE+w6wgOwOG?|G$IW7}hW zgE2zT`H*?M^o#j!ba09QPD)^p>yi@`p$IhqdU2Sa5Gdp2D=?JzTkLugqjoHm(A94Z?Z5uhK? z%w*=4X+LEdyXzd1L^M&`N>`Y;(DS5&8@4>Jketg$DM&RK58EdT-=v&ffxWX5gW$?b z$+cFd>pe1qE7a9Ofc@E4ICmAF>V30TxveqZiWl;mA(OwgNl)PWc=gwQM9mlzY|{*L z05>3H%GtN$apsz|a#TOUPlGeU`g$0AtSZ^z#i&%uxbTd=wTs?3v6I1L?da1)u=Vcg zxZ7jD@&p`$Erh|gBPN$<`#Uc*BSK+%FKOQ>XFoQk2vIuXL-)1 z(0AtDb88j|26G?Xd8uPklTPxYLDwhOE-WTi(Ld!_j%vW^UUPDKyV9eW7%v{MJ5jydy8Xv@uiv-ynW){wL zc-z-V_vERM%yOd2c$1acI1Rgrn3H=q(zmZ4Y22MONOxY&L1gS|=NW88Y1(Mt>^V{pS^oiJksMzV5!ts{;kCqbUaCSpCQaCJC9pj&x$|u#Yk*Ye zgnmlT`qjhT4fD!MmUw92WT*PTnRr?w!^TWZOkMvxL1LT`^bws<=1&LF{M9h~$Rd-( zs6hdf^-^sG>R3?&dT!t09Su9l<=lae>jf0{P#)8E4B0@ymFZ+fWOmx-Fg0WAjk;m)byc7MBmDlrjI^A0f z_PGa;LrvG-IS>g1>Jh#)p(KjxZPK9Q*rLrL!68^X(In(XYNRp+SOr z=$13hp;u~~s#eVVMBN9}0-dy7C0Yrus1A9uM6IaOAP|>LgOVB9+{GZ)3~Bo)3p1j< z`qz)xsbjfhix37$9*(RE1P%2p6F(wtZs0srGmVN_*~SPbZ-qPho}~^93^Z3U{-eFv zrFSm=n>>$m^)8*!`shis&3PCqCz_yGu3up1$~U&kz1AUg;=$s48{sZv3e5?HIL{DT zEwQa=A^!PH4Ap^x71-YRGuJzTVzIQwz_|E^yK*+2wWfuQPQJ7G@n3c|(-5)rUtdeE z{mgAB0LTS>Jvvc<@w6=oY5@Bnsrrx$z!@oz82qtG_rE)eW6A03@0^xDg#vNsbMEWE z_VJ+O;^oa8-2e~@cITHr_x9j^^vHtu-sN*rCNY0zAmFavo8%1kivfoZf?c`K&aQ|} z|8#Yzk&VN9q5h{xC!fb9vpY1@)F7i69VPIXhb0k446<2TI(Y*tv={pZV>^du&O*r{ zI{SWLi!^ZjxVpFBKT~SMkWa856 zdU)n-04t@FB#qa)K;u$}OM?P}=6so+omP62V{ShHr!2{R-PFu12<)F@%mjg$e2tj_H9-&TZ*|eZf%C}ZU%)Vq zDW1$lTjRe{13v+E3?ZO$>gQ=}4bBEJaW(E8Ch`O`)#$@n#Q15!!hDBG6j;F!?hXWP z2ew7JiG>C4E|q!E+t+!Vq?kv1$m!}1Vmnu^sQeP*t+YkP(;w!>S*a%k2QB-jxBk;^ zI~TF3U(wS_4X6Z}bn>d07VPiLCZJit_2f_k>lVwrI`=~bqgxBLf=zzkR(h$+5bcTuE`uJvtT7@hG19fnlaDyk4YJpHZ>=<7BLKF z2F!Y|+F~3bDywIeKmXJe^m54*=45uUl~Vru1!i~D@&=~ob6$c2tmTW@PObwC z#ahUXC!twIIpf;;5?&OViPIK8+EgItil`k~e^l@5mN~ZJ)!bXbulD7&W15R((i_sg z(+sc1L@PB|ov3tQu#7lEFuQt3%CrMn*`^r1TF)Ds02*y@4hj1|F?!CJQ30P+-%WIF z1J%0QG-^ZC^84o>8!J1g(UR25)%v{exuqIA!sJdjo?0u~@reAVGu>u&@d*=*)R7O@!N0*UGuI!3O8(zi^9&*3ECJc|nb|t5zJMvG<0rWSuxYRtDwYQJ)-j)VI` zv$oVh)*jiV3tezuI-3r+vg-TlLmzv@;`GEgvnbJcXJ$lYA#CAJnK-zcY$`i36!BgW z_=S_iRYZWDVSxV1499O8dQaE<Yb(h1v_IauwCf!n*>KjaF4nJzmK z;LZ*P6FacOy!Tt$aX!Vw#GEk6M;Oqr9D0UIHC>$601?y9F(Dx#IERN`J@Gu!y}0C| ztzW(fJ~m7jXQPd`YdG}u0iP$u4(tnlNMeC1*1LF}mY@>^fEF$Yy@wxASHRbV6G!Xo zh4&viS>4auf%b14g816g-u@Gd#C6+#H^Tabet(DS+hB;D`5*<2rq_<^?Bx(iwO=78x{)`L?hJI@(WvS=?>@+-b^95qiBu>y}@Kwm+L-{WGv5_x)=g zBHKpxFLDMi?Et!yh23@6DUY`vTKi*ays7YFH3scp%6w59M54M*u3;ppc!(#&9b*Gfo=@#pI2| z#0;JH>ENwJ9Ousj_ExCzJYWdqfJz&M`|$aHrrCM$@yp7aD{`AuiyL2B_ULg>s-|j`#D0L zy;Rx5>Ht4AANMAM?Fb-Ppz1WA409XRq0%~PPKs5o?KxdJ)=<~%?5jtfCJqP8r}4Ok zyGSl}8O(jA0(=5!l(kv1zquGS6uw}sW| zylI-Z32q7x1&JrChi$7fx`he9mtMQbA0-U#pPqD^;mcp&{gAl8PFiLgv&F1MVrAtIPnDl^YPn7ReWGT>EQr8-i>c#ytPhNGUT>=VxZD6EsC{Lv02=^+ z9fl=(&Q29wz*Og{5PTV4$xcUW0BjyN7IM*|(*2GjK{S2wbMVT=oA&%Laqijooz$8< zU1$sPL-In>FunSfRSzz+UfH6TsExGFsCx>eiE)%!!~u<39myHBZJG`zhlf^gRFZRUffo^b%q*VKh#dQ2VN*K$q#IRCM}@KD7L-fD_=inq zw^#ZC+)U#>ndk;Ee0@63RY4})61Rig-N5aY&faLmu*}I3NMkgpXN?z+jy7i?;Iw~q zdvkVeXRM5FPoGsjVvE{zIQZn_6rSd6(OjESVublsW1w!tPA6F@$$67^EffxR+5ZpXWwdH1h*v#O}ekZ#>Q7{eUx{tyt}x zo#jQ}Al{>{*jRslf&xaV@arGY8q}ld+}aEc=?lhA+w} zp7u)ZXaVaR@niUW=iZ5$9{1DV)p!@j^&3s^)qOpMNx4)TB$1PgPShEov~E-sqYDte zCuQst`lpG~XsUQX7>GQ>ZaR3p8S|%)%%2%I!m_QF>{zE)y%=&GxLaF|7Guu4I2)2o z=gd<)mVbWt^L|yZ=hFLKY5%A3cg|m4tr63Jm zj`qO7@(J*LEM2^8-qxIj$SW2x*?%LTo(jTgSKa~i^Wz$p(7{y)dC4f~WQ*&cmLGqw zKl$}HKp|r#OGf*Wg#{pxcUm1_rla;>(OR+C66fKDq`_D!^x<95L4xs2T7dZbVy=d_ zfiUsp=BFm&cPx<|uXyhvW+X7(D!}HT{S$qgRy!-;qwa^dQQ;A6I161CH-Je~>iUQk z%g~Zv<>ui5(|lZ9Q7{;nzPue+qviIy_ka0s%X@kXZGc^YWVE@j)1ggX{;SxORG&GrO71i(!YoMXpY;I#Th#^4ye5`vu)Ktl@mf{uqL& zdPc;%kEf$?5DGL$s2m+#o%B?BY1iM2R6Kpxx1>qNu-UoAjnPNkF4f9Xw8D_?$;iVc z&fPLME`LWgHD*GbxNHBdOB3jv7i=hj!=L#cC6ienrKC)#d4b=!t`g(HXH51{VM(rD z!};xN1a`XGHS32>#u2V1C50~@c0kuTPfdV-*ifOH9W&>vRa&b?*WaCdR|v5c zBEA@FVg4D+Pipre8+;!R8OKtz;*0SkstxF1nj>&5V#@uJBsox}RlN~6S}+QgqkB}$ zbz@^0#?7VG(jAdINWPPw^9*-EgBrq%x*h*TRmvd>Vs#oU?b;giTws_y9@SqjDdl5& z+(;}g=ah5AswM^_&7k_|%B^nJ%`UOcJ0-Uf_qds~-aV79x9ZVAz>g|28xE1+gOge? z1SnYTs=fu$4~mI3oX9O^+QU^W&X_iq1o-jQg z0r;j^#rXQ8a>aN#nDTrbzn4X$#q8-t&z!jjDxrSi&ieNSt;IK@8;i2x_LL=fJ+@3* z9YkrC*_{hM8QJlL{0>j34QsaSr#jopYz-VF^H!?G10@dUU+d&FeKE5}%xCjiLvK_( z3wLos+|3-yInv83$uihd_@FZz*9ZbZ{>SbpW`Ueu(hmDlZHetVJ4GKlcS*a<`4DKR zi+6!n@gsn0TUm{jjhGQRn&*5~i`Xek6%+}q{q$VClJZRMxaJi%tv|DVCr$iN*K8p} zMBH^Ze~PKwlRvBdByhed%>U|FX%zmae${TZp(gs{A39oTBKlBw!ORpfx|QHU)<#1^ zz@!~w+;+$tHpT1K-JPMWDH;1UwX_MGjW1W9M~4&j-t6RgQFo$Z%D6og4GN1N@Mv-3 z9$Ue%619yMhVKiCRrY|-OG8Z@a*d$swE`23!0XUutVGjol&sDrz+u$9nriYc1OpOf$} z1D{pTeq8=AK|7fISW)aat#3mZ^=1dDHvj#q$Bzp;zij!Dl7zOnJYsQxSE@0jb^N}R z$B{$Xh=g>SYb-XPhh-x{1(3wYw4cB0HygfM>%pW{b`srp-!Y8Mkl>}nSCviXY$FP5Dd6`W~u9J#xDdgUOGo2Q0X34?Zhhb6u;-*@@CsQq)@A-{9-m( zxOQ2#uPMy3eKLnu`O#@R_yu?$G)T7>1I^%MXA6ixFj zGoM1;+%muac-^^xy|-ss>Rc>mbTKAjg3{v#+L5R;iup;NNI$MGy7*X9>J#QcabXG- zs(`$f)z8U7E1u^@4>P4NDg<&C{JqdA4YzRCN8mb5b(-TrZv@Ng|0F&?|2(}B zElhzl$(`O{m9{l)iLSQRelN87K%qa2)iw5EJnfbFJrGOtd~>X759bw}*}GOpqWxg2 zM#FRN`2HCBc@*R?IA#$c1N&1bznpT^^Im0)8c4$@M}KE^u#_-Bj~#|XfDZ08=_>?R z1#BlWn5N;Lz~05T%W3rtJOJ!rH45$6TyhF>OOojyuuFQ5XImOf!2g^a2AJPI#O$sV zHrfA^Z7Q&vQoQ>v=+rI+vLX}t)nAlr#NB)M1~x9I|LOkvoGCdaCGR~TcmO6rVAJPI z4i~E$eQ2)q4*&oIHdX!`1fat*28#fIZQIy9{vH4TbR{@`x50NKm9WD0)6f4K0ssR2 zVmwh`qL16OWA6@j&vfSY1qa-BO#s5cDqf)5Q#FI!v;egEBGdZ1yITPi7z%h$Q&WY} z0SbUM3H}W&k4Q=B^#odA)tHbgftVL@|7uH5nRV>Wrr)}?E}DAe{my83$T&S-bpY(A z0l@ge0OAqx2!Vqy_c=qn7M-@jB|8sD;0zJ|lHZC22xpNB@LlKlzc&1p|O#SNlVG`Ir|A;4mF-TKcVSk4N zlyah!_tyQas}$IqP{n|sl}V2m#@6z0kSP}ti-d{_4OLn%sLU&|q5_Mg6+e`BZVQJ% z2!-z}cZWLgW<*Sj8CM=g%(K!s|LPrn?Z>=>BsEsf_>KdNB6nP@Y&Knl!}aiJ8bBd% z)Es8br8nJxA`CfSxz)BQ-b zG9JT>UVn4A@wU1s+%Se*Z0+d8?lZk=IpPB-M#8)a`$sZF$8X!vI)?*@s>y5p>a2Or zqJQs^G!m^*CsQ0xq3uekZGD(q&K&p<+vzj$D4zFv6(+WcN-Pa}mOnB`Q7hb(K;YY>#Yo&?D7tV04UM3UZ82 zsvj>KA+mj*XI!LkJ)mz)bmR^!-xY{t7L61)$>1wNO{ThlTh?q(PF`1%^-U__7;3Rc zB}%7vzn}dEDwZ_6&-?DP33YOvftL2>)!(Vg@V7-&IXQ0*yIur=1y3xQ8{Ni``wpBY zHaKDy{30ow*sdWlO@=x27Xt6Hty(2X2NUYjFj86(-}6U_71$b`&`&I+mI0FqWIm=V zx#f-*O-^WwN1~LfX6ero=bY`CzElCaRr=&@@_L|s34xvP!bgUnz2b`d@S`S zqU->u!>W^!-tVOVY0zRib(5?|t)3;ukjAsR#xU7X6Gc8;v-|m@r@oG#J~$VDJKSd1 zMq7T7fzU>mesNbpzRLjmFfh6S=QGq&$S1*fTRe5t?d1}T-2Km|vuK6bLPNfA z*uV}{(7Rl@nPWGUE#-Mi*Ie0e(fdZ>DWBr=X+`wYy)|vU)TupmQF%WeaNXc8DRhza zV_yoSoGDUj*-SF}NyqK>#qj#?9-5>v!u$MZwn`lIiboVGhtnb?_pZQ;-F0ntKSkuW z@-wLgJKkz*SvE!U-^6*i^)L9_{%5AoQwm@=;sD!P5?}wFY3Vz{%-Y>bTHBdua(<#+ zXb`2Fq1cIA`9e)>O`vd7%a4UO@1RtTd`E@*&F`GVfuEeX8#N6ZvN_RqVNu-?4X!r6 zOm{nef8h44z=sjqX!k^x0mABXlsZG1=bZU;soquk9v*%!!iU8%un_1Md6n$+6OKnP zaVEXbE44;U8_@nIM;69W(BrcO0;o`SRz;RUlAxGRUn5YYsgC^c_njlsJ={KA4;uWD zpKwPD_&hcPrN}UG(VibAZ^D^c+Ve=r`hINBp08pChi>3O^8lGsI5*_?NXtf&^h_o- z=igelRlAftrOd#&5ya%$wceOsHgiBYPN&47Lu?*;_ihL2rL##I1J%597sdp00dmr*yg(wxn<% z4N|X&Hieynjq^`H@+!ZkyF~bvJ5799cuzgUhDzdNz%3e=^f$aeg+%Z})T(mo&?ubQ zPFnV&4UmNj6Qh2}Wx97CF9BX7tQ1ScK>^GlzmEEQ@0wqKV;yY%KR^)3X_*lQCH)q0 zVq&8!$TJjrZtf*WMP?;}PRs45_XT?*V))yDckX+7X87;)6(|2AscT?*dmZoj{K7M= zHub;ry8oBU{m-~uykA^ylBe+Ux5*qG9px>W@mYt(fz`hlJI?`J;bZ)hwUrh(b17gz z6=&A8UF(MKQr5@V=FIvk()EM?4Vq0LootWv1#+lAM(#k!K^peZbLCo~nyG|44sQfV zrkncL0);IAds^Ke@eW}|Y~ywO&-DTI3shW|#_iktaj&c)@sbRrOPtJM@8hbLuAIk< zgF??+{ud$Kx%XL}6&e9PZfXwMf6-2Bo77|tx16+A2&r`WF1S%Ik)!E`B(=|i>=Uxm>z z8KIR@ImOSaYE05=Kl;AmQqu?2c$nDlVB14P&f{GlS2^3&SAM)ZhQq;&3D3Li2s^ro zQf^F?jWC!#8TV|+RpNOO0{=cC8@hqCV)*>)GUd zwJJOvo1xFD`?Ln{b=}GO1}Me#1gwzv33K+B8V}PCJrZqg2ISjY%l7v_^*=pQ*m|*a zrOY+da!RYrMx(_cU^gk&?W^PDoP~0*NG|q44YJ~}s$!Md> z=F`ontFSF5oc>VA?uTrD6{VoSI>ea+z#%^`$Q7m2x5Mwwd#6Z1nbY-4sfEcYY&c~- z7DEfvaJ8vE#E4zE=rsEASmc|HaQdf*>n{ZsTqhCK&h(E*HAYl~*%eh#t|gyvll2F@6g?u7q_Y#bu+3Z?m3gQnzhS12$3Fg7=C! zkU3&;@mL_@Bdy`toM!W?}ShI@qRn?b$*Qi1lM^oxjlVPfa$#Wqrku@?CzG1_gGcUjlF3FHWmj+o@t2Hxg^2`!pvAS zBsUEt=ZyDnypPVAM zQ0I5TSfXE$z`0s+3}2N~d35H;qK?nBpBXjx8lOBSmyI+++J#rQI8emE=3dIfN;TDy z+@fHm_Lz7%s?2>mhGI|2g^67I(#g_^Ifkg68RM*cR|iP4*4wqtA{nUA=GVcF)g%r2 zJjv03L_+54tGAyuw1CCSsV7Wg6V%S-dbL9O<#CkaZ;@+C4)4Hk34*lz&ED zXk+pk&Z>F+55tS`hKt(snd7r_Mn507?VaJOK`*<8=*IVWalCj$tA7xy3@`O8hlIZH zXz5hlt%efGINAz9UB`4{zvECD9hEd7pdJhw)29(~hIalPqq)hM9(R(%GLh0YEh>?{ z0#64%-Q*qmagROmoYjsm>z=eWx0hAkRB_HvkeCQqZ;&&oM3b*L8RZ0AD zKKJ2^o*`*Q&`lKRf*s6Wsy;{TnX4WIlA&+2yV@T<{;IM-@$L7Y0fY@q&hR5M!%h)_ zy`vhP!<94o(hs3-@TZB_)C4?$e4O#L*6{0j7OKG)@s;DHsMxN6f4!i7FxP~F=;^&% z6=$HsGu&8=#nff>Y95RQr9DlX?NUutFn(2{R2Av>W;M?pwPi%3cNyeJ&MnjF3`Aa z6?qD#T<^*dU8Tcgvflj2222_OIS-EYX7M;&?ykzn*lq3J-rgx&<@@%^;OQ%nE8mtJ zWw9?D98KzRtQ?0=HDJUar?QgVTv=HG-S`1#)g=4jedh9Ny=~yf$5y`c0ac?nvvDXl z6j1^MTHqjP4VGwAQ_1zGE%SL_Z&ac~(|965GFm0F4hOGZz1$e;-#m^1;dg4EfQX0) zFK;t;2hdf!EY-XhY$+)zq&Kg*5N`&vf$Qi+FSO0NV;Ov(lCws1KkT;O<5abnaT0C1 z5|W!a{x5;f{UMI2`+PIW?^DQgX-B~VKeP6*8a5)hsrLu$ek3^DA>mmAHKQ9E*p=`P z2(UB7j@>+hHNO^i+XhR`Qf-nvJ$sc>~h% z=^?~tZijzDZ}Lp@+!Y7McIF)}p>1CIow~c)BPr5hJn=tg{zA2`Sx^{RrvAiDpj@e)4R_8V9pfU?a4f{Ka zS@vICO3R;*tAuL|<;!fb%6(l_9~XB~&k$*RaGtlNSrzA#aD=EZur7I3z$#q!>86Ax z!9f`Z<@3jy%BmX5F7!kyX=A=we`u1YSz6kuidp#B9iFQQ1LfP9Y@Z}4PZ?X6fCEpt zo=`7s-`d#N(Ry>U$!XPBQBoe{(wB z4HeJWut2`g8OhfD@KKF_vgjfD?7eZctCMc>9cL(G^z+uE^@YH-8dD@+dlva*$pU^r zcwf6E1xsW^a(8oyt(KVqS6{Vfhnc$0Wd3x(@Il&Na6V%WUVsHB=WBcMg_S3m{E9(0 zV`pjva!t;!?&ZV6$;PJ@b^53G_awKnh&8e;rms=8EoUpSI5`te!Q zSknYERCN%4vQl__X>^ihAAwM2b|)uO{%jq*Ox{Ot9ZQ+OBAwfLr$9m^MFreq$upju zU2g?hXfy7WS;@J3rIneWMlV@4Qn|f z`DgS^@u<9t(wn?X6p>+&aWeM4lalzuf^vyUMK8YcxN9Zmo%#FZTAFwGB6L&{di)a} zc{1!cuj>cpKRhT`D4)Emyy#)4&Pr3{e1!?Fo=R9t@;thR#k01|!nyFm!9xH-!=h%I zAS0$RD?YkzoiI{moTgKk9j|Q{R39A1r)+X6cLN#1sX%KmHJ1NHCIl!-4l<~N*sS{? zWJJNI@A;qgD{+SDro_uoNo#hpLJu;BCRX3}(!Q~J4NJRm$70;Y1A`nq6#b%~;uPPV zqQhdBYu=!V8_<2qx^zc;={i->I-}DYL7J?d&dqS+U)gba{bIz92ZW&#As=O_No2CF7@SgE?ZDiyYQk z?LNYb&@|mDGty8jUz&4*I_`^%j2vBKp3W?XU-RoYbmUe^_MqZ z*r)H_z~P9M$G(tVHM{I6*xZPeX5)%X3+s}SA)3$lIvhgiTjw?tHXuJ>S zX5Z4jL5Ws+jQ63t2sV3^sOHf@SXBvGNR@{bOAqbvlH;)fF!lvjc}Dpfi?jcm$8RIY z@DuO)xw$zo-h`bAdg8|#E!SeacX04Ug()}D$j}sAhvN~A7`hb;?5=tZlO2VJg`6Ny zli=Oi?X(_QDv$W^#If1#eiJcc_LH9}vtkil+F&HewHpfiME`3f^ZKWk-fYpmbp|Ea zmEaZ;@rGb0g1!aPT?gZt(qPG6S^&9Qb~aW>+y?vWGVZyHbc2B)BO_V7()vF^XWUEG z_dh(A0?{2NOfX=&8L!a}UGu#nK%gU`rM%633|Je>^EH8JuX?Rz*o@^#(k7N^_MtPR^2 zw2_ZB#>iT6`je8E?$lV#_YCg}YC(LQ*BU^2U5%|obWHn|m*V6U6+}2N@_Ed-BELmC z4H7FaM=l==)g$s!ko(=u3-Q%wp2L6QQ73VmIHNKGeN7n!ijF=suZdYWa(k*nIG zwnMS1xU^2n!5GkvJLxh3WnMZ%;@ z`InVOhmuI{gJD@SZS|KG$Fym>bm`>dWP?tm+@03~i#aokl-z1hpUedW?*m%x8>y(q zUG88=S+-@lwXP>~3H4*aVm#bcN4e9)P=V+gGHxA}ZK~PmtrBlOnGOGC*HL|*spaa? z2$`L{UF1r{i-C&t;2^f?Rrp*nM`mQDTkYYKH)rZ;hxnvoS8;5$!+W5x{#&Bf&RLau z^a;Z}JP~Fw%vEgH!tu-P_J1Ua=2MukXi%@eNa-JZL3qTe|7F0e>4c|l+IQnDW5Z_V zU_lV6H(9vUf192}NNLnxg9tgONH)pv%4I?~=g5{LbKzQL?PR`)Kz60E3_9naMr&Jq z_hA|iPPO7c%|@X1{rQ_1>L8%XZq}e2IhdpDhdx!-axMQ;-u$^^r@=2JDG8yZyv6`p zj1zglXMXNjUS0;Z>cPRm$;k=*bXZu}W4~TmbLcH>(_x{?7GqH7S>%cL0Z^v@SnK|( zeqAMERPz>HBf%`oU6nt}Wf`It0dMWvO;7If83=tqXZ6PAhF9KMKoI0o}p)S+5?rG7Gv_GK&_k)`Z|mDJj*{ zQIX)#>=C67j*bIE>0eFnwocc&fs_7L1S{QJi|ikp-}Cgzmp3;zpY=JO{xEkB9GK#P z$5Pd-FFR>)Xs98vc2Gf4@2}=Y$B73I+gB~@+l<<|TJ_h}3=i4VgXTZpA-wN_F`F{4wQk9hx$jM>!f9bq# z!UsrAoUzwSo&V`7{O9ZS>z!yC92^Wr%+$;Re9(35y?+(Q>>cwTL`7>W;29iQNhOKm IXGU-TAJ+s}>Hq)$ diff --git a/docs/manual-test.md b/docs/manual-test.md index cde0423..c104ff1 100644 --- a/docs/manual-test.md +++ b/docs/manual-test.md @@ -8,7 +8,9 @@ Use these checks for release smoke testing on Windows 11. For restore behavior, - Confirm the installed exe exists under `%LOCALAPPDATA%\WindowAutoLayout`. - Confirm the installed file version matches the release version. - Start the installed app once and confirm it stays alive. +- Start the installed app again and confirm the existing window opens without creating a second process. - Close the visible window and confirm the tray icon remains when close-to-tray is enabled. +- Disable close-to-tray, close the window, and confirm the process exits instead of becoming unreachable. ## Monitor And Window Detection @@ -29,7 +31,9 @@ Use these checks for release smoke testing on Windows 11. For restore behavior, - Move both windows away from their saved positions. - Restore the profile from Dashboard. - Minimize one window and restore again. -- Maximize one window, save the layout, and restore again. +- Maximize one window, capture it, and confirm its saved window state remains maximized after restore. +- Change monitor resolution and confirm oversized saved bounds are constrained to the current display. +- With three displays connected, confirm nearest fallback chooses the display closest to the saved profile size. - Enable `Move all matching windows` for a browser and verify multiple matching windows move when intended. - Check Logs for applied layout counts. @@ -57,7 +61,7 @@ This is the important streaming test. - Confirm app launch failures appear in Logs. - Confirm running tray apps are woken before a duplicate launch is attempted. -## Startup, Tray, And Hotkey +## Startup, Tray, And Input Safety - Enable startup restore and confirm the HKCU Run entry is created. - Confirm the Run entry includes `--startup-restore`. @@ -66,17 +70,28 @@ This is the important streaming test. - Confirm the default startup profile restores. - Close the main window and confirm it hides to tray. - Restore from the tray menu. -- Press `Ctrl+Alt+L` and confirm the selected/default profile restores. -- Disable the hotkey and confirm it no longer triggers. +- Confirm `Ctrl+Alt+L` is not reserved by WindowAutoLayout. +- Confirm the installed process stays at Below normal priority. +- Confirm there is only one WindowAutoLayout tray process. ## Layout Lock - Enable layout lock for the streaming profile. -- Move a target window during the lock and confirm it snaps back. - Press Show Desktop and confirm the profile is restored while lock is active. -- Minimize OBS during the lock and confirm it is pulled back when OBS settings allow it. -- Confirm the lock stops after its duration or when disabled manually. -- Watch CPU usage briefly and confirm the lock is not causing heavy idle load. +- Leave a fullscreen app and confirm the profile is restored after returning to the desktop. +- Return to the fullscreen app immediately and confirm the pending restore is cancelled. +- Confirm a closed profile app is not launched by an automatic event restore. +- Confirm disabling the lock stops event restores. +- Sample idle CPU and confirm there is no recurring five-second activity. +- Trigger restore twice quickly and confirm only one restore runs. +- Start a restore while a fullscreen game is foreground and confirm the result says Paused rather than Success. + +## Config Import + +- Import a valid exported config and confirm it remains editable before saving. +- Import malformed JSON and confirm the current config stays unchanged. +- Import duplicate or empty profile/app IDs and confirm they are repaired without losing entries. +- Import extreme delay and rectangle values and confirm they are constrained to safe bounds. ## Failure Cases diff --git a/docs/release.md b/docs/release.md index b868919..ab6874d 100644 --- a/docs/release.md +++ b/docs/release.md @@ -18,7 +18,7 @@ Update these together for every release: The tag must match the package version: ```text -package.json version 0.1.18 -> tag v0.1.18 +package.json version 0.1.23 -> tag v0.1.23 ``` ## Local Finish Pass @@ -68,17 +68,27 @@ Minimum OBS release check: ## Publish +Before creating a public tag: + +- replace the pending `LICENSE` text with the final distribution terms +- configure Authenticode signing for both Windows installers +- verify the signing certificate and timestamp service in CI +- add a signed update channel before advertising automatic updates + +The workflow intentionally rejects release tags while `LICENSE` still contains the pending no-redistribution text. Do not publish unsigned installers as a production release. + Commit the release changes, then push main and the version tag: ```powershell git push origin main -git tag v0.1.18 -git push origin v0.1.18 +git tag v0.1.23 +git push origin v0.1.23 ``` The GitHub workflow: - validates the tag matches `package.json` +- blocks distribution while the repository license is still pending - runs TypeScript checks - runs the frontend dependency audit - runs Rust format, check, test, and clippy passes @@ -101,7 +111,7 @@ WindowAutoLayout__x64_en-US.msi.sha256 Verify the published release: ```powershell -gh release view v0.1.18 --repo Riqqqque/WindowAutoLayout --json url,tagName,name,isDraft,isPrerelease,assets +gh release view v0.1.23 --repo Riqqqque/WindowAutoLayout --json url,tagName,name,isDraft,isPrerelease,assets ``` ## Troubleshooting Release Builds diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 64ee06c..2126bb4 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -103,20 +103,17 @@ Fix: ## Show Desktop Still Hides Windows -The Windows Show Desktop command can minimize windows. Layout lock is the recovery mechanism. +The Windows Show Desktop command can minimize windows. Event lock is the recovery mechanism. -Turn on layout lock for the profile. While the lock is active, WindowAutoLayout watches the managed windows and restores the profile when one moves, minimizes, hides, or disappears. +Turn on layout lock for the profile and leave WindowAutoLayout running in the tray. The lock listens for the desktop reveal and restores already-running profile windows without launching apps or taking focus. -## Hotkey Does Nothing +## Game Or Input Feels Affected -Check: +WindowAutoLayout does not register a global hotkey, raw mouse/keyboard device events, or low-level input hooks. The layout lock is event-driven and has no recurring scan interval. -- hotkey is enabled in Settings -- the accelerator is valid -- another app is not already using the same hotkey -- WindowAutoLayout is still running in the tray +Check Task Manager for exactly one `WindowAutoLayout.exe` process. Its priority should be Below normal, and CPU should stay at or near zero while idle. Disable layout lock temporarily to separate a shell-triggered restore from unrelated game behavior. -Try changing the hotkey, saving, then changing it back. +Automatic restore is skipped whenever a known game or any fullscreen foreground window is active. If a restore was already waiting to run, returning to the game cancels it. ## Startup Restore Does Not Run diff --git a/docs/usage.md b/docs/usage.md index c6b717f..fb55bb2 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -11,7 +11,7 @@ WindowAutoLayout is built around one idea: save a workspace once, then bring it | Layout | The saved X, Y, width, and height for an app window | | Target monitor | The monitor where the saved layout should land | | Restore | The action that launches missing apps, finds windows, and moves them | -| Layout lock | A temporary keep-in-place mode that restores a profile when managed windows change | +| Layout lock | An event-driven guard that recovers a profile after Show Desktop or leaving a fullscreen app | ## First Setup @@ -24,7 +24,7 @@ WindowAutoLayout is built around one idea: save a workspace once, then bring it 7. Fine-tune any app entry in Apps or any single window in Layout if needed. 8. Press Restore. -Once that works, enable startup restore or use the tray menu and hotkey. +Once that works, enable startup restore or use the tray menu. ## Profiles @@ -97,7 +97,6 @@ Recommended OBS app entry: | Pull hidden/tray windows | On | | Wake running tray apps | On | | Restore if minimized | On | -| Launch if missing | On | | Detection timeout | At least 25 seconds | | Retry interval | Around 700 ms | @@ -118,11 +117,11 @@ Discord can take a moment to expose its main Electron window after launch. Keep ## Startup Restore -Startup restore is controlled from Settings and Profiles. +Startup restore is controlled from Settings, with the default profile selected under Profiles. Settings control whether WindowAutoLayout starts with Windows, whether it starts minimized to tray, how long it waits, and whether it restores on launch. -Profiles control which profile is the default startup profile and whether that profile participates in startup restore. +Profiles control which profile is the default startup profile. The startup command is stored in the current user's Run key: @@ -134,26 +133,17 @@ No admin rights are required for normal startup registration. ## Layout Lock -Layout lock is for keeping a live workspace in place. +Layout lock is for recovering a workspace from shell actions without continuous background work. -When enabled, WindowAutoLayout watches the selected profile and restores only when a managed window changes. That means: +When enabled: -- Show Desktop gets corrected while the lock is active. -- Accidentally dragged windows snap back. -- Minimized matching windows get pulled back if the app settings allow it. -- The app keeps watching the selected profile until the lock is disabled or the lock duration ends. +- Show Desktop triggers a restore of already-running profile windows. +- Leaving a game or fullscreen app triggers a delayed restore. +- Returning to a game before restore begins cancels the background restore. +- Automatic restore never launches a missing app or forces keyboard focus. +- No window scan runs on a timer while the desktop is idle. -The lock interval is clamped internally to 2-5 seconds. If a fullscreen app that is not part of the profile is foreground, WindowAutoLayout pauses lock work longer so games are not polled hard. - -## Hotkey - -The default hotkey is: - -```text -Ctrl+Alt+L -``` - -When enabled, the hotkey restores the selected/default profile. If restore-without-opening is enabled, the main WindowAutoLayout window does not need to pop open. +Use the Dashboard Restore button or tray Restore command when missing apps also need to launch. ## Config And Logs @@ -163,7 +153,7 @@ User config and logs are stored under: %APPDATA%\com.rique.windowautolayout ``` -The config is JSON and can be imported or exported from Settings. If the config becomes unreadable, WindowAutoLayout backs it up and starts from a fresh default config. +The config is JSON and can be imported or exported from Settings. Imports are parsed and normalized by the Rust backend before the interface uses them. If the config becomes unreadable, WindowAutoLayout backs it up and starts from a fresh default config. ## Everyday Streaming Flow @@ -174,4 +164,4 @@ The config is JSON and can be imported or exported from Settings. If the config 5. Missing apps open. 6. Tray apps are pulled forward. 7. The selected streaming profile is restored. -8. Layout lock keeps the workspace stable if enabled. +8. Layout lock recovers the workspace after relevant shell events if enabled. diff --git a/examples/windowautolayout.example.json b/examples/windowautolayout.example.json index faec8f1..bc5dc42 100644 --- a/examples/windowautolayout.example.json +++ b/examples/windowautolayout.example.json @@ -1,11 +1,9 @@ { - "schemaVersion": 3, - "appVersion": "0.1.18", + "schemaVersion": 5, + "appVersion": "0.1.23", "global": { "defaultMonitorId": null, - "monitorMissingBehavior": "nearestMatch", - "warnWhenMonitorMissing": true, - "advancedMode": false + "monitorMissingBehavior": "nearestMatch" }, "startup": { "enabled": false, @@ -13,24 +11,14 @@ "defaultProfileId": "profile-streaming", "delaySeconds": 8, "restoreOnLaunch": true, - "launchMissingApps": true, - "enforceAfterStartup": true + "launchMissingApps": true }, "tray": { - "minimizeToTrayOnClose": true, - "showRestoreStatus": true - }, - "hotkey": { - "enabled": true, - "accelerator": "Ctrl+Alt+L", - "restoreWithoutOpening": true + "minimizeToTrayOnClose": true }, "enforcement": { "enabled": false, - "profileId": "profile-streaming", - "durationSeconds": 30, - "intervalMs": 2000, - "pauseForFullscreenGames": true + "profileId": "profile-streaming" }, "profiles": [ { @@ -38,8 +26,6 @@ "name": "Streaming", "description": "OBS and Discord on the selected monitor.", "targetMonitorId": null, - "startupRestore": true, - "enforceAfterRestore": true, "apps": [ { "id": "preset-obs", @@ -56,7 +42,6 @@ "launchDelaySeconds": 0, "detectionTimeoutSeconds": 25, "retryIntervalMs": 700, - "launchIfMissing": true, "moveIfRunning": true, "forceResize": true, "applyToAllMatchingWindows": false, @@ -81,7 +66,6 @@ "launchDelaySeconds": 0, "detectionTimeoutSeconds": 25, "retryIntervalMs": 700, - "launchIfMissing": true, "moveIfRunning": true, "forceResize": true, "applyToAllMatchingWindows": false, @@ -106,7 +90,6 @@ "launchDelaySeconds": 0, "detectionTimeoutSeconds": 45, "retryIntervalMs": 700, - "launchIfMissing": true, "moveIfRunning": true, "forceResize": true, "applyToAllMatchingWindows": false, diff --git a/package-lock.json b/package-lock.json index fabdb77..9551a02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,14 @@ { "name": "windowautolayout", - "version": "0.1.18", + "version": "0.1.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windowautolayout", - "version": "0.1.18", + "version": "0.1.23", "dependencies": { "@tauri-apps/api": "^2", - "@tauri-apps/plugin-global-shortcut": "^2.3.2", - "@tauri-apps/plugin-opener": "^2", "clsx": "^2.1.1", "lucide-react": "^1.17.0", "react": "^19.1.0", @@ -310,17 +308,6 @@ "node": ">=6.9.0" } }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", @@ -821,9 +808,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", - "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", "cpu": [ "arm" ], @@ -835,9 +822,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", - "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", "cpu": [ "arm64" ], @@ -849,9 +836,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", - "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", "cpu": [ "arm64" ], @@ -863,9 +850,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", - "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", "cpu": [ "x64" ], @@ -877,9 +864,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", - "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", "cpu": [ "arm64" ], @@ -891,9 +878,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", - "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", "cpu": [ "x64" ], @@ -905,9 +892,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", - "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", "cpu": [ "arm" ], @@ -919,9 +906,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", - "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", "cpu": [ "arm" ], @@ -933,9 +920,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", - "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", "cpu": [ "arm64" ], @@ -947,9 +934,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", - "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", "cpu": [ "arm64" ], @@ -961,9 +948,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", - "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", "cpu": [ "loong64" ], @@ -975,9 +962,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", - "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", "cpu": [ "loong64" ], @@ -989,9 +976,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", - "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", "cpu": [ "ppc64" ], @@ -1003,9 +990,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", - "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", "cpu": [ "ppc64" ], @@ -1017,9 +1004,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", - "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", "cpu": [ "riscv64" ], @@ -1031,9 +1018,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", - "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", "cpu": [ "riscv64" ], @@ -1045,9 +1032,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", - "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", "cpu": [ "s390x" ], @@ -1059,9 +1046,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", - "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", "cpu": [ "x64" ], @@ -1073,9 +1060,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", - "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", "cpu": [ "x64" ], @@ -1087,9 +1074,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", - "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", "cpu": [ "x64" ], @@ -1101,9 +1088,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", - "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", "cpu": [ "arm64" ], @@ -1115,9 +1102,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", - "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", "cpu": [ "arm64" ], @@ -1129,9 +1116,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", - "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", "cpu": [ "ia32" ], @@ -1143,9 +1130,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", - "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", "cpu": [ "x64" ], @@ -1157,9 +1144,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", - "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", "cpu": [ "x64" ], @@ -1171,49 +1158,49 @@ ] }, "node_modules/@tailwindcss/node": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", - "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", + "integrity": "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.21.0", - "jiti": "^2.6.1", + "enhanced-resolve": "5.21.6", + "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.3.0" + "tailwindcss": "4.3.2" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", - "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.2.tgz", + "integrity": "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==", "dev": true, "license": "MIT", "engines": { "node": ">= 20" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-arm64": "4.3.0", - "@tailwindcss/oxide-darwin-x64": "4.3.0", - "@tailwindcss/oxide-freebsd-x64": "4.3.0", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", - "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", - "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", - "@tailwindcss/oxide-linux-x64-musl": "4.3.0", - "@tailwindcss/oxide-wasm32-wasi": "4.3.0", - "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", - "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" + "@tailwindcss/oxide-android-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-x64": "4.3.2", + "@tailwindcss/oxide-freebsd-x64": "4.3.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-x64-musl": "4.3.2", + "@tailwindcss/oxide-wasm32-wasi": "4.3.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", - "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz", + "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==", "cpu": [ "arm64" ], @@ -1228,9 +1215,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", - "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz", + "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==", "cpu": [ "arm64" ], @@ -1245,9 +1232,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", - "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz", + "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==", "cpu": [ "x64" ], @@ -1262,9 +1249,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", - "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz", + "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==", "cpu": [ "x64" ], @@ -1279,9 +1266,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", - "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz", + "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==", "cpu": [ "arm" ], @@ -1296,9 +1283,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", - "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz", + "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==", "cpu": [ "arm64" ], @@ -1313,9 +1300,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", - "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz", + "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==", "cpu": [ "arm64" ], @@ -1330,9 +1317,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", - "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz", + "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==", "cpu": [ "x64" ], @@ -1347,9 +1334,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", - "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz", + "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==", "cpu": [ "x64" ], @@ -1364,9 +1351,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", - "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz", + "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -1382,87 +1369,21 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.10.0", - "@emnapi/runtime": "^1.10.0", - "@emnapi/wasi-threads": "^1.2.1", + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", "@napi-rs/wasm-runtime": "^1.1.4", - "@tybys/wasm-util": "^0.10.1", + "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { - "version": "2.8.1", - "dev": true, - "inBundle": true, - "license": "0BSD", - "optional": true - }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", - "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", + "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==", "cpu": [ "arm64" ], @@ -1477,9 +1398,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", - "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.2.tgz", + "integrity": "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==", "cpu": [ "x64" ], @@ -1494,24 +1415,24 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz", - "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.2.tgz", + "integrity": "sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.3.0", - "@tailwindcss/oxide": "4.3.0", - "tailwindcss": "4.3.0" + "@tailwindcss/node": "4.3.2", + "@tailwindcss/oxide": "4.3.2", + "tailwindcss": "4.3.2" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "node_modules/@tauri-apps/api": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.0.tgz", - "integrity": "sha512-7CinYODhky9lmO23xHnUFv0Xt43fbtWMyxZcLcRBlFkcgXKuEirBvHpmtJ89YMhyeGcq20Wuc47Fa4XjyniywA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.11.1.tgz", + "integrity": "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==", "license": "Apache-2.0 OR MIT", "funding": { "type": "opencollective", @@ -1519,9 +1440,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.2.tgz", - "integrity": "sha512-bk3HemqvGRoy+5D/dVMUQHKMYLglD0jVnMm/0iGMH6ufZ+p8r14m6BpIixwij3PBvZdvORUp1YifTD8QxVZ1Nw==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-2.11.4.tgz", + "integrity": "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -1535,23 +1456,23 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "2.11.2", - "@tauri-apps/cli-darwin-x64": "2.11.2", - "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.2", - "@tauri-apps/cli-linux-arm64-gnu": "2.11.2", - "@tauri-apps/cli-linux-arm64-musl": "2.11.2", - "@tauri-apps/cli-linux-riscv64-gnu": "2.11.2", - "@tauri-apps/cli-linux-x64-gnu": "2.11.2", - "@tauri-apps/cli-linux-x64-musl": "2.11.2", - "@tauri-apps/cli-win32-arm64-msvc": "2.11.2", - "@tauri-apps/cli-win32-ia32-msvc": "2.11.2", - "@tauri-apps/cli-win32-x64-msvc": "2.11.2" + "@tauri-apps/cli-darwin-arm64": "2.11.4", + "@tauri-apps/cli-darwin-x64": "2.11.4", + "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", + "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", + "@tauri-apps/cli-linux-arm64-musl": "2.11.4", + "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", + "@tauri-apps/cli-linux-x64-gnu": "2.11.4", + "@tauri-apps/cli-linux-x64-musl": "2.11.4", + "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", + "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", + "@tauri-apps/cli-win32-x64-msvc": "2.11.4" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.2.tgz", - "integrity": "sha512-+4UZzLt+eOAEQCwgd+TqKgyUJMrvx+BgdXLLaqJYmPqzP+nE6YZr/hY6CWLYGQb8jFn99jEkmC6uA3tNvamA1w==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.11.4.tgz", + "integrity": "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ==", "cpu": [ "arm64" ], @@ -1566,9 +1487,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.2.tgz", - "integrity": "sha512-VjYYtZUPqDMLutSfJEyxFE3Bz+DPi7c8wC3imckgvciLDZLq4qwKJxBicg0BXGhXjJsl8vKWgWRFNMPELQ+Xyg==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.11.4.tgz", + "integrity": "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A==", "cpu": [ "x64" ], @@ -1583,9 +1504,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.2.tgz", - "integrity": "sha512-yMemD6f4i95AQriS8EazyOFzbE34yjnP16i3IOzpHGQvBoy2DjypFMFBq0NtPuITURv/cOGguRtHR5d79/9CSA==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.11.4.tgz", + "integrity": "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ==", "cpu": [ "arm" ], @@ -1600,9 +1521,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.2.tgz", - "integrity": "sha512-cgI91D2wL8GSgoWwZXDqt+DwnuZCP2/bz03QAE4TrhgAKIsrB4hX26W/H1EONPUUNkqrsgeCD0wU6pcNjV/5kw==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.11.4.tgz", + "integrity": "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA==", "cpu": [ "arm64" ], @@ -1617,9 +1538,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.2.tgz", - "integrity": "sha512-X1rm0BERqAAggtYTESSgXrS3sz4Sb/OiPiz54UqISlXW+GkR3vNIGnsy/lejNmoXGVqri3Q53BCfQiclOIyRPw==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.11.4.tgz", + "integrity": "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw==", "cpu": [ "arm64" ], @@ -1634,9 +1555,9 @@ } }, "node_modules/@tauri-apps/cli-linux-riscv64-gnu": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.2.tgz", - "integrity": "sha512-usbMLJbT3KtkOrBMDVeGYNM35aTHXx38SJSzTMSqqjeUIOQ+iVPjb2yAGNAE+KqmBbAx4FOFIyMeKXx2M/JKGQ==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-riscv64-gnu/-/cli-linux-riscv64-gnu-2.11.4.tgz", + "integrity": "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ==", "cpu": [ "riscv64" ], @@ -1651,9 +1572,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.2.tgz", - "integrity": "sha512-Ru4gwJKPG0ctVGchRGpRup4Y4lW2SSfFnrbQcyHhCliKy4g8Qz97TrUgCur4CbWyAgKxvGh3SjrkA0LDYzDGiw==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.11.4.tgz", + "integrity": "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ==", "cpu": [ "x64" ], @@ -1668,9 +1589,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.2.tgz", - "integrity": "sha512-eUm7T6clN1MMmNSRQ9gaWsQdyehQx2Gmn5hht/QUlqZQI/qcP2OJK5dnaxqwFzCr2HdsEo9ydxaqcS1oJzMvUw==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.11.4.tgz", + "integrity": "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A==", "cpu": [ "x64" ], @@ -1685,9 +1606,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.2.tgz", - "integrity": "sha512-HeeZW80jU+gVTOEX4X/hC6NVSAdDVXajwP5fxIZ/3z9WvUC7qrudX2GMTilYq6Dg0e0sk0XgsAJD1hZ5wPBXUA==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.11.4.tgz", + "integrity": "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ==", "cpu": [ "arm64" ], @@ -1702,9 +1623,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.2.tgz", - "integrity": "sha512-YhjQNZcXfbkCLyazSv1nPnJ9iRFE1wm6kc51FDbU10/Dk09io+6PAGMLjkxnX2GdM0qMnDmTjstY8mTDVvtKeA==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.11.4.tgz", + "integrity": "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA==", "cpu": [ "ia32" ], @@ -1719,9 +1640,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.2.tgz", - "integrity": "sha512-d2JchlFIpZevZVReyqhQOekJmb1UH3rhZ5VX6sH3ty9ETE0TKQavpihvoScUXfKKpW6HZC0MrFGRU0ZtD+w3gA==", + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.11.4.tgz", + "integrity": "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw==", "cpu": [ "x64" ], @@ -1735,24 +1656,6 @@ "node": ">= 10" } }, - "node_modules/@tauri-apps/plugin-global-shortcut": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-global-shortcut/-/plugin-global-shortcut-2.3.2.tgz", - "integrity": "sha512-UReHNXrLvpEjylE4jb4oCYiy96uRykPUthoCQCmRXYrd5hs5X9DrW+qOn7GLW57EJN4tdK8bgK5twBTz2NOxzA==", - "license": "MIT OR Apache-2.0", - "dependencies": { - "@tauri-apps/api": "^2.11.0" - } - }, - "node_modules/@tauri-apps/plugin-opener": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.4.tgz", - "integrity": "sha512-1HnPkb+AmgO29HBazm4uPLKB+r7zzcTBW1d0fyYp1uP+jwtpoiNDGKMMzz58SFp49nOIrxdE3aUJtT57lfO9CQ==", - "license": "MIT OR Apache-2.0", - "dependencies": { - "@tauri-apps/api": "^2.11.0" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1799,16 +1702,16 @@ } }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, "node_modules/@types/react": { - "version": "19.2.15", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", - "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "dev": true, "license": "MIT", "peer": true, @@ -1848,9 +1751,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.32", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", - "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", + "version": "2.10.42", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.42.tgz", + "integrity": "sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==", "dev": true, "license": "Apache-2.0", "bin": { @@ -1861,9 +1764,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.5.tgz", + "integrity": "sha512-Cu2E6QejHWzuDMTkuwgpABFgDfZrXLQq5V13YOACZx4mFAG4IwGTbTfHPMr4WtxlHoXSM8FIuRwYYCz5XiabaQ==", "dev": true, "funding": [ { @@ -1882,10 +1785,10 @@ "license": "MIT", "peer": true, "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001800", + "electron-to-chromium": "^1.5.387", + "node-releases": "^2.0.50", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -1896,9 +1799,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001793", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", - "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "version": "1.0.30001803", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001803.tgz", + "integrity": "sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg==", "dev": true, "funding": [ { @@ -1968,16 +1871,16 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.364", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz", - "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==", + "version": "1.5.389", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz", + "integrity": "sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==", "dev": true, "license": "ISC" }, "node_modules/enhanced-resolve": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", - "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2405,9 +2308,9 @@ } }, "node_modules/lucide-react": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.17.0.tgz", - "integrity": "sha512-9FA9evdox/JQL5PT57fdA1x/yg8T7knJ98+zjTL3UfKza6pflQUUh3XtaQIHKvnsJw1lmsEyHVlt5jchYxOQ5w==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.24.0.tgz", + "integrity": "sha512-YT6mBD8lGKkg4nM39enlm94/sfJIiW0YKUT60fBy4YK8tai31ylg1VhGNWxkpSKHo9UagfnZqwIff3HTDQwXeA==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -2431,9 +2334,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", "dev": true, "funding": [ { @@ -2450,9 +2353,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.46", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", - "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", "dev": true, "license": "MIT", "engines": { @@ -2467,9 +2370,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "peer": true, @@ -2481,9 +2384,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", + "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", "dev": true, "funding": [ { @@ -2510,9 +2413,9 @@ } }, "node_modules/react": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", - "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "peer": true, "engines": { @@ -2520,15 +2423,15 @@ } }, "node_modules/react-dom": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", - "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.6" + "react": "^19.2.7" } }, "node_modules/react-refresh": { @@ -2542,13 +2445,13 @@ } }, "node_modules/rollup": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", - "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -2558,31 +2461,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.4", - "@rollup/rollup-android-arm64": "4.60.4", - "@rollup/rollup-darwin-arm64": "4.60.4", - "@rollup/rollup-darwin-x64": "4.60.4", - "@rollup/rollup-freebsd-arm64": "4.60.4", - "@rollup/rollup-freebsd-x64": "4.60.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", - "@rollup/rollup-linux-arm-musleabihf": "4.60.4", - "@rollup/rollup-linux-arm64-gnu": "4.60.4", - "@rollup/rollup-linux-arm64-musl": "4.60.4", - "@rollup/rollup-linux-loong64-gnu": "4.60.4", - "@rollup/rollup-linux-loong64-musl": "4.60.4", - "@rollup/rollup-linux-ppc64-gnu": "4.60.4", - "@rollup/rollup-linux-ppc64-musl": "4.60.4", - "@rollup/rollup-linux-riscv64-gnu": "4.60.4", - "@rollup/rollup-linux-riscv64-musl": "4.60.4", - "@rollup/rollup-linux-s390x-gnu": "4.60.4", - "@rollup/rollup-linux-x64-gnu": "4.60.4", - "@rollup/rollup-linux-x64-musl": "4.60.4", - "@rollup/rollup-openbsd-x64": "4.60.4", - "@rollup/rollup-openharmony-arm64": "4.60.4", - "@rollup/rollup-win32-arm64-msvc": "4.60.4", - "@rollup/rollup-win32-ia32-msvc": "4.60.4", - "@rollup/rollup-win32-x64-gnu": "4.60.4", - "@rollup/rollup-win32-x64-msvc": "4.60.4", + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" } }, @@ -2613,9 +2516,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", - "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.2.tgz", + "integrity": "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==", "dev": true, "license": "MIT" }, @@ -2634,9 +2537,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -2650,14 +2553,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", diff --git a/package.json b/package.json index 6d20e69..b172882 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "windowautolayout", "private": true, - "version": "0.1.18", + "version": "0.1.23", "type": "module", "scripts": { "dev": "vite", @@ -15,8 +15,6 @@ }, "dependencies": { "@tauri-apps/api": "^2", - "@tauri-apps/plugin-global-shortcut": "^2.3.2", - "@tauri-apps/plugin-opener": "^2", "clsx": "^2.1.1", "lucide-react": "^1.17.0", "react": "^19.1.0", diff --git a/scripts/install-current.ps1 b/scripts/install-current.ps1 index 4acb9fa..c2acba8 100644 --- a/scripts/install-current.ps1 +++ b/scripts/install-current.ps1 @@ -101,16 +101,11 @@ try { $stayedAlive = $null if (-not $NoLaunchSmoke) { - $app = Start-Process -FilePath $exe -PassThru -WindowStyle Hidden + Get-Process -Name "WindowAutoLayout", "windowautolayout" -ErrorAction SilentlyContinue | + Stop-Process -Force -ErrorAction SilentlyContinue + $app = Start-Process -FilePath $exe -ArgumentList "--startup-restore" -PassThru -WindowStyle Hidden Start-Sleep -Seconds 5 $stayedAlive = -not $app.HasExited - if ($stayedAlive) { - $app.CloseMainWindow() | Out-Null - Start-Sleep -Seconds 2 - if (-not $app.HasExited) { - Stop-Process -Id $app.Id -Force - } - } if (-not $stayedAlive) { throw "Installed app exited during launch smoke" } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 553ae2b..809d6a4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -25,9 +25,9 @@ checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" dependencies = [ "alloc-no-stdlib", ] @@ -43,140 +43,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "pin-project-lite", - "slab", -] - -[[package]] -name = "async-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" -dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-lock" -version = "3.4.2" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "async-signal" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix", - "signal-hook-registry", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "atk" @@ -248,9 +117,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -273,24 +142,11 @@ dependencies = [ "objc2", ] -[[package]] -name = "blocking" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - [[package]] name = "brotli" -version = "8.0.3" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" +checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -299,9 +155,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.1" +version = "5.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" +checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -324,9 +180,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" -version = "1.25.0" +version = "1.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" [[package]] name = "byteorder" @@ -336,9 +192,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" dependencies = [ "serde", ] @@ -349,7 +205,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cairo-sys-rs", "glib", "libc", @@ -370,9 +226,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.2.2" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" dependencies = [ "serde_core", ] @@ -412,9 +268,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.63" +version = "1.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" dependencies = [ "find-msvc-tools", "shlex", @@ -455,9 +311,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "js-sys", @@ -477,15 +333,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "cookie" version = "0.18.1" @@ -518,7 +365,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "core-graphics-types", "foreign-types", @@ -531,7 +378,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "libc", ] @@ -556,18 +403,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crypto-common" @@ -599,7 +446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -638,7 +485,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -649,14 +496,14 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "dbus" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" +checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e" dependencies = [ "libc", "libdbus-sys", @@ -669,7 +516,6 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -691,7 +537,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -731,7 +577,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -745,7 +591,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -768,7 +614,7 @@ checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -779,7 +625,7 @@ checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ "bit-set", "cssparser", - "foldhash 0.2.0", + "foldhash", "html5ever", "precomputed-hash", "selectors", @@ -839,9 +685,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "embed-resource" -version = "3.0.9" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a88c8d26de40ed18fe748c547845aa39de1db3afd958f8cb91579f3644bcb" +checksum = "fbfdaacccebec3b28e4866b8973543c7647797db5ada1bdab552e48fe665fbbd" dependencies = [ "cc", "memchr", @@ -857,33 +703,6 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" -[[package]] -name = "endi" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" - -[[package]] -name = "enumflags2" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -901,37 +720,6 @@ dependencies = [ "typeid", ] -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] - [[package]] name = "fastrand" version = "2.4.1" @@ -979,12 +767,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -1009,7 +791,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1059,19 +841,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - [[package]] name = "futures-macro" version = "0.3.32" @@ -1080,7 +849,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1220,16 +989,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "gethostname" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" -dependencies = [ - "rustix", - "windows-link 0.2.1", -] - [[package]] name = "getrandom" version = "0.2.17" @@ -1255,15 +1014,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "wasip2", - "wasip3", ] [[package]] @@ -1304,7 +1061,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "futures-channel", "futures-core", "futures-executor", @@ -1332,7 +1089,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1351,24 +1108,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" -[[package]] -name = "global-hotkey" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c386b0a4a70cb2d39fffd74480f985b6f0bfbcb934b6a6b6b7e630e448f242e" -dependencies = [ - "crossbeam-channel", - "keyboard-types", - "objc2", - "objc2-app-kit", - "once_cell", - "serde", - "thiserror 2.0.18", - "windows-sys 0.59.0", - "x11rb", - "xkeysym", -] - [[package]] name = "gobject-sys" version = "0.18.0" @@ -1429,7 +1168,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1438,15 +1177,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - [[package]] name = "hashbrown" version = "0.17.1" @@ -1465,12 +1195,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - [[package]] name = "hex" version = "0.4.3" @@ -1489,9 +1213,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -1685,12 +1409,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -1756,25 +1474,6 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" -[[package]] -name = "is-docker" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" -dependencies = [ - "once_cell", -] - -[[package]] -name = "is-wsl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" -dependencies = [ - "is-docker", - "once_cell", -] - [[package]] name = "itoa" version = "1.0.18" @@ -1845,18 +1544,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "js-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -1888,17 +1586,11 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "serde", "unicode-segmentation", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libappindicator" version = "0.9.0" @@ -1950,19 +1642,13 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - [[package]] name = "litemap" version = "0.8.2" @@ -1980,9 +1666,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.30" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "markup5ever" @@ -1997,9 +1683,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.1" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memoffset" @@ -2039,9 +1725,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" dependencies = [ "crossbeam-channel", "dpi", @@ -2064,7 +1750,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys", @@ -2122,7 +1808,7 @@ dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2141,7 +1827,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -2154,7 +1840,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-foundation", ] @@ -2175,7 +1861,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", ] @@ -2186,7 +1872,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", "objc2-core-foundation", @@ -2219,7 +1905,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -2246,7 +1932,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -2258,7 +1944,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -2269,7 +1955,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -2281,7 +1967,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-cloud-kit", @@ -2312,7 +1998,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-app-kit", @@ -2326,34 +2012,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "open" -version = "5.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" -dependencies = [ - "dunce", - "is-wsl", - "libc", - "pathdiff", -] - [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "pango" version = "0.18.3" @@ -2379,12 +2043,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - [[package]] name = "parking_lot" version = "0.12.5" @@ -2408,12 +2066,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "pathdiff" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" - [[package]] name = "percent-encoding" version = "2.3.2" @@ -2461,7 +2113,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2479,17 +2131,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "piper" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkg-config" version = "0.3.33" @@ -2498,9 +2139,9 @@ checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ "base64 0.22.1", "indexmap 2.14.0", @@ -2528,27 +2169,13 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] -[[package]] -name = "polling" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix", - "windows-sys 0.61.2", -] - [[package]] name = "potential_utf" version = "0.1.5" @@ -2570,16 +2197,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -2644,18 +2261,18 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.39.4" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -2684,7 +2301,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -2715,14 +2332,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", @@ -2732,9 +2349,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -2743,9 +2360,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" @@ -2783,9 +2400,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -2796,24 +2413,11 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "same-file" @@ -2872,7 +2476,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2887,7 +2491,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cssparser", "derive_more", "log", @@ -2949,7 +2553,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2960,7 +2564,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2984,7 +2588,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3007,9 +2611,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ "base64 0.22.1", "bs58", @@ -3027,14 +2631,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3056,7 +2660,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3085,16 +2689,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - [[package]] name = "simd-adler32" version = "0.3.9" @@ -3115,9 +2709,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" @@ -3236,9 +2830,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -3262,7 +2856,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3284,7 +2878,7 @@ version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "core-foundation", "core-graphics", @@ -3326,7 +2920,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3337,9 +2931,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.11.2" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437404997acf375d85f1177afa7e11bb971f274ed6a7b83a2a3e339015f4cc28" +checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5" dependencies = [ "anyhow", "bytes", @@ -3388,9 +2982,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa1f9055fc23919a54e4e125052bed16ed04aef0487086e758fe01a67b451c7" +checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" dependencies = [ "anyhow", "cargo_toml", @@ -3409,9 +3003,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a0319528a025a38c4078e7dae2c446f4e63620ddb0659a643ede1cb38f90e9" +checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" dependencies = [ "base64 0.22.1", "brotli", @@ -3425,7 +3019,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.117", + "syn 2.0.118", "tauri-utils", "thiserror 2.0.18", "time", @@ -3436,76 +3030,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6cb4e3896c21d2f6da5b31251d2faea0153bba56ed0e970f918115dbee4924" +checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "tauri-codegen", "tauri-utils", ] -[[package]] -name = "tauri-plugin" -version = "2.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e126abc9e84e35cdfd01596140a73a1850cdb0df0a23acf0185776c30b469a6e" -dependencies = [ - "anyhow", - "glob", - "plist", - "schemars 0.8.22", - "serde", - "serde_json", - "tauri-utils", - "walkdir", -] - -[[package]] -name = "tauri-plugin-global-shortcut" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4dd9f4c5136c09cd962da0c86dc4accd4666db2ea591cf16e6597435843bd2b" -dependencies = [ - "global-hotkey", - "log", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror 2.0.18", -] - -[[package]] -name = "tauri-plugin-opener" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17e1bea14edce6b793a04e2417e3fd924b9bc4faae83cdee7d714156cceeed29" -dependencies = [ - "dunce", - "glob", - "objc2-app-kit", - "objc2-foundation", - "open", - "schemars 0.8.22", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror 2.0.18", - "url", - "windows 0.61.3", - "zbus", -] - [[package]] name = "tauri-runtime" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48222d7116c8807eaa6fe2f372e023fae125084e61e6eca6d70b7961cdf129ef" +checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" dependencies = [ "cookie", "dpi", @@ -3528,9 +3069,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.11.2" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83849ee63ecb27a8e8d0fe51915ca215076914aca43f96db1179f0f415f6cd9" +checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" dependencies = [ "gtk", "http", @@ -3554,9 +3095,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092379df9a707631978e6c56b1bc2401d387f01e2d4a3c123360d167bbb9aa95" +checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" dependencies = [ "anyhow", "brotli", @@ -3601,27 +3142,13 @@ dependencies = [ "toml 1.1.2+spec-1.1.0", ] -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - [[package]] name = "tendril" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4790fc369d5a530f4b544b094e31388b9b3a37c0f4652ade4505945f5660d24" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" dependencies = [ "new_debug_unreachable", - "utf-8", ] [[package]] @@ -3650,7 +3177,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3661,17 +3188,16 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde_core", @@ -3681,15 +3207,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -3707,9 +3233,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -3888,7 +3414,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "bytes", "futures-util", "http", @@ -3919,21 +3445,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "tracing-core" version = "0.1.36" @@ -3945,9 +3459,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.23.1" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15edbb0d80583e85ee8df283410038e17314df5cba30da2087a54a85216c0773" +checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc" dependencies = [ "crossbeam-channel", "dirs", @@ -3983,17 +3497,6 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" -[[package]] -name = "uds_windows" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" -dependencies = [ - "memoffset", - "tempfile", - "windows-sys 0.61.2", -] - [[package]] name = "unic-char-property" version = "0.9.0" @@ -4043,15 +3546,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "url" @@ -4078,12 +3575,6 @@ dependencies = [ "url", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -4092,11 +3583,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.23.2" +version = "1.23.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" +checksum = "ea5fab0d6c3c01ae70085a09cb03d4c7a1d6314e2b3e075392783396d724ca0a" dependencies = [ - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "serde_core", "wasm-bindgen", @@ -4161,27 +3652,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -4192,9 +3674,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.72" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -4202,9 +3684,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4212,48 +3694,26 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.122" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.14.0", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.5.0" @@ -4267,23 +3727,11 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.15.5", - "indexmap 2.14.0", - "semver", -] - [[package]] name = "web-sys" -version = "0.3.99" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -4291,9 +3739,9 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +checksum = "075474b12bcb3d2e3d4546580e9de478eeeead668a1761e2a8860c836b7ef297" dependencies = [ "phf", "phf_codegen", @@ -4367,7 +3815,7 @@ checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4429,7 +3877,7 @@ dependencies = [ [[package]] name = "windowautolayout" -version = "0.1.18" +version = "0.1.23" dependencies = [ "chrono", "regex", @@ -4437,8 +3885,6 @@ dependencies = [ "serde_json", "tauri", "tauri-build", - "tauri-plugin-global-shortcut", - "tauri-plugin-opener", "thiserror 2.0.18", "uuid", "windows 0.62.2", @@ -4544,7 +3990,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4555,7 +4001,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4845,100 +4291,12 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck 0.5.0", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck 0.5.0", - "indexmap 2.14.0", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.1", - "indexmap 2.14.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.14.0", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -5010,34 +4368,11 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" -dependencies = [ - "gethostname", - "rustix", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" - -[[package]] -name = "xkeysym" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" - [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -5052,71 +4387,10 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] -[[package]] -name = "zbus" -version = "5.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee682d202a77e4a9f3b2c2bdf48a7b28af5c08c34ddf66f98c93e5e39464285" -dependencies = [ - "async-broadcast", - "async-executor", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener", - "futures-core", - "futures-lite", - "hex", - "libc", - "ordered-stream", - "rustix", - "serde", - "serde_repr", - "tracing", - "uds_windows", - "uuid", - "windows-sys 0.61.2", - "winnow 1.0.3", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "5.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6" -dependencies = [ - "proc-macro-crate 3.5.0", - "proc-macro2", - "quote", - "syn 2.0.117", - "zbus_names", - "zvariant", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" -dependencies = [ - "serde", - "winnow 1.0.3", - "zvariant", -] - [[package]] name = "zerofrom" version = "0.1.8" @@ -5134,7 +4408,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] @@ -5168,51 +4442,11 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zvariant" -version = "5.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a192a0bde63360d77a7523c833d4b4ce6070a927e2c53246e4c540b1a3e27be0" -dependencies = [ - "endi", - "enumflags2", - "serde", - "winnow 1.0.3", - "zvariant_derive", - "zvariant_utils", -] - -[[package]] -name = "zvariant_derive" -version = "5.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737" -dependencies = [ - "proc-macro-crate 3.5.0", - "proc-macro2", - "quote", - "syn 2.0.117", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "3.4.0" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e8535915cfa75547e559d8c68e8139909a4aeee076831e4ef7fc59d8172c4d6" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn 2.0.117", - "winnow 1.0.3", -] +checksum = "bd2f034a4bebf216c9e4b7083603e024cf930873fd67830cfb083c9fa33129d9" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1fc0119..f23cb8a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "windowautolayout" -version = "0.1.18" +version = "0.1.23" description = "Windows workspace layout restore utility" authors = ["Rique"] edition = "2021" @@ -23,17 +23,18 @@ regex = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" tauri = { version = "2", features = ["tray-icon"] } -tauri-plugin-global-shortcut = "2.3.2" -tauri-plugin-opener = "2" thiserror = "2" uuid = { version = "1", features = ["v4", "serde"] } windows = { version = "0.62.2", features = [ "Win32_Foundation", "Win32_Graphics_Dwm", "Win32_Graphics_Gdi", + "Win32_Security", "Win32_System_Diagnostics_ToolHelp", "Win32_System_Threading", + "Win32_UI_Accessibility", "Win32_UI_HiDpi", + "Win32_UI_Input", "Win32_UI_WindowsAndMessaging" ] } winreg = "0.56" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index c54480b..b9ec4c1 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -4,11 +4,6 @@ "description": "Capability for the main window", "windows": ["main"], "permissions": [ - "core:default", - "global-shortcut:allow-is-registered", - "global-shortcut:allow-register", - "global-shortcut:allow-unregister", - "global-shortcut:allow-unregister-all", - "opener:default" + "core:default" ] } diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index d5d5f94..2a8d813 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, path::PathBuf, process::Command}; -use tauri::{AppHandle, Manager, State}; +use tauri::{AppHandle, State}; use crate::{ config, @@ -25,22 +25,28 @@ pub fn get_config(state: State<'_, AppState>) -> AppResult AppResult { + config::parse_json(&raw) +} + #[tauri::command] pub fn save_config( app: AppHandle, state: State<'_, AppState>, mut next_config: WindowAutoLayoutConfig, ) -> AppResult { - next_config.schema_version = crate::models::CONFIG_SCHEMA_VERSION; - next_config.app_version = crate::models::APP_VERSION.to_string(); - next_config.startup.launch_missing_apps = true; - for profile in &mut next_config.profiles { - for app in &mut profile.apps { - app.launch_if_missing = true; - } - } - startup::set_startup_enabled(next_config.startup.enabled)?; + config::normalize_config(&mut next_config); + let previous_config = state + .config + .lock() + .map_err(|_| AppError::Config("Config lock was poisoned".to_string()))? + .clone(); config::save(&state.config_dir, &next_config)?; + if let Err(error) = startup::set_startup_enabled(next_config.startup.enabled) { + let _ = config::save(&state.config_dir, &previous_config); + return Err(error); + } *state .config .lock() @@ -102,33 +108,6 @@ pub async fn restore_profile( .map_err(|error| AppError::Config(format!("Restore task failed: {error}")))? } -#[tauri::command] -pub async fn lock_layout_temporarily( - state: State<'_, AppState>, - profile_id: Option, - duration_seconds: u64, -) -> AppResult { - let config_dir = state.config_dir.clone(); - let config = state - .config - .lock() - .map_err(|_| AppError::Config("Config lock was poisoned".to_string()))? - .clone(); - let interval_ms = config.enforcement.interval_ms; - - tauri::async_runtime::spawn_blocking(move || { - profiles::enforce_profile_for( - &config_dir, - &config, - profile_id, - duration_seconds, - interval_ms, - ) - }) - .await - .map_err(|error| AppError::Config(format!("Lock task failed: {error}")))? -} - #[tauri::command] pub fn set_layout_lock( app: AppHandle, @@ -408,11 +387,14 @@ fn captured_apps_for_windows(monitor: &MonitorInfo, windows: &[WindowInfo]) -> V bottom: window.y + window.height, }, ), - window_state: WindowStatePreference::Normal, + window_state: if window.is_maximized { + WindowStatePreference::Maximized + } else { + WindowStatePreference::Normal + }, launch_delay_seconds: 0, detection_timeout_seconds: 25, retry_interval_ms: 700, - launch_if_missing: true, move_if_running: true, force_resize: true, apply_to_all_matching_windows: false, @@ -439,20 +421,19 @@ fn window_matches_capture_monitor(window: &WindowInfo, monitor: &MonitorInfo) -> .monitor_id .as_ref() .map(|id| id == &monitor.id) - .unwrap_or(false) - || window_intersects_monitor(window, monitor) + .unwrap_or_else(|| window_center_is_on_monitor(window, monitor)) } -fn window_intersects_monitor(window: &WindowInfo, monitor: &MonitorInfo) -> bool { - let window_right = window.x + window.width; - let window_bottom = window.y + window.height; +fn window_center_is_on_monitor(window: &WindowInfo, monitor: &MonitorInfo) -> bool { + let center_x = window.x + window.width / 2; + let center_y = window.y + window.height / 2; let monitor_right = monitor.x + monitor.width; let monitor_bottom = monitor.y + monitor.height; - window.x < monitor_right - && window_right > monitor.x - && window.y < monitor_bottom - && window_bottom > monitor.y + center_x >= monitor.x + && center_x < monitor_right + && center_y >= monitor.y + && center_y < monitor_bottom } fn is_self_window(window: &WindowInfo) -> bool { @@ -613,17 +594,7 @@ pub fn open_log_file(state: State<'_, AppState>) -> AppResult<()> { #[tauri::command] pub fn show_main_window(app: AppHandle) -> AppResult<()> { - if let Some(window) = app.get_webview_window("main") { - window - .show() - .map_err(|error| AppError::Config(error.to_string()))?; - window - .unminimize() - .map_err(|error| AppError::Config(error.to_string()))?; - window - .set_focus() - .map_err(|error| AppError::Config(error.to_string()))?; - } + crate::show_main_window(&app); Ok(()) } @@ -680,6 +651,7 @@ mod tests { height, is_visible: true, is_minimized: false, + is_maximized: false, } } @@ -707,6 +679,26 @@ mod tests { assert!(!capture_window_candidate(&other_monitor, &target)); } + #[test] + fn capture_uses_monitor_id_before_overlap() { + let target = monitor("display-2", -1920, 0, 1920, 1080); + let barely_overlapping = window("Chat.exe", "Chat", "display-1", -10, 100, 600, 500); + + assert!(!capture_window_candidate(&barely_overlapping, &target)); + } + + #[test] + fn capture_uses_window_center_when_monitor_id_is_missing() { + let target = monitor("display-2", -1920, 0, 1920, 1080); + let mut centered = window("Chat.exe", "Chat", "display-unknown", -1000, 100, 600, 500); + centered.monitor_id = None; + assert!(capture_window_candidate(¢ered, &target)); + + let mut off_target = window("Chat.exe", "Chat", "display-unknown", 100, 100, 600, 500); + off_target.monitor_id = None; + assert!(!capture_window_candidate(&off_target, &target)); + } + #[test] fn captured_apps_use_target_monitor_layout_and_duplicate_title_rules() { let target = monitor("display-2", -1920, 160, 1920, 1080); @@ -742,4 +734,15 @@ mod tests { assert_eq!(obs_rule.value, "OBS"); assert_eq!(apps[2].display_name, "OBS Studio"); } + + #[test] + fn capture_preserves_maximized_window_state() { + let target = monitor("display-1", 0, 0, 1920, 1080); + let mut maximized = window("Editor.exe", "Editor", "display-1", 0, 0, 1920, 1080); + maximized.is_maximized = true; + + let apps = captured_apps_for_windows(&target, &[maximized]); + + assert_eq!(apps[0].window_state, WindowStatePreference::Maximized); + } } diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index 1a6520d..a2e3677 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -1,9 +1,12 @@ use std::{ + collections::HashSet, fs, path::{Path, PathBuf}, }; use chrono::Utc; +use regex::RegexBuilder; +use uuid::Uuid; use crate::{ errors::{AppError, AppResult}, @@ -11,6 +14,10 @@ use crate::{ }; pub const CONFIG_FILE_NAME: &str = "config.json"; +const MAX_STARTUP_DELAY_SECONDS: u64 = 300; +const MAX_LAUNCH_DELAY_SECONDS: u64 = 120; +const MAX_LAYOUT_DIMENSION: i32 = 32_768; +const MAX_LAYOUT_OFFSET: i32 = 131_072; pub fn config_file_path(config_dir: &Path) -> PathBuf { config_dir.join(CONFIG_FILE_NAME) @@ -28,7 +35,8 @@ pub fn load_or_create(config_dir: &Path) -> AppResult { } let raw = fs::read_to_string(&path)?; - match serde_json::from_str::(&raw) { + let raw = raw.trim_start_matches('\u{feff}'); + match serde_json::from_str::(raw) { Ok(mut config) => { let mut should_save = false; if config.schema_version != CONFIG_SCHEMA_VERSION { @@ -73,43 +81,145 @@ pub fn save(config_dir: &Path, config: &WindowAutoLayoutConfig) -> AppResult<()> Ok(()) } -fn normalize_config(config: &mut WindowAutoLayoutConfig) -> bool { +pub fn parse_json(raw: &str) -> AppResult { + let mut config = + serde_json::from_str::(raw.trim_start_matches('\u{feff}'))?; + normalize_config(&mut config); + Ok(config) +} + +pub fn normalize_config(config: &mut WindowAutoLayoutConfig) -> bool { let mut changed = false; + if config.schema_version != CONFIG_SCHEMA_VERSION { + config.schema_version = CONFIG_SCHEMA_VERSION; + changed = true; + } + if config.app_version != APP_VERSION { + config.app_version = APP_VERSION.to_string(); + changed = true; + } + if !config.startup.launch_missing_apps { config.startup.launch_missing_apps = true; changed = true; } - for profile in &mut config.profiles { - for app in &mut profile.apps { - if !app.launch_if_missing { - app.launch_if_missing = true; + let startup_delay = config.startup.delay_seconds.min(MAX_STARTUP_DELAY_SECONDS); + if config.startup.delay_seconds != startup_delay { + config.startup.delay_seconds = startup_delay; + changed = true; + } + + if config.profiles.is_empty() { + config.profiles = WindowAutoLayoutConfig::default().profiles; + changed = true; + } + + let mut profile_ids = HashSet::new(); + for (profile_index, profile) in config.profiles.iter_mut().enumerate() { + if profile.id.trim().is_empty() || !profile_ids.insert(profile.id.clone()) { + profile.id = unique_id("profile", &mut profile_ids); + changed = true; + } + if profile.name.trim().is_empty() { + profile.name = format!("Profile {}", profile_index + 1); + changed = true; + } + + let mut app_ids = HashSet::new(); + for (app_index, app) in profile.apps.iter_mut().enumerate() { + if app.id.trim().is_empty() || !app_ids.insert(app.id.clone()) { + app.id = unique_id("app", &mut app_ids); + changed = true; + } + if app.display_name.trim().is_empty() { + app.display_name = app + .process_name + .as_deref() + .map(str::trim) + .filter(|name| !name.is_empty()) + .map(|name| name.trim_end_matches(".exe").to_string()) + .filter(|name| !name.is_empty()) + .unwrap_or_else(|| format!("App {}", app_index + 1)); + changed = true; + } + + let launch_delay_seconds = app.launch_delay_seconds.min(MAX_LAUNCH_DELAY_SECONDS); + if app.launch_delay_seconds != launch_delay_seconds { + app.launch_delay_seconds = launch_delay_seconds; + changed = true; + } + + let retry_interval_ms = app.retry_interval_ms.clamp(250, 5000); + if app.retry_interval_ms != retry_interval_ms { + app.retry_interval_ms = retry_interval_ms; + changed = true; + } + + let detection_timeout_seconds = app.detection_timeout_seconds.clamp(1, 120); + if app.detection_timeout_seconds != detection_timeout_seconds { + app.detection_timeout_seconds = detection_timeout_seconds; + changed = true; + } + + let x = app.layout.x.clamp(-MAX_LAYOUT_OFFSET, MAX_LAYOUT_OFFSET); + let y = app.layout.y.clamp(-MAX_LAYOUT_OFFSET, MAX_LAYOUT_OFFSET); + let width = app.layout.width.clamp(80, MAX_LAYOUT_DIMENSION); + let height = app.layout.height.clamp(80, MAX_LAYOUT_DIMENSION); + if ( + app.layout.x, + app.layout.y, + app.layout.width, + app.layout.height, + ) != (x, y, width, height) + { + app.layout.x = x; + app.layout.y = y; + app.layout.width = width; + app.layout.height = height; changed = true; } } } - if let Some(profile_id) = &config.enforcement.profile_id { - if !config - .profiles - .iter() - .any(|profile| &profile.id == profile_id) - { - config.enforcement.profile_id = None; - changed = true; - } + let first_profile_id = config.profiles[0].id.clone(); + if !config + .startup + .default_profile_id + .as_ref() + .is_some_and(|id| config.profiles.iter().any(|profile| &profile.id == id)) + { + config.startup.default_profile_id = Some(first_profile_id.clone()); + changed = true; } - let interval_ms = config.enforcement.interval_ms.clamp(2000, 5000); - if config.enforcement.interval_ms != interval_ms { - config.enforcement.interval_ms = interval_ms; + if !config + .enforcement + .profile_id + .as_ref() + .is_some_and(|id| config.profiles.iter().any(|profile| &profile.id == id)) + { + config.enforcement.profile_id = config + .startup + .default_profile_id + .clone() + .or(Some(first_profile_id)); changed = true; } changed } +fn unique_id(prefix: &str, seen: &mut HashSet) -> String { + loop { + let candidate = format!("{prefix}-{}", Uuid::new_v4()); + if seen.insert(candidate.clone()) { + return candidate; + } + } +} + fn migrate_config(config: &mut WindowAutoLayoutConfig) { if config.schema_version < 3 && matches!( @@ -130,12 +240,26 @@ pub fn backup_config(path: &Path, reason: &str) -> AppResult { pub fn validate_config(config: &WindowAutoLayoutConfig) -> Vec { let mut issues = Vec::new(); + let mut profile_ids = HashSet::new(); + if config.profiles.is_empty() { + issues.push("At least one profile is required".to_string()); + } for profile in &config.profiles { + if profile.id.trim().is_empty() || !profile_ids.insert(profile.id.as_str()) { + issues.push("Profile IDs must be present and unique".to_string()); + } if profile.name.trim().is_empty() { issues.push(format!("Profile {} has an empty name", profile.id)); } + let mut app_ids = HashSet::new(); for app in &profile.apps { + if app.id.trim().is_empty() || !app_ids.insert(app.id.as_str()) { + issues.push(format!( + "{} contains duplicate or empty app IDs", + profile.name + )); + } if app.display_name.trim().is_empty() { issues.push(format!( "Profile {} contains an app with an empty display name", @@ -148,12 +272,40 @@ pub fn validate_config(config: &WindowAutoLayoutConfig) -> Vec { app.display_name, app.layout.width, app.layout.height )); } - if app.retry_interval_ms < 100 { + if app.retry_interval_ms < 250 { + issues.push(format!( + "{} has a retry interval below 250 ms", + app.display_name + )); + } + if app + .process_name + .as_deref() + .map(str::trim) + .filter(|value| !value.is_empty()) + .is_none() + && app + .executable_path + .as_deref() + .map(str::trim) + .filter(|value| !value.is_empty()) + .is_none() + { issues.push(format!( - "{} has a retry interval below 100 ms", + "{} needs a process name or executable path", app.display_name )); } + if let Some(rule) = &app.title_rule { + if matches!(rule.mode, crate::models::TitleMatchMode::Regex) + && RegexBuilder::new(&rule.value) + .case_insensitive(!rule.case_sensitive) + .build() + .is_err() + { + issues.push(format!("{} has an invalid title regex", app.display_name)); + } + } } } issues @@ -174,8 +326,6 @@ mod tests { parsed.global.monitor_missing_behavior, MonitorMissingBehavior::NearestMatch ); - assert_eq!(parsed.enforcement.interval_ms, 2000); - assert!(parsed.enforcement.pause_for_fullscreen_games); } #[test] @@ -203,11 +353,81 @@ mod tests { } #[test] - fn normalizes_lock_interval_for_low_impact_polling() { + fn normalizes_active_restore_retry_limits() { let mut config = WindowAutoLayoutConfig::default(); - config.enforcement.interval_ms = 150; + config.profiles[0].apps[0].retry_interval_ms = 10; + config.profiles[0].apps[0].detection_timeout_seconds = 900; assert!(normalize_config(&mut config)); - assert_eq!(config.enforcement.interval_ms, 2000); + assert_eq!(config.profiles[0].apps[0].retry_interval_ms, 250); + assert_eq!(config.profiles[0].apps[0].detection_timeout_seconds, 120); + } + + #[test] + fn legacy_ask_next_open_value_migrates_to_do_nothing() { + let json = serde_json::to_string(&WindowAutoLayoutConfig::default()) + .expect("serialize") + .replace("nearestMatch", "askNextOpen"); + + let parsed = parse_json(&json).expect("parse legacy config"); + + assert_eq!( + parsed.global.monitor_missing_behavior, + MonitorMissingBehavior::DoNothing + ); + } + + #[test] + fn normalization_repairs_ids_delays_and_unsafe_layout_bounds() { + let mut config = WindowAutoLayoutConfig::default(); + let duplicate = config.profiles[0].apps[0].clone(); + config.profiles[0].apps.push(duplicate); + config.profiles[0].id.clear(); + config.profiles[0].name.clear(); + config.profiles[0].apps[0].id.clear(); + config.profiles[0].apps[0].launch_delay_seconds = u64::MAX; + config.profiles[0].apps[0].layout.width = i32::MAX; + config.startup.default_profile_id = Some("missing".into()); + config.enforcement.profile_id = Some("missing".into()); + + assert!(normalize_config(&mut config)); + + let profile = &config.profiles[0]; + assert!(!profile.id.is_empty()); + assert_eq!(profile.name, "Profile 1"); + assert_ne!(profile.apps[0].id, profile.apps[1].id); + assert_eq!( + profile.apps[0].launch_delay_seconds, + MAX_LAUNCH_DELAY_SECONDS + ); + assert_eq!(profile.apps[0].layout.width, MAX_LAYOUT_DIMENSION); + assert_eq!( + config.startup.default_profile_id.as_deref(), + Some(profile.id.as_str()) + ); + assert_eq!( + config.enforcement.profile_id.as_deref(), + Some(profile.id.as_str()) + ); + } + + #[test] + fn validation_reports_invalid_regex_and_missing_process_identity() { + let mut config = WindowAutoLayoutConfig::default(); + let app = &mut config.profiles[0].apps[0]; + app.process_name = None; + app.executable_path = None; + app.title_rule = Some(crate::models::MatchRule { + mode: crate::models::TitleMatchMode::Regex, + value: "[".into(), + case_sensitive: false, + }); + + let issues = validate_config(&config); + + assert!(issues.iter().any(|issue| issue.contains("process name"))); + assert!(issues + .iter() + .any(|issue| issue.contains("invalid title regex"))); } } diff --git a/src-tauri/src/desktop_guard.rs b/src-tauri/src/desktop_guard.rs new file mode 100644 index 0000000..c3bc8c0 --- /dev/null +++ b/src-tauri/src/desktop_guard.rs @@ -0,0 +1,371 @@ +use std::{ + sync::{Arc, Condvar, Mutex, OnceLock}, + thread, + time::{Duration, Instant}, +}; + +use tauri::{AppHandle, Manager}; +use windows::Win32::{ + Foundation::HWND, + UI::{ + Accessibility::{SetWinEventHook, HWINEVENTHOOK}, + WindowsAndMessaging::{ + DispatchMessageW, GetMessageW, TranslateMessage, EVENT_SYSTEM_FOREGROUND, + EVENT_SYSTEM_MINIMIZESTART, MSG, WINEVENT_OUTOFCONTEXT, WINEVENT_SKIPOWNPROCESS, + }, + }, +}; + +use crate::{ + layout_lock, logging, + models::{LogSeverity, RestoreStatus, WindowInfo}, + performance, profiles, + state::AppState, + windows_enum, +}; + +const DESKTOP_RESTORE_DELAY: Duration = Duration::from_millis(500); +const GAME_EXIT_RESTORE_DELAY: Duration = Duration::from_millis(750); +const RESTORE_DEBOUNCE: Duration = Duration::from_secs(3); +const RECENT_MINIMIZE_WINDOW: Duration = Duration::from_secs(2); + +static GUARD: OnceLock> = OnceLock::new(); + +pub fn start(app: AppHandle) { + let guard = Arc::new(DesktopGuard { + app, + timing: Mutex::new(GuardTiming { + latency_sensitive_foreground: performance::foreground_is_latency_sensitive(), + ..GuardTiming::default() + }), + schedule: Mutex::new(None), + schedule_changed: Condvar::new(), + }); + if GUARD.set(guard.clone()).is_err() { + return; + } + + let restore_guard = guard.clone(); + if let Err(error) = thread::Builder::new() + .name("windowautolayout-restore-worker".into()) + .spawn(move || restore_guard.run_restore_worker()) + { + let state = guard.app.state::(); + let _ = logging::append( + &state.config_dir, + LogSeverity::Error, + None, + None, + format!("Could not start restore worker: {error}"), + ); + } + let config_dir = guard.app.state::().config_dir.clone(); + if let Err(error) = thread::Builder::new() + .name("windowautolayout-desktop-events".into()) + .spawn(move || run_event_thread(config_dir)) + { + let state = guard.app.state::(); + let _ = logging::append( + &state.config_dir, + LogSeverity::Error, + None, + None, + format!("Could not start desktop event worker: {error}"), + ); + } +} + +struct DesktopGuard { + app: AppHandle, + timing: Mutex, + schedule: Mutex>, + schedule_changed: Condvar, +} + +#[derive(Default)] +struct GuardTiming { + latency_sensitive_foreground: bool, + last_minimize_start: Option, + last_restore: Option, +} + +impl DesktopGuard { + fn handle_event(&self, event: u32, hwnd: HWND) { + if hwnd.0.is_null() { + return; + } + + match event { + EVENT_SYSTEM_FOREGROUND => self.handle_foreground(hwnd), + EVENT_SYSTEM_MINIMIZESTART => self.handle_minimize_start(), + _ => {} + } + } + + fn handle_foreground(&self, hwnd: HWND) { + let Some(window) = windows_enum::window_info_from_handle_lightweight(hwnd) else { + return; + }; + let is_latency_sensitive = performance::is_latency_sensitive_window(&window); + let (left_latency_sensitive, desktop_reveal) = { + let Ok(mut timing) = self.timing.lock() else { + return; + }; + let was_latency_sensitive = timing.latency_sensitive_foreground; + timing.latency_sensitive_foreground = is_latency_sensitive; + let recent_minimize = timing + .last_minimize_start + .map(|at| at.elapsed() <= RECENT_MINIMIZE_WINDOW) + .unwrap_or(false); + + ( + was_latency_sensitive && !is_latency_sensitive && !is_own_window(&window), + is_desktop_shell_window(&window) + || (recent_minimize && is_taskbar_shell_window(&window)), + ) + }; + + if desktop_reveal { + self.request_restore(DESKTOP_RESTORE_DELAY); + } else if left_latency_sensitive { + self.request_restore(GAME_EXIT_RESTORE_DELAY); + } + } + + fn handle_minimize_start(&self) { + let Ok(mut timing) = self.timing.lock() else { + return; + }; + timing.last_minimize_start = Some(Instant::now()); + } + + fn request_restore(&self, delay: Duration) { + if !layout_lock::enabled(&self.app).unwrap_or(false) { + return; + } + + { + let Ok(timing) = self.timing.lock() else { + return; + }; + if timing + .last_restore + .map(|at| at.elapsed() < RESTORE_DEBOUNCE) + .unwrap_or(false) + { + return; + } + } + + let Ok(mut schedule) = self.schedule.lock() else { + return; + }; + if schedule.is_none() { + *schedule = Some(Instant::now() + delay); + self.schedule_changed.notify_one(); + } + } + + fn run_restore_worker(&self) { + performance::lower_current_thread_priority(); + + loop { + { + let Ok(mut schedule) = self.schedule.lock() else { + return; + }; + loop { + let Some(deadline) = *schedule else { + let Ok(next) = self.schedule_changed.wait(schedule) else { + return; + }; + schedule = next; + continue; + }; + let now = Instant::now(); + if deadline <= now { + *schedule = None; + break; + } + + let Ok((next, wait)) = self + .schedule_changed + .wait_timeout(schedule, deadline.saturating_duration_since(now)) + else { + return; + }; + schedule = next; + if wait.timed_out() && *schedule == Some(deadline) { + *schedule = None; + break; + } + } + } + + if !layout_lock::enabled(&self.app).unwrap_or(false) + || performance::foreground_is_latency_sensitive() + { + continue; + } + + let state = self.app.state::(); + let config_dir = state.config_dir.clone(); + let Ok(config) = state.config.lock().map(|config| config.clone()) else { + continue; + }; + let profile_id = config + .enforcement + .profile_id + .clone() + .or_else(|| config.startup.default_profile_id.clone()); + if profiles::restore_profile_silent(&config_dir, &config, profile_id, Some(false)) + .is_ok_and(|result| !matches!(result.status, RestoreStatus::Paused)) + { + if let Ok(mut timing) = self.timing.lock() { + timing.last_restore = Some(Instant::now()); + } + } + } + } +} + +fn run_event_thread(config_dir: std::path::PathBuf) { + performance::lower_current_thread_priority(); + let hook_foreground = install_hook(EVENT_SYSTEM_FOREGROUND); + let hook_minimize = install_hook(EVENT_SYSTEM_MINIMIZESTART); + if hook_foreground.0.is_null() && hook_minimize.0.is_null() { + let _ = logging::append( + &config_dir, + LogSeverity::Error, + None, + None, + "Could not register Windows desktop event hooks", + ); + return; + } + if hook_foreground.0.is_null() || hook_minimize.0.is_null() { + let _ = logging::append( + &config_dir, + LogSeverity::Warn, + None, + None, + "One Windows desktop event hook could not be registered", + ); + } + + let mut message = MSG::default(); + unsafe { + loop { + let result = GetMessageW(&mut message, None, 0, 0); + if result.0 <= 0 { + break; + } + let _ = TranslateMessage(&message); + DispatchMessageW(&message); + } + if !hook_foreground.0.is_null() { + let _ = windows::Win32::UI::Accessibility::UnhookWinEvent(hook_foreground); + } + if !hook_minimize.0.is_null() { + let _ = windows::Win32::UI::Accessibility::UnhookWinEvent(hook_minimize); + } + } +} + +fn install_hook(event: u32) -> HWINEVENTHOOK { + unsafe { + SetWinEventHook( + event, + event, + None, + Some(win_event_proc), + 0, + 0, + WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS, + ) + } +} + +unsafe extern "system" fn win_event_proc( + _hook: HWINEVENTHOOK, + event: u32, + hwnd: HWND, + _object_id: i32, + _child_id: i32, + _event_thread: u32, + _event_time: u32, +) { + if let Some(guard) = GUARD.get() { + guard.handle_event(event, hwnd); + } +} + +fn is_own_window(window: &WindowInfo) -> bool { + matches!( + window.process_name.trim().to_ascii_lowercase().as_str(), + "windowautolayout.exe" | "windowautolayout" + ) +} + +fn is_desktop_shell_window(window: &WindowInfo) -> bool { + let class = window.class_name.trim().to_ascii_lowercase(); + let title = window.title.trim().to_ascii_lowercase(); + let process = window.process_name.trim().to_ascii_lowercase(); + + process == "explorer.exe" + && (class == "progman" || class == "workerw" || title == "program manager") +} + +fn is_taskbar_shell_window(window: &WindowInfo) -> bool { + let class = window.class_name.trim().to_ascii_lowercase(); + let process = window.process_name.trim().to_ascii_lowercase(); + + process == "explorer.exe" && class == "shell_traywnd" +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn detects_desktop_shell_windows() { + let window = test_window("explorer.exe", "Program Manager", "Progman"); + + assert!(is_desktop_shell_window(&window)); + assert!(!is_taskbar_shell_window(&window)); + } + + #[test] + fn detects_taskbar_shell_window_separately() { + let window = test_window("explorer.exe", "", "Shell_TrayWnd"); + + assert!(!is_desktop_shell_window(&window)); + assert!(is_taskbar_shell_window(&window)); + } + + #[test] + fn ignores_own_windows() { + let window = test_window("WindowAutoLayout.exe", "WindowAutoLayout", "Tauri Window"); + + assert!(is_own_window(&window)); + } + + fn test_window(process_name: &str, title: &str, class_name: &str) -> WindowInfo { + WindowInfo { + handle: "0x1".into(), + title: title.into(), + class_name: class_name.into(), + process_id: 10, + process_name: process_name.into(), + executable_path: None, + monitor_id: None, + x: 0, + y: 0, + width: 100, + height: 100, + is_visible: true, + is_minimized: false, + is_maximized: false, + } + } +} diff --git a/src-tauri/src/errors.rs b/src-tauri/src/errors.rs index 6b83bd4..93bf3b7 100644 --- a/src-tauri/src/errors.rs +++ b/src-tauri/src/errors.rs @@ -21,6 +21,8 @@ pub enum AppError { InvalidWindowHandle(String), #[error("Invalid executable path: {0}")] InvalidExecutablePath(String), + #[error("A layout restore is already in progress")] + RestoreInProgress, } impl Serialize for AppError { diff --git a/src-tauri/src/launcher.rs b/src-tauri/src/launcher.rs index f5fecd5..5c31347 100644 --- a/src-tauri/src/launcher.rs +++ b/src-tauri/src/launcher.rs @@ -14,6 +14,7 @@ use winreg::{ use crate::{ errors::{AppError, AppResult}, models::AppConfig, + processes, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -47,13 +48,8 @@ pub fn launch_app_with_path( command.args(&target.arguments); command.args(&app.arguments); - if let Some(working_directory) = &app.working_directory { - let working_directory = working_directory.trim(); - if !working_directory.is_empty() && Path::new(working_directory).exists() { - command.current_dir(working_directory); - } - } else if let Some(parent) = target.path.parent() { - command.current_dir(parent); + if let Some(working_directory) = launch_working_directory(app, &target.path) { + command.current_dir(working_directory); } let child = command.spawn()?; @@ -71,6 +67,17 @@ fn launch_candidates(app: &AppConfig, preferred_path: Option<&str>) -> Vec, path: Option<&str>) { } fn resolve_candidate(candidate: LaunchTarget) -> Option { + if candidate.use_shell { + return Some(candidate); + } if candidate.path.exists() { return Some(candidate); } @@ -383,13 +393,21 @@ fn start_menu_candidates(app: &AppConfig, process_name: &str) -> Vec) { +fn collect_shortcuts( + root: &Path, + targets: &[String], + candidates: &mut Vec, + depth: usize, +) { + if depth >= 6 || candidates.len() >= 64 { + return; + } let Ok(entries) = fs::read_dir(root) else { return; }; @@ -397,7 +415,7 @@ fn collect_shortcuts(root: &Path, targets: &[String], candidates: &mut Vec= 64 { + return; + } } } +fn launch_working_directory(app: &AppConfig, target: &Path) -> Option { + app.working_directory + .as_deref() + .map(str::trim) + .filter(|path| !path.is_empty()) + .map(PathBuf::from) + .filter(|path| path.is_dir()) + .or_else(|| target.parent().map(Path::to_path_buf)) +} + fn common_install_roots() -> Vec { [ "LOCALAPPDATA", @@ -523,6 +554,13 @@ fn has_path_separator(path: &Path) -> bool { } fn is_shell_item(path: &str) -> bool { + if path + .trim() + .to_ascii_lowercase() + .starts_with("shell:appsfolder\\") + { + return true; + } let ext = Path::new(path) .extension() .map(|ext| ext.to_string_lossy().to_ascii_lowercase()) @@ -597,7 +635,6 @@ mod tests { launch_delay_seconds: 0, detection_timeout_seconds: 1, retry_interval_ms: 100, - launch_if_missing: true, move_if_running: true, force_resize: true, apply_to_all_matching_windows: false, @@ -661,4 +698,31 @@ mod tests { .contains("githubdesktop") })); } + + #[test] + fn store_app_candidates_use_package_family_shell_identity() { + let mut codex = app("Codex", "Codex.exe"); + codex.executable_path = Some( + r"C:\Program Files\WindowsApps\OpenAI.Codex_26.623.5546.0_x64__2p2nqsd0c76g0\app\Codex.exe" + .into(), + ); + + let candidates = launch_candidates(&codex, None); + assert!(candidates.iter().any(|candidate| { + candidate.use_shell + && candidate.path.to_string_lossy() + == r"shell:AppsFolder\OpenAI.Codex_2p2nqsd0c76g0!App" + })); + } + + #[test] + fn invalid_working_directory_falls_back_to_executable_parent() { + let mut app = app("Editor", "Editor.exe"); + app.working_directory = Some(r"Z:\missing\folder".into()); + + assert_eq!( + launch_working_directory(&app, Path::new(r"C:\Apps\Editor\Editor.exe")), + Some(PathBuf::from(r"C:\Apps\Editor")) + ); + } } diff --git a/src-tauri/src/layout_lock.rs b/src-tauri/src/layout_lock.rs index 0ae5b67..8d4a7d3 100644 --- a/src-tauri/src/layout_lock.rs +++ b/src-tauri/src/layout_lock.rs @@ -1,21 +1,13 @@ -use std::{thread, time::Duration}; - use tauri::{AppHandle, Manager}; use crate::{ config, errors::{AppError, AppResult}, logging, - models::{LogSeverity, MonitorInfo, WindowAutoLayoutConfig, WindowInfo}, - monitors, profiles, + models::{LogSeverity, WindowAutoLayoutConfig}, state::AppState, - windows_enum, }; -const MIN_LOCK_INTERVAL_MS: u64 = 2_000; -const MAX_LOCK_INTERVAL_MS: u64 = 5_000; -const FULLSCREEN_PAUSE_INTERVAL_MS: u64 = 10_000; - pub fn enabled(app: &AppHandle) -> AppResult { let state = app.state::(); let enabled = state @@ -28,7 +20,7 @@ pub fn enabled(app: &AppHandle) -> AppResult { pub fn set(app: &AppHandle, enabled: bool, profile_id: Option) -> AppResult { let state = app.state::(); - let (generation, next_config) = { + let next_config = { let mut lock = state .layout_lock .lock() @@ -38,7 +30,6 @@ pub fn set(app: &AppHandle, enabled: bool, profile_id: Option) -> AppRes .lock() .map_err(|_| AppError::Config("Config lock was poisoned".to_string()))?; let next_profile_id = profile_id - .clone() .or_else(|| lock.profile_id.clone()) .or_else(|| config.enforcement.profile_id.clone()) .or_else(|| config.startup.default_profile_id.clone()); @@ -48,7 +39,7 @@ pub fn set(app: &AppHandle, enabled: bool, profile_id: Option) -> AppRes lock.profile_id = next_profile_id.clone(); config.enforcement.enabled = enabled; config.enforcement.profile_id = next_profile_id; - (lock.generation, config.clone()) + config.clone() }; config::save(&state.config_dir, &next_config)?; @@ -58,232 +49,36 @@ pub fn set(app: &AppHandle, enabled: bool, profile_id: Option) -> AppRes None, None, if enabled { - "Layout lock enabled" + "Event-driven layout lock enabled" } else { "Layout lock disabled" }, )?; - if enabled { - spawn(app.clone(), generation); - } - Ok(enabled) } pub fn sync_from_config(app: &AppHandle, config: &WindowAutoLayoutConfig) -> AppResult<()> { let state = app.state::(); - let (enabled, generation) = { - let mut lock = state - .layout_lock - .lock() - .map_err(|_| AppError::Config("Layout lock state was poisoned".to_string()))?; - let next_profile_id = config - .enforcement - .profile_id - .clone() - .or_else(|| config.startup.default_profile_id.clone()); - - if lock.enabled == config.enforcement.enabled && lock.profile_id == next_profile_id { - return Ok(()); - } - + let mut lock = state + .layout_lock + .lock() + .map_err(|_| AppError::Config("Layout lock state was poisoned".to_string()))?; + let next_profile_id = config + .enforcement + .profile_id + .clone() + .or_else(|| config.startup.default_profile_id.clone()); + + if lock.enabled != config.enforcement.enabled || lock.profile_id != next_profile_id { lock.generation = lock.generation.wrapping_add(1); lock.enabled = config.enforcement.enabled; lock.profile_id = next_profile_id; - (lock.enabled, lock.generation) - }; - - if enabled { - spawn(app.clone(), generation); } Ok(()) } pub fn toggle(app: &AppHandle, profile_id: Option) -> AppResult { - let next = !enabled(app)?; - set(app, next, profile_id) -} - -fn spawn(app: AppHandle, generation: u64) { - let mut allow_launch_missing = true; - let mut last_signature: Option = None; - let mut force_restore = true; - thread::spawn(move || loop { - let (config_dir, config, profile_id, interval_ms) = { - let state = app.state::(); - let lock = match state.layout_lock.lock() { - Ok(lock) => lock.clone(), - Err(_) => break, - }; - if !lock.enabled || lock.generation != generation { - break; - } - - let config = match state.config.lock() { - Ok(config) => config.clone(), - Err(_) => break, - }; - let interval_ms = config - .enforcement - .interval_ms - .clamp(MIN_LOCK_INTERVAL_MS, MAX_LOCK_INTERVAL_MS); - ( - state.config_dir.clone(), - config, - lock.profile_id.clone(), - interval_ms, - ) - }; - - let sleep_ms = if should_pause_for_fullscreen(&config, profile_id.as_deref()) { - FULLSCREEN_PAUSE_INTERVAL_MS - } else { - let current_signature = - profiles::profile_window_signature(&config, profile_id.as_deref()).ok(); - let should_restore = should_restore_for_signature( - force_restore, - current_signature.as_ref(), - last_signature.as_ref(), - ); - - if should_restore { - let _ = profiles::restore_profile_silent( - &config_dir, - &config, - profile_id.clone(), - Some(allow_launch_missing), - ); - allow_launch_missing = false; - force_restore = false; - last_signature = profiles::profile_window_signature(&config, profile_id.as_deref()) - .ok() - .or(current_signature); - } - - interval_ms - }; - - thread::sleep(Duration::from_millis(sleep_ms)); - }); -} - -fn should_restore_for_signature( - force_restore: bool, - current_signature: Option<&String>, - last_signature: Option<&String>, -) -> bool { - force_restore - || current_signature - .zip(last_signature) - .map(|(current, last)| current != last) - .unwrap_or(true) -} - -fn should_pause_for_fullscreen(config: &WindowAutoLayoutConfig, profile_id: Option<&str>) -> bool { - if !config.enforcement.pause_for_fullscreen_games { - return false; - } - - let Some(window) = windows_enum::foreground_window() else { - return false; - }; - if !is_fullscreen_window(&window) { - return false; - } - - profiles::resolve_profile(config, profile_id) - .map(|profile| !profiles::window_matches_profile_app(profile, &window)) - .unwrap_or(true) -} - -fn is_fullscreen_window(window: &WindowInfo) -> bool { - if !window.is_visible || window.is_minimized { - return false; - } - - monitors::list_monitors() - .unwrap_or_default() - .iter() - .any(|monitor| covers_monitor(window, monitor)) -} - -fn covers_monitor(window: &WindowInfo, monitor: &MonitorInfo) -> bool { - let tolerance = 4; - (window.x - monitor.x).abs() <= tolerance - && (window.y - monitor.y).abs() <= tolerance - && window.width >= monitor.width - tolerance - && window.height >= monitor.height - tolerance -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn detects_monitor_covering_windows() { - let monitor = MonitorInfo { - id: "display".into(), - name: "Display".into(), - device_name: "DISPLAY1".into(), - x: 0, - y: 0, - width: 2560, - height: 1440, - work_x: 0, - work_y: 0, - work_width: 2560, - work_height: 1392, - scale_factor: 1.25, - is_primary: true, - }; - let fullscreen = WindowInfo { - handle: "0x1".into(), - title: "Game".into(), - class_name: "GameWindow".into(), - process_id: 10, - process_name: "game.exe".into(), - executable_path: None, - monitor_id: Some("display".into()), - x: 0, - y: 0, - width: 2560, - height: 1440, - is_visible: true, - is_minimized: false, - }; - let maximized = WindowInfo { - height: 1392, - ..fullscreen.clone() - }; - - assert!(covers_monitor(&fullscreen, &monitor)); - assert!(!covers_monitor(&maximized, &monitor)); - } - - #[test] - fn restores_when_signature_changes_or_first_pass_is_forced() { - let current = "app:0x1:true:false:0:0:100:100".to_string(); - let same = current.clone(); - let moved = "app:0x1:true:false:10:0:100:100".to_string(); - - assert!(should_restore_for_signature( - true, - Some(¤t), - Some(&same) - )); - assert!(!should_restore_for_signature( - false, - Some(¤t), - Some(&same) - )); - assert!(should_restore_for_signature( - false, - Some(&moved), - Some(&same) - )); - assert!(should_restore_for_signature(false, None, Some(&same))); - assert!(should_restore_for_signature(false, Some(¤t), None)); - } + set(app, !enabled(app)?, profile_id) } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 63755d6..5b73aad 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,13 +1,16 @@ mod commands; mod config; +mod desktop_guard; mod errors; mod launcher; mod layout_lock; mod logging; mod models; mod monitors; +mod performance; mod processes; mod profiles; +mod single_instance; mod startup; mod state; mod window_actions; @@ -27,11 +30,15 @@ use crate::{ #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { + let Some(single_instance) = single_instance::acquire() else { + return; + }; + let activation_event_address = single_instance.activation_event_address(); + tauri::Builder::default() - .plugin(tauri_plugin_opener::init()) - .setup(|app| { - app.handle() - .plugin(tauri_plugin_global_shortcut::Builder::new().build())?; + .device_event_filter(tauri::DeviceEventFilter::Always) + .setup(move |app| { + performance::lower_process_priority(); let config_dir = app.path().app_config_dir()?; let config = match config::load_or_create(&config_dir) { @@ -57,6 +64,18 @@ pub fn run() { None, "WindowAutoLayout started", ); + let (severity, input_status) = match performance::registered_raw_input_device_count() { + Some(0) => (LogSeverity::Info, "Raw input capture disabled".to_string()), + Some(count) => ( + LogSeverity::Warn, + format!("Unexpected raw input registration count: {count}"), + ), + None => ( + LogSeverity::Warn, + "Could not verify raw input registration state".to_string(), + ), + }; + let _ = append(&config_dir, severity, None, None, input_status); if let Some(state) = app.try_state::() { if let Ok(config) = state.config.lock() { if let Err(error) = startup::set_startup_enabled(config.startup.enabled) { @@ -73,8 +92,24 @@ pub fn run() { wire_close_to_tray(app); build_tray(app)?; + if let Some(event_address) = activation_event_address { + if let Err(error) = + single_instance::start_activation_listener(event_address, app.handle().clone()) + { + let _ = append( + &config_dir, + LogSeverity::Warn, + None, + None, + format!("Could not start second-launch listener: {error}"), + ); + } + } + desktop_guard::start(app.handle().clone()); maybe_startup_restore(app.handle().clone()); - maybe_start_layout_lock(app.handle().clone()); + if !is_startup_restore() { + show_main_window(app.handle()); + } Ok(()) }) .invoke_handler(tauri::generate_handler![ @@ -86,9 +121,9 @@ pub fn run() { commands::list_monitors, commands::list_windows, commands::layout_lock_enabled, - commands::lock_layout_temporarily, commands::log_path, commands::open_log_file, + commands::parse_config_json, commands::read_logs, commands::restore_profile, commands::save_all_current_layouts, @@ -127,6 +162,9 @@ fn wire_close_to_tray(app: &tauri::App) { if should_hide { api.prevent_close(); let _ = window_to_hide.hide(); + } else { + api.prevent_close(); + app_handle.exit(0); } } }); @@ -152,7 +190,7 @@ fn build_tray(app: &tauri::App) -> tauri::Result<()> { .show_menu_on_left_click(false) .on_menu_event(|app, event| match event.id.as_ref() { "restore_default" => restore_default_in_background(app.clone(), None, Some(true)), - "layout_lock" => toggle_layout_lock(app.clone(), None), + "layout_lock" => toggle_layout_lock(app), "open" => show_main_window(app), "logs" => open_logs(app), "quit" => app.exit(0), @@ -178,7 +216,7 @@ fn build_tray(app: &tauri::App) -> tauri::Result<()> { } fn maybe_startup_restore(app: tauri::AppHandle) { - let is_startup = std::env::args().any(|arg| arg == "--startup-restore"); + let is_startup = is_startup_restore(); if !is_startup { return; } @@ -193,7 +231,7 @@ fn maybe_startup_restore(app: tauri::AppHandle) { let _ = window.hide(); } } - if !config.startup.restore_on_launch { + if !config.startup.restore_on_launch && !config.enforcement.enabled { return; } @@ -202,38 +240,31 @@ fn maybe_startup_restore(app: tauri::AppHandle) { if delay > 0 { tokio_sleep(delay).await; } - restore_default_in_background(app, None, Some(true)); + let state = app.state::(); + let config_dir = state.config_dir.clone(); + let config = match state.config.lock() { + Ok(config) => config.clone(), + Err(_) => return, + }; + let _ = tauri::async_runtime::spawn_blocking(move || { + if let Err(error) = + profiles::restore_profile_background(&config_dir, &config, None, Some(true)) + { + let _ = append( + &config_dir, + LogSeverity::Warn, + None, + None, + format!("Startup restore did not run: {error}"), + ); + } + }) + .await; }); } -fn maybe_start_layout_lock(app: tauri::AppHandle) { - let is_startup = std::env::args().any(|arg| arg == "--startup-restore"); - let state = app.state::(); - let config = match state.config.lock() { - Ok(config) => config.clone(), - Err(_) => return, - }; - if !config.enforcement.enabled { - return; - } - - let profile_id = config - .enforcement - .profile_id - .clone() - .or_else(|| config.startup.default_profile_id.clone()); - let delay = if is_startup { - config.startup.delay_seconds - } else { - 0 - }; - - tauri::async_runtime::spawn(async move { - if delay > 0 { - tokio_sleep(delay).await; - } - let _ = layout_lock::set(&app, true, profile_id); - }); +fn is_startup_restore() -> bool { + std::env::args().any(|arg| arg == "--startup-restore") } async fn tokio_sleep(seconds: u64) { @@ -258,26 +289,59 @@ fn restore_default_in_background( tauri::async_runtime::spawn(async move { let _ = tauri::async_runtime::spawn_blocking(move || { - profiles::restore_profile(&config_dir, &config, profile_id, launch_missing) + if let Err(error) = + profiles::restore_profile(&config_dir, &config, profile_id, launch_missing) + { + let _ = append( + &config_dir, + LogSeverity::Warn, + None, + None, + format!("Tray restore did not run: {error}"), + ); + } }) .await; }); } -fn toggle_layout_lock(app: tauri::AppHandle, profile_id: Option) { - let _ = layout_lock::toggle(&app, profile_id); +fn toggle_layout_lock(app: &tauri::AppHandle) { + if let Err(error) = layout_lock::toggle(app, None) { + let state = app.state::(); + let _ = append( + &state.config_dir, + LogSeverity::Error, + None, + None, + format!("Could not toggle layout lock: {error}"), + ); + } } -fn show_main_window(app: &tauri::AppHandle) { +pub(crate) fn show_main_window(app: &tauri::AppHandle) { if let Some(window) = app.get_webview_window("main") { let _ = window.show(); let _ = window.unminimize(); - let _ = window.set_focus(); + if let Ok(hwnd) = window.hwnd() { + let hwnd = windows::Win32::Foundation::HWND(hwnd.0 as usize as *mut std::ffi::c_void); + unsafe { + let _ = windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow(hwnd); + } + } } } fn open_logs(app: &tauri::AppHandle) { let state = app.state::(); let path = logging::log_file_path(&state.config_dir); + if !path.exists() { + let _ = append( + &state.config_dir, + LogSeverity::Info, + None, + None, + "Created log file", + ); + } let _ = std::process::Command::new("explorer").arg(path).spawn(); } diff --git a/src-tauri/src/logging.rs b/src-tauri/src/logging.rs index ea6b58c..7df1cfd 100644 --- a/src-tauri/src/logging.rs +++ b/src-tauri/src/logging.rs @@ -2,6 +2,7 @@ use std::{ fs::{self, OpenOptions}, io::Write, path::{Path, PathBuf}, + sync::Mutex, }; use chrono::Utc; @@ -14,6 +15,7 @@ use crate::{ const LOG_DIR_NAME: &str = "logs"; const LOG_FILE_NAME: &str = "windowautolayout.log"; const MAX_LOG_BYTES: u64 = 1_048_576; +static LOG_LOCK: Mutex<()> = Mutex::new(()); pub fn log_file_path(config_dir: &Path) -> PathBuf { config_dir.join(LOG_DIR_NAME).join(LOG_FILE_NAME) @@ -26,6 +28,7 @@ pub fn append( app: Option<&str>, message: impl AsRef, ) -> AppResult<()> { + let _guard = LOG_LOCK.lock().unwrap_or_else(|error| error.into_inner()); let path = log_file_path(config_dir); if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; @@ -46,6 +49,7 @@ pub fn append( } pub fn read(config_dir: &Path, max_lines: usize) -> AppResult> { + let _guard = LOG_LOCK.lock().unwrap_or_else(|error| error.into_inner()); let path = log_file_path(config_dir); if !path.exists() { return Ok(Vec::new()); @@ -63,6 +67,7 @@ pub fn read(config_dir: &Path, max_lines: usize) -> AppResult> { } pub fn clear(config_dir: &Path) -> AppResult<()> { + let _guard = LOG_LOCK.lock().unwrap_or_else(|error| error.into_inner()); let path = log_file_path(config_dir); if path.exists() { fs::write(path, "")?; diff --git a/src-tauri/src/models.rs b/src-tauri/src/models.rs index 3184575..bd0926b 100644 --- a/src-tauri/src/models.rs +++ b/src-tauri/src/models.rs @@ -1,15 +1,15 @@ use serde::{Deserialize, Serialize}; -pub const CONFIG_SCHEMA_VERSION: u32 = 3; +pub const CONFIG_SCHEMA_VERSION: u32 = 5; pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub enum MonitorMissingBehavior { + #[serde(alias = "askNextOpen")] DoNothing, UsePrimary, NearestMatch, - AskNextOpen, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -35,6 +35,7 @@ pub enum TitleMatchMode { pub enum RestoreStatus { Success, PartialSuccess, + Paused, Failed, MonitorMissing, } @@ -44,6 +45,7 @@ pub enum RestoreStatus { pub enum AppRestoreStatus { Success, Skipped, + Paused, Launched, LaunchedWindowNotFound, ProcessRunningWindowNotFound, @@ -107,7 +109,6 @@ pub struct AppConfig { pub launch_delay_seconds: u64, pub detection_timeout_seconds: u64, pub retry_interval_ms: u64, - pub launch_if_missing: bool, pub move_if_running: bool, pub force_resize: bool, pub apply_to_all_matching_windows: bool, @@ -142,7 +143,6 @@ impl AppConfig { launch_delay_seconds: 0, detection_timeout_seconds: 25, retry_interval_ms: 700, - launch_if_missing: true, move_if_running: true, force_resize: true, apply_to_all_matching_windows: false, @@ -167,8 +167,6 @@ pub struct Profile { pub description: Option, pub target_monitor_id: Option, pub apps: Vec, - pub startup_restore: bool, - pub enforce_after_restore: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -176,8 +174,6 @@ pub struct Profile { pub struct GlobalSettings { pub default_monitor_id: Option, pub monitor_missing_behavior: MonitorMissingBehavior, - pub warn_when_monitor_missing: bool, - pub advanced_mode: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -189,22 +185,12 @@ pub struct StartupSettings { pub delay_seconds: u64, pub restore_on_launch: bool, pub launch_missing_apps: bool, - pub enforce_after_startup: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct TraySettings { pub minimize_to_tray_on_close: bool, - pub show_restore_status: bool, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct HotkeySettings { - pub enabled: bool, - pub accelerator: String, - pub restore_without_opening: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -213,10 +199,6 @@ pub struct EnforcementSettings { pub enabled: bool, #[serde(default)] pub profile_id: Option, - pub duration_seconds: u64, - pub interval_ms: u64, - #[serde(default = "default_true")] - pub pause_for_fullscreen_games: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -227,7 +209,6 @@ pub struct WindowAutoLayoutConfig { pub global: GlobalSettings, pub startup: StartupSettings, pub tray: TraySettings, - pub hotkey: HotkeySettings, pub enforcement: EnforcementSettings, pub profiles: Vec, } @@ -266,6 +247,7 @@ pub struct WindowInfo { pub height: i32, pub is_visible: bool, pub is_minimized: bool, + pub is_maximized: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -349,7 +331,6 @@ pub fn preset_apps() -> Vec { value: "GitHub Desktop".to_string(), case_sensitive: false, }); - github_desktop.launch_if_missing = true; github_desktop.detection_timeout_seconds = 45; vec![ @@ -405,8 +386,6 @@ impl Default for WindowAutoLayoutConfig { global: GlobalSettings { default_monitor_id: None, monitor_missing_behavior: MonitorMissingBehavior::NearestMatch, - warn_when_monitor_missing: true, - advanced_mode: false, }, startup: StartupSettings { enabled: false, @@ -415,23 +394,13 @@ impl Default for WindowAutoLayoutConfig { delay_seconds: 8, restore_on_launch: true, launch_missing_apps: true, - enforce_after_startup: true, }, tray: TraySettings { minimize_to_tray_on_close: true, - show_restore_status: true, - }, - hotkey: HotkeySettings { - enabled: true, - accelerator: "Ctrl+Alt+L".to_string(), - restore_without_opening: true, }, enforcement: EnforcementSettings { enabled: false, profile_id: Some(default_profile_id.clone()), - duration_seconds: 30, - interval_ms: 2000, - pause_for_fullscreen_games: true, }, profiles: vec![Profile { id: default_profile_id, @@ -439,8 +408,6 @@ impl Default for WindowAutoLayoutConfig { description: Some("OBS and Discord arranged on a selected monitor.".to_string()), target_monitor_id: None, apps: streaming_apps, - startup_restore: true, - enforce_after_restore: true, }], } } diff --git a/src-tauri/src/monitors.rs b/src-tauri/src/monitors.rs index 20811f1..51d4289 100644 --- a/src-tauri/src/monitors.rs +++ b/src-tauri/src/monitors.rs @@ -33,21 +33,7 @@ pub fn monitor_for_rect(rect: RECT) -> Option { return None; } - list_monitors().ok().and_then(|monitors| { - monitors - .into_iter() - .find(|monitor| monitor_matches_handle(monitor, handle)) - }) -} - -fn monitor_matches_handle(monitor: &MonitorInfo, handle: HMONITOR) -> bool { - let mut info = MONITORINFOEXW::default(); - info.monitorInfo.cbSize = std::mem::size_of::() as u32; - let ok = unsafe { GetMonitorInfoW(handle, &mut info as *mut MONITORINFOEXW as *mut _) }; - if !ok.as_bool() { - return false; - } - monitor.device_name == wide_to_string(&info.szDevice) + monitor_info(handle) } unsafe extern "system" fn enum_monitor_proc( diff --git a/src-tauri/src/performance.rs b/src-tauri/src/performance.rs new file mode 100644 index 0000000..587f129 --- /dev/null +++ b/src-tauri/src/performance.rs @@ -0,0 +1,153 @@ +use windows::Win32::Foundation::RECT; +use windows::Win32::System::Threading::{ + GetCurrentProcess, GetCurrentThread, SetPriorityClass, SetThreadPriority, + BELOW_NORMAL_PRIORITY_CLASS, THREAD_PRIORITY_BELOW_NORMAL, +}; +use windows::Win32::UI::Input::{GetRegisteredRawInputDevices, RAWINPUTDEVICE}; + +use crate::{models::WindowInfo, monitors, windows_enum}; + +pub fn lower_process_priority() { + unsafe { + let _ = SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); + } +} + +pub fn lower_current_thread_priority() { + unsafe { + let _ = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); + } +} + +pub fn registered_raw_input_device_count() -> Option { + let mut count = 0u32; + let result = unsafe { + GetRegisteredRawInputDevices( + None, + &mut count, + std::mem::size_of::() as u32, + ) + }; + if result == u32::MAX { + None + } else { + Some(count) + } +} + +pub fn foreground_is_latency_sensitive() -> bool { + windows_enum::foreground_window() + .map(|window| is_latency_sensitive_window(&window)) + .unwrap_or(false) +} + +pub fn is_latency_sensitive_window(window: &WindowInfo) -> bool { + if is_latency_sensitive_game_process(&window.process_name) { + return true; + } + + let rect = RECT { + left: window.x, + top: window.y, + right: window.x + window.width, + bottom: window.y + window.height, + }; + monitors::monitor_for_rect(rect) + .map(|monitor| covers_monitor(window, &monitor)) + .unwrap_or(false) +} + +pub fn is_latency_sensitive_game_process(process_name: &str) -> bool { + matches!( + process_name.trim().to_ascii_lowercase().as_str(), + "valorant-win64-shipping.exe" + | "valorant.exe" + | "cs2.exe" + | "csgo.exe" + | "fortniteclient-win64-shipping.exe" + | "r5apex.exe" + | "overwatch.exe" + | "league of legends.exe" + | "rocketleague.exe" + | "tslgame.exe" + | "rainbowsix.exe" + | "rainbowsix_vulkan.exe" + | "escapefromtarkov.exe" + | "minecraft.windows.exe" + | "javaw.exe" + | "osu!.exe" + | "eldenring.exe" + | "gta5.exe" + | "fivem.exe" + | "helldivers2.exe" + ) +} + +fn covers_monitor(window: &WindowInfo, monitor: &crate::models::MonitorInfo) -> bool { + if !window.is_visible || window.is_minimized { + return false; + } + + let tolerance = 4; + (window.x - monitor.x).abs() <= tolerance + && (window.y - monitor.y).abs() <= tolerance + && window.width >= monitor.width - tolerance + && window.height >= monitor.height - tolerance +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::models::MonitorInfo; + + #[test] + fn recognizes_named_games_without_requiring_fullscreen() { + assert!(is_latency_sensitive_game_process( + "VALORANT-Win64-Shipping.exe" + )); + assert!(is_latency_sensitive_game_process("javaw.exe")); + assert!(!is_latency_sensitive_game_process("Discord.exe")); + } + + #[test] + fn distinguishes_fullscreen_from_work_area_windows() { + let monitor = MonitorInfo { + id: "display".into(), + name: "Display".into(), + device_name: "DISPLAY1".into(), + x: 0, + y: 0, + width: 2560, + height: 1440, + work_x: 0, + work_y: 0, + work_width: 2560, + work_height: 1392, + scale_factor: 1.25, + is_primary: true, + }; + let fullscreen = WindowInfo { + handle: "0x1".into(), + title: "Game".into(), + class_name: "GameWindow".into(), + process_id: 10, + process_name: "unknown-game.exe".into(), + executable_path: None, + monitor_id: Some("display".into()), + x: 0, + y: 0, + width: 2560, + height: 1440, + is_visible: true, + is_minimized: false, + is_maximized: false, + }; + let maximized = WindowInfo { + height: 1392, + ..fullscreen.clone() + }; + + assert!(covers_monitor(&fullscreen, &monitor)); + assert!(!covers_monitor(&maximized, &monitor)); + } +} diff --git a/src-tauri/src/processes.rs b/src-tauri/src/processes.rs index 401aa1b..35fa6d3 100644 --- a/src-tauri/src/processes.rs +++ b/src-tauri/src/processes.rs @@ -54,10 +54,15 @@ pub fn list_processes() -> AppResult> { } pub fn query_process_name(pid: u32) -> String { - list_processes() - .ok() - .and_then(|processes| processes.into_iter().find(|process| process.pid == pid)) - .map(|process| process.name) + query_process_path(pid) + .as_deref() + .and_then(file_name_from_path) + .or_else(|| { + list_processes() + .ok() + .and_then(|processes| processes.into_iter().find(|process| process.pid == pid)) + .map(|process| process.name) + }) .unwrap_or_default() } @@ -90,6 +95,28 @@ pub fn file_name_from_path(path: &str) -> Option { .map(|value| value.to_string_lossy().to_string()) } +pub fn windows_app_package_family(path: &str) -> Option { + let normalized = path.replace('/', "\\"); + let lower = normalized.to_ascii_lowercase(); + let marker = "\\windowsapps\\"; + let start = lower.find(marker)? + marker.len(); + let package_full_name = normalized[start..].split('\\').next()?; + let (name_and_version, publisher_id) = package_full_name.rsplit_once("__")?; + let package_name = name_and_version.split('_').next()?; + if package_name.is_empty() || publisher_id.is_empty() { + return None; + } + + Some(format!("{package_name}_{publisher_id}")) +} + +pub fn same_windows_app_package(left: &str, right: &str) -> bool { + windows_app_package_family(left) + .zip(windows_app_package_family(right)) + .map(|(left, right)| left.eq_ignore_ascii_case(&right)) + .unwrap_or(false) +} + fn wide_to_string(buffer: &[u16]) -> String { let len = buffer .iter() @@ -97,3 +124,21 @@ fn wide_to_string(buffer: &[u16]) -> String { .unwrap_or(buffer.len()); String::from_utf16_lossy(&buffer[..len]) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn store_package_identity_survives_versioned_folder_changes() { + let old = r"C:\Program Files\WindowsApps\OpenAI.Codex_26.623.5546.0_x64__2p2nqsd0c76g0\app\Codex.exe"; + let new = r"C:\Program Files\WindowsApps\OpenAI.Codex_26.707.3563.0_x64__2p2nqsd0c76g0\app\ChatGPT.exe"; + + assert_eq!( + windows_app_package_family(old).as_deref(), + Some("OpenAI.Codex_2p2nqsd0c76g0") + ); + assert!(same_windows_app_package(old, new)); + assert!(!same_windows_app_package(old, r"C:\Apps\Discord.exe")); + } +} diff --git a/src-tauri/src/profiles.rs b/src-tauri/src/profiles.rs index 98b4166..be81013 100644 --- a/src-tauri/src/profiles.rs +++ b/src-tauri/src/profiles.rs @@ -1,5 +1,6 @@ use std::{ path::Path, + sync::{Mutex, TryLockError}, thread, time::{Duration, Instant}, }; @@ -15,9 +16,11 @@ use crate::{ MonitorInfo, MonitorMissingBehavior, Profile, RestoreResult, RestoreStatus, TitleMatchMode, WindowAutoLayoutConfig, WindowInfo, }, - monitors, processes, window_actions, windows_enum, + monitors, performance, processes, window_actions, windows_enum, }; +static RESTORE_LOCK: Mutex<()> = Mutex::new(()); + #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum AppPresence { NotRunning, @@ -42,6 +45,13 @@ struct RestoreTarget<'a> { layout: &'a LayoutRect, } +#[derive(Clone, Copy)] +struct RestoreMode { + log_events: bool, + activate_visible_windows: bool, + abort_for_latency_sensitive_foreground: bool, +} + pub fn restore_profile( config_dir: &Path, config: &WindowAutoLayoutConfig, @@ -53,8 +63,11 @@ pub fn restore_profile( config, profile_id, launch_missing_override, - true, - true, + RestoreMode { + log_events: true, + activate_visible_windows: true, + abort_for_latency_sensitive_foreground: true, + }, ) } @@ -69,60 +82,31 @@ pub fn restore_profile_silent( config, profile_id, launch_missing_override, - false, - false, + RestoreMode { + log_events: false, + activate_visible_windows: false, + abort_for_latency_sensitive_foreground: true, + }, ) } -pub fn profile_window_signature( +pub fn restore_profile_background( + config_dir: &Path, config: &WindowAutoLayoutConfig, - profile_id: Option<&str>, -) -> AppResult { - let profile = resolve_profile(config, profile_id)?; - let windows = windows_enum::list_windows_with_hidden(true).unwrap_or_default(); - Ok(profile_window_signature_from_windows(profile, &windows)) -} - -fn profile_window_signature_from_windows(profile: &Profile, windows: &[WindowInfo]) -> String { - profile - .apps - .iter() - .map(|app| app_window_signature(app, windows)) - .collect::>() - .join("|") -} - -fn app_window_signature(app: &AppConfig, windows: &[WindowInfo]) -> String { - let mut matched = windows - .iter() - .filter(|window| window_matches_app(window, app, None)) - .cloned() - .collect::>(); - sort_matching_windows(&mut matched); - let selected = selected_matching_windows(app, &matched); - - if selected.is_empty() { - return format!("{}:missing", app.id); - } - - let windows = selected - .iter() - .map(|window| { - format!( - "{}:{}:{}:{}:{}:{}:{}:{}", - window.handle, - window.process_id, - window.is_visible, - window.is_minimized, - window.x, - window.y, - window.width, - window.height - ) - }) - .collect::>() - .join(","); - format!("{}:{windows}", app.id) + profile_id: Option, + launch_missing_override: Option, +) -> AppResult { + restore_profile_inner( + config_dir, + config, + profile_id, + launch_missing_override, + RestoreMode { + log_events: true, + activate_visible_windows: false, + abort_for_latency_sensitive_foreground: true, + }, + ) } fn restore_profile_inner( @@ -130,11 +114,31 @@ fn restore_profile_inner( config: &WindowAutoLayoutConfig, profile_id: Option, launch_missing_override: Option, - log_events: bool, - activate_visible_windows: bool, + mode: RestoreMode, ) -> AppResult { + let _restore_guard = match RESTORE_LOCK.try_lock() { + Ok(guard) => guard, + Err(TryLockError::WouldBlock) => return Err(AppError::RestoreInProgress), + Err(TryLockError::Poisoned(_)) => { + return Err(AppError::Config("Restore lock was poisoned".to_string())) + } + }; + let log_events = mode.log_events; + let abort_for_latency_sensitive_foreground = mode.abort_for_latency_sensitive_foreground; let started_at = Utc::now(); let profile = resolve_profile(config, profile_id.as_deref())?.clone(); + if abort_for_latency_sensitive_foreground && performance::foreground_is_latency_sensitive() { + if log_events { + logging::append( + config_dir, + LogSeverity::Info, + Some(&profile.name), + None, + "Restore paused for a foreground game or fullscreen app", + )?; + } + return Ok(paused_restore_result(profile, started_at)); + } if log_events { logging::append( config_dir, @@ -171,7 +175,9 @@ fn restore_profile_inner( return Ok(result); } - let monitor = monitor.expect("checked above"); + let Some(monitor) = monitor else { + return Err(AppError::MonitorNotFound); + }; if monitor.is_fallback && log_events { logging::append( config_dir, @@ -181,28 +187,29 @@ fn restore_profile_inner( format!("Saved monitor is missing; using {}", monitor.monitor.name), )?; } + let mut paused = false; for app in &profile.apps { + if abort_for_latency_sensitive_foreground && performance::foreground_is_latency_sensitive() + { + paused = true; + break; + } let app_monitor = resolve_app_monitor(config, &profile, app, &monitors) .unwrap_or_else(|| monitor.clone()); - let layout = if app_monitor.is_fallback { - scaled_layout_for_monitor(&profile, app, &app_monitor.monitor) - } else { - app.layout.clone() - }; + let layout = restore_layout_for_monitor(&profile, app, &app_monitor); let launch_missing = launch_missing_override.unwrap_or(config.startup.launch_missing_apps); let target = RestoreTarget { monitor: &app_monitor.monitor, layout: &layout, }; - results.push(restore_app( - config_dir, - &profile, - app, - target, - launch_missing, - log_events, - activate_visible_windows, - )); + let result = restore_app(config_dir, &profile, app, target, launch_missing, mode); + if matches!(result.status, AppRestoreStatus::Paused) { + paused = true; + } + results.push(result); + if paused { + break; + } } let success_count = results @@ -210,11 +217,13 @@ fn restore_profile_inner( .filter(|result| { matches!( result.status, - AppRestoreStatus::Success | AppRestoreStatus::Launched + AppRestoreStatus::Success | AppRestoreStatus::Launched | AppRestoreStatus::Skipped ) }) .count(); - let status = if success_count == results.len() { + let status = if paused { + RestoreStatus::Paused + } else if success_count == results.len() { RestoreStatus::Success } else if success_count > 0 { RestoreStatus::PartialSuccess @@ -225,7 +234,7 @@ fn restore_profile_inner( if log_events { logging::append( config_dir, - if matches!(status, RestoreStatus::Success) { + if matches!(status, RestoreStatus::Success | RestoreStatus::Paused) { LogSeverity::Info } else { LogSeverity::Warn @@ -247,23 +256,16 @@ fn restore_profile_inner( }) } -pub fn enforce_profile_for( - config_dir: &Path, - config: &WindowAutoLayoutConfig, - profile_id: Option, - duration_seconds: u64, - interval_ms: u64, -) -> AppResult { - let interval = interval_ms.clamp(2000, 5000); - let until = Instant::now() + Duration::from_secs(duration_seconds.max(1)); - let mut last = restore_profile(config_dir, config, profile_id.clone(), Some(false))?; - - while Instant::now() < until { - thread::sleep(Duration::from_millis(interval)); - last = restore_profile(config_dir, config, profile_id.clone(), Some(false))?; +fn paused_restore_result(profile: Profile, started_at: chrono::DateTime) -> RestoreResult { + RestoreResult { + profile_id: profile.id, + profile_name: profile.name, + status: RestoreStatus::Paused, + started_at: started_at.to_rfc3339(), + finished_at: Utc::now().to_rfc3339(), + monitor: None, + results: Vec::new(), } - - Ok(last) } pub fn resolve_profile<'a>( @@ -296,9 +298,13 @@ fn restore_app( app: &AppConfig, target: RestoreTarget<'_>, launch_missing: bool, - log_events: bool, - activate_visible_windows: bool, + mode: RestoreMode, ) -> AppRestoreResult { + let RestoreMode { + log_events, + activate_visible_windows, + abort_for_latency_sensitive_foreground, + } = mode; let mut matched = find_matching_windows(app, None); let mut running_processes = matching_processes(app); let mut presence = if matched.is_empty() { @@ -311,9 +317,11 @@ fn restore_app( AppPresence::RunningWithWindow }; let mut launched = false; - let mut activate_after_hidden_restore = false; - if launch_missing && should_show_matched_windows(app, &matched) { + if abort_for_latency_sensitive_foreground && performance::foreground_is_latency_sensitive() + { + return background_restore_paused(app, matched); + } let selected = selected_matching_windows(app, &matched); if should_restore_through_qt_tray(app, &selected) { let mut activated_processes = Vec::new(); @@ -340,6 +348,7 @@ fn restore_app( None, app.detection_timeout_seconds, app.retry_interval_ms, + abort_for_latency_sensitive_foreground, ); if restored .iter() @@ -357,7 +366,6 @@ fn restore_app( } else { AppPresence::RunningWithWindow }; - activate_after_hidden_restore = true; } } } @@ -367,7 +375,9 @@ fn restore_app( if should_show_matched_windows(app, &selected) { for window in &selected { match windows_enum::parse_handle(&window.handle) { - Ok(hwnd) => window_actions::show_window_for_restore(hwnd), + Ok(hwnd) => { + window_actions::show_window_for_restore(hwnd, activate_visible_windows) + } Err(error) => { show_error = Some(error.to_string()); break; @@ -401,6 +411,7 @@ fn restore_app( None, app.detection_timeout_seconds, app.retry_interval_ms, + abort_for_latency_sensitive_foreground, ); settle_visible_window(app); matched = find_matching_windows(app, None); @@ -414,7 +425,6 @@ fn restore_app( } else { AppPresence::RunningWithWindow }; - activate_after_hidden_restore = true; } } @@ -446,6 +456,7 @@ fn restore_app( None, app.detection_timeout_seconds, app.retry_interval_ms, + abort_for_latency_sensitive_foreground, ); settle_visible_window(app); matched = find_matching_windows(app, None); @@ -459,19 +470,23 @@ fn restore_app( } else { AppPresence::RunningWithWindow }; - activate_after_hidden_restore = true; } } let should_launch_missing = matches!(presence, AppPresence::NotRunning); let should_wake_running = matches!(presence, AppPresence::RunningWithoutWindow) && app.wake_running_process; - let should_launch_running_process = should_wake_running && !is_obs_app(app); + let should_launch_running_process = + should_wake_running && !is_obs_app(app) && !is_quick_tray_detection_app(app); if matched.is_empty() && launch_missing && (should_launch_missing || should_launch_running_process) { + if abort_for_latency_sensitive_foreground && performance::foreground_is_latency_sensitive() + { + return background_restore_paused(app, matched); + } let launch_path = if should_launch_running_process { running_process_launch_path(app, &running_processes) } else { @@ -536,8 +551,9 @@ fn restore_app( let _ = wait_for_visible_windows( app, launched_pid, - app.detection_timeout_seconds, + launch_detection_timeout_seconds(app), app.retry_interval_ms, + abort_for_latency_sensitive_foreground, ); settle_visible_window(app); matched = find_matching_windows(app, launched_pid); @@ -554,6 +570,35 @@ fn restore_app( } if matched.is_empty() { + if is_quick_tray_detection_app(app) && matches!(presence, AppPresence::RunningWithoutWindow) + { + let message = if launched { + "App launched and is running in the tray; no movable window was exposed" + } else { + "App is running in the tray; no movable window was exposed" + } + .to_string(); + if log_events { + let _ = logging::append( + config_dir, + LogSeverity::Info, + Some(&profile.name), + Some(&app.display_name), + &message, + ); + } + return app_result( + app, + if launched { + AppRestoreStatus::Launched + } else { + AppRestoreStatus::Success + }, + message, + matched, + ); + } + let status = if launched { AppRestoreStatus::LaunchedWindowNotFound } else { @@ -593,6 +638,10 @@ fn restore_app( let mut already_current_count = 0usize; for window in &selected { + if abort_for_latency_sensitive_foreground && performance::foreground_is_latency_sensitive() + { + return background_restore_paused(app, matched); + } let hwnd = match windows_enum::parse_handle(&window.handle) { Ok(hwnd) => hwnd, Err(error) => { @@ -601,10 +650,7 @@ fn restore_app( }; let pull_hidden_window = app.pull_hidden_windows && !window.is_visible; let restore_minimized_window = app.restore_if_minimized && window.is_minimized; - let activate_window = pull_hidden_window - || restore_minimized_window - || activate_after_hidden_restore - || activate_visible_windows; + let activate_window = activate_visible_windows; if window_layout_is_current( window, target.monitor, @@ -627,22 +673,21 @@ fn restore_app( pull_hidden_window, activate_window, ) { - let message = error.to_string(); - let status = if message.to_ascii_lowercase().contains("access") { - AppRestoreStatus::PermissionDenied - } else { - AppRestoreStatus::MoveFailed - }; - if log_events { - let _ = logging::append( - config_dir, - LogSeverity::Error, - Some(&profile.name), - Some(&app.display_name), - &message, - ); + return move_failed_result(config_dir, profile, app, matched, error, log_events); + } + if should_retry_layout(hwnd, target.monitor, app, target.layout) { + if let Err(error) = window_actions::apply_layout( + hwnd, + target.monitor, + target.layout, + &app.window_state, + app.force_resize, + restore_minimized_window, + pull_hidden_window, + activate_window, + ) { + return move_failed_result(config_dir, profile, app, matched, error, log_events); } - return app_result(app, status, message, matched); } moved_count += 1; } @@ -684,13 +729,6 @@ fn restore_app( app_result(app, status, message, selected) } -pub fn window_matches_profile_app(profile: &Profile, window: &WindowInfo) -> bool { - profile - .apps - .iter() - .any(|app| window_matches_app(window, app, None)) -} - pub fn find_matching_windows(app: &AppConfig, launched_pid: Option) -> Vec { let mut matched = windows_enum::list_windows_with_hidden(app.pull_hidden_windows || launched_pid.is_some()) @@ -708,7 +746,10 @@ fn sort_matching_windows(matched: &mut [WindowInfo]) { .is_visible .cmp(&left.is_visible) .then(left.is_minimized.cmp(&right.is_minimized)) - .then((right.width * right.height).cmp(&(left.width * left.height))) + .then( + (i64::from(right.width) * i64::from(right.height)) + .cmp(&(i64::from(left.width) * i64::from(left.height))), + ) .then(left.title.cmp(&right.title)) }); } @@ -730,6 +771,15 @@ fn window_layout_is_current( return false; } + window_geometry_matches_layout(window, monitor, app, layout) +} + +fn window_geometry_matches_layout( + window: &WindowInfo, + monitor: &MonitorInfo, + app: &AppConfig, + layout: &LayoutRect, +) -> bool { let rect = window_actions::absolute_rect(monitor, layout); nearly_equal(window.x, rect.left) && nearly_equal(window.y, rect.top) @@ -738,8 +788,24 @@ fn window_layout_is_current( && nearly_equal(window.height, rect.bottom - rect.top))) } +fn should_retry_layout( + hwnd: windows::Win32::Foundation::HWND, + monitor: &MonitorInfo, + app: &AppConfig, + layout: &LayoutRect, +) -> bool { + if app.window_state != crate::models::WindowStatePreference::Normal { + return false; + } + + thread::sleep(Duration::from_millis(80)); + windows_enum::window_info_from_handle(hwnd) + .map(|window| !window_geometry_matches_layout(&window, monitor, app, layout)) + .unwrap_or(false) +} + fn nearly_equal(left: i32, right: i32) -> bool { - (left - right).abs() <= 3 + left.abs_diff(right) <= 3 } fn should_show_matched_windows(app: &AppConfig, matched: &[WindowInfo]) -> bool { @@ -767,13 +833,18 @@ fn wait_for_visible_windows( launched_pid: Option, timeout_seconds: u64, retry_interval_ms: u64, + abort_for_latency_sensitive_foreground: bool, ) -> Vec { let timeout = Duration::from_secs(timeout_seconds.max(1)); - let interval = Duration::from_millis(retry_interval_ms.max(100)); + let interval = Duration::from_millis(retry_interval_ms.clamp(250, 5000)); let deadline = Instant::now() + timeout; let mut last_match = Vec::new(); loop { + if abort_for_latency_sensitive_foreground && performance::foreground_is_latency_sensitive() + { + return last_match; + } let matched = find_matching_windows(app, launched_pid); if matched .iter() @@ -791,6 +862,15 @@ fn wait_for_visible_windows( } } +fn background_restore_paused(app: &AppConfig, matched: Vec) -> AppRestoreResult { + app_result( + app, + AppRestoreStatus::Paused, + "Restore paused for a foreground game or fullscreen app".to_string(), + matched, + ) +} + fn settle_visible_window(app: &AppConfig) { let delay = if is_obs_app(app) { app.retry_interval_ms.clamp(2500, 3500) @@ -806,6 +886,20 @@ fn is_obs_app(app: &AppConfig) -> bool { .unwrap_or(false) } +fn launch_detection_timeout_seconds(app: &AppConfig) -> u64 { + if is_quick_tray_detection_app(app) { + app.detection_timeout_seconds.clamp(1, 5) + } else { + app.detection_timeout_seconds + } +} + +fn is_quick_tray_detection_app(app: &AppConfig) -> bool { + configured_process_name(app) + .map(|process_name| names_match("OpenLaunchDeck.exe", &process_name)) + .unwrap_or(false) +} + fn window_matches_app(window: &WindowInfo, app: &AppConfig, launched_pid: Option) -> bool { if !window.is_visible && !app.pull_hidden_windows && launched_pid != Some(window.process_id) { return false; @@ -827,7 +921,10 @@ fn window_matches_app(window: &WindowInfo, app: &AppConfig, launched_pid: Option .executable_path .as_ref() .zip(window.executable_path.as_ref()) - .map(|(expected, actual)| expected.eq_ignore_ascii_case(actual)) + .map(|(expected, actual)| { + expected.eq_ignore_ascii_case(actual) + || processes::same_windows_app_package(expected, actual) + }) .unwrap_or(false); if !process_matches { @@ -984,7 +1081,7 @@ fn resolve_app_monitor( } if matches!( config.global.monitor_missing_behavior, - MonitorMissingBehavior::DoNothing | MonitorMissingBehavior::AskNextOpen + MonitorMissingBehavior::DoNothing ) { return None; } @@ -1012,26 +1109,23 @@ fn resolve_profile_monitor( } return match config.global.monitor_missing_behavior { - MonitorMissingBehavior::DoNothing | MonitorMissingBehavior::AskNextOpen => None, + MonitorMissingBehavior::DoNothing => None, MonitorMissingBehavior::UsePrimary => monitors .iter() .find(|monitor| monitor.is_primary) .cloned() .map(fallback_monitor), - MonitorMissingBehavior::NearestMatch => monitors - .iter() - .find(|monitor| !monitor.is_primary) - .cloned() - .or_else(|| monitors.iter().find(|monitor| monitor.is_primary).cloned()) - .map(fallback_monitor), + MonitorMissingBehavior::NearestMatch => { + nearest_monitor_for_profile(profile, monitors).map(fallback_monitor) + } }; } monitors .iter() - .find(|monitor| !monitor.is_primary) + .find(|monitor| monitor.is_primary) .cloned() - .or_else(|| monitors.iter().find(|monitor| monitor.is_primary).cloned()) + .or_else(|| monitors.first().cloned()) .map(|monitor| MonitorResolution { monitor, is_fallback: false, @@ -1045,12 +1139,63 @@ fn fallback_monitor(monitor: MonitorInfo) -> MonitorResolution { } } +fn restore_layout_for_monitor( + profile: &Profile, + app: &AppConfig, + resolution: &MonitorResolution, +) -> LayoutRect { + let layout = if resolution.is_fallback { + scaled_layout_for_monitor(profile, app, &resolution.monitor) + } else { + app.layout.clone() + }; + keep_layout_visible_on_monitor(&layout, &resolution.monitor) +} + +fn keep_layout_visible_on_monitor(layout: &LayoutRect, monitor: &MonitorInfo) -> LayoutRect { + let monitor_width = monitor.width.max(1); + let monitor_height = monitor.height.max(1); + let width = layout.width.clamp(80.min(monitor_width), monitor_width); + let height = layout.height.clamp(80.min(monitor_height), monitor_height); + let candidate = LayoutRect { + x: layout.x, + y: layout.y, + width, + height, + }; + if layout_has_usable_visible_area(&candidate, monitor) { + return candidate; + } + + let x = layout.x.clamp(0, monitor_width.saturating_sub(width)); + let y = layout.y.clamp(0, monitor_height.saturating_sub(height)); + + LayoutRect { + x, + y, + width, + height, + } +} + +fn layout_has_usable_visible_area(layout: &LayoutRect, monitor: &MonitorInfo) -> bool { + let right = layout.x.saturating_add(layout.width); + let bottom = layout.y.saturating_add(layout.height); + let visible_width = right.min(monitor.width).saturating_sub(layout.x.max(0)); + let visible_height = bottom.min(monitor.height).saturating_sub(layout.y.max(0)); + let min_visible_width = layout.width.min(80); + let min_visible_height = layout.height.min(80); + + visible_width >= min_visible_width && visible_height >= min_visible_height +} + fn scaled_layout_for_monitor( profile: &Profile, app: &AppConfig, monitor: &MonitorInfo, ) -> LayoutRect { - let Some((canvas_width, canvas_height)) = profile_layout_canvas(profile) else { + let Some((canvas_x, canvas_y, canvas_width, canvas_height)) = profile_layout_canvas(profile) + else { return app.layout.clone(); }; if canvas_width <= 0 || canvas_height <= 0 || monitor.width <= 0 || monitor.height <= 0 { @@ -1059,8 +1204,10 @@ fn scaled_layout_for_monitor( let scale_x = monitor.width as f64 / canvas_width as f64; let scale_y = monitor.height as f64 / canvas_height as f64; - let x = scale_i32(app.layout.x, scale_x).clamp(0, monitor.width.saturating_sub(1)); - let y = scale_i32(app.layout.y, scale_y).clamp(0, monitor.height.saturating_sub(1)); + let x = scale_i32(app.layout.x.saturating_sub(canvas_x), scale_x) + .clamp(0, monitor.width.saturating_sub(1)); + let y = scale_i32(app.layout.y.saturating_sub(canvas_y), scale_y) + .clamp(0, monitor.height.saturating_sub(1)); let available_width = (monitor.width - x).max(1); let available_height = (monitor.height - y).max(1); let width = @@ -1076,7 +1223,9 @@ fn scaled_layout_for_monitor( } } -fn profile_layout_canvas(profile: &Profile) -> Option<(i32, i32)> { +fn profile_layout_canvas(profile: &Profile) -> Option<(i32, i32, i32, i32)> { + let left = profile.apps.iter().map(|app| app.layout.x).min()?; + let top = profile.apps.iter().map(|app| app.layout.y).min()?; let right = profile .apps .iter() @@ -1087,7 +1236,31 @@ fn profile_layout_canvas(profile: &Profile) -> Option<(i32, i32)> { .iter() .map(|app| app.layout.y.saturating_add(app.layout.height)) .max()?; - Some((right.max(1), bottom.max(1))) + Some(( + left, + top, + right.saturating_sub(left).max(1), + bottom.saturating_sub(top).max(1), + )) +} + +fn nearest_monitor_for_profile(profile: &Profile, monitors: &[MonitorInfo]) -> Option { + let Some((_, _, canvas_width, canvas_height)) = profile_layout_canvas(profile) else { + return monitors + .iter() + .find(|monitor| monitor.is_primary) + .cloned() + .or_else(|| monitors.first().cloned()); + }; + monitors + .iter() + .min_by_key(|monitor| { + let width_delta = i64::from(monitor.width).abs_diff(i64::from(canvas_width)); + let height_delta = i64::from(monitor.height).abs_diff(i64::from(canvas_height)); + (width_delta.saturating_add(height_delta), monitor.is_primary) + }) + .cloned() + .or_else(|| monitors.first().cloned()) } fn scale_i32(value: i32, scale: f64) -> i32 { @@ -1109,6 +1282,32 @@ fn app_result( } } +fn move_failed_result( + config_dir: &Path, + profile: &Profile, + app: &AppConfig, + matched: Vec, + error: AppError, + log_events: bool, +) -> AppRestoreResult { + let message = error.to_string(); + let status = if message.to_ascii_lowercase().contains("access") { + AppRestoreStatus::PermissionDenied + } else { + AppRestoreStatus::MoveFailed + }; + if log_events { + let _ = logging::append( + config_dir, + LogSeverity::Error, + Some(&profile.name), + Some(&app.display_name), + &message, + ); + } + app_result(app, status, message, matched) +} + #[cfg(test)] mod tests { use super::*; @@ -1149,7 +1348,6 @@ mod tests { launch_delay_seconds: 0, detection_timeout_seconds: 1, retry_interval_ms: 100, - launch_if_missing: false, move_if_running: true, force_resize: true, apply_to_all_matching_windows: false, @@ -1173,6 +1371,7 @@ mod tests { height: 100, is_visible: true, is_minimized: false, + is_maximized: false, }; assert!(!window_matches_app(&window, &app, None)); @@ -1197,6 +1396,7 @@ mod tests { height: 100, is_visible: false, is_minimized: false, + is_maximized: false, }; assert!(window_matches_app(&window, &app, None)); @@ -1220,6 +1420,7 @@ mod tests { height: 100, is_visible: true, is_minimized: false, + is_maximized: false, }; assert!(!should_show_matched_windows(&app, &[window])); @@ -1242,6 +1443,7 @@ mod tests { height: 100, is_visible: false, is_minimized: false, + is_maximized: false, }; assert!(should_restore_through_qt_tray(&app, &[window.clone()])); @@ -1251,6 +1453,23 @@ mod tests { assert!(!should_restore_through_qt_tray(&app, &[window])); } + #[test] + fn caps_openlaunchdeck_launch_detection_timeout() { + let mut openlaunchdeck = AppConfig::new_preset( + "openlaunchdeck", + "OpenLaunchDeck", + "OpenLaunchDeck.exe", + LayoutRect::default(), + ); + openlaunchdeck.detection_timeout_seconds = 25; + assert_eq!(launch_detection_timeout_seconds(&openlaunchdeck), 5); + + let mut obs = + AppConfig::new_preset("obs", "OBS Studio", "obs64.exe", LayoutRect::default()); + obs.detection_timeout_seconds = 25; + assert_eq!(launch_detection_timeout_seconds(&obs), 25); + } + #[test] fn rejects_hidden_window_when_pull_is_disabled() { let mut app = @@ -1270,6 +1489,7 @@ mod tests { height: 100, is_visible: false, is_minimized: false, + is_maximized: false, }; assert!(!window_matches_app(&window, &app, None)); @@ -1294,6 +1514,7 @@ mod tests { height: 800, is_visible: true, is_minimized: false, + is_maximized: false, }; assert!(window_matches_app(&window, &app, None)); @@ -1318,6 +1539,7 @@ mod tests { height: 500, is_visible: true, is_minimized: false, + is_maximized: false, }; assert!(!window_matches_app(&window, &app, None)); @@ -1346,6 +1568,7 @@ mod tests { height: 500, is_visible: true, is_minimized: false, + is_maximized: false, }; assert!(window_matches_app(&window, &app, None)); @@ -1393,6 +1616,7 @@ mod tests { height: 719, is_visible: true, is_minimized: false, + is_maximized: false, }; assert!(window_layout_is_current( @@ -1416,7 +1640,7 @@ mod tests { } #[test] - fn missing_profile_monitor_uses_secondary_nearest_match() { + fn missing_profile_monitor_uses_closest_resolution() { let mut config = WindowAutoLayoutConfig::default(); config.global.monitor_missing_behavior = MonitorMissingBehavior::NearestMatch; config.profiles[0].target_monitor_id = Some("missing-display".into()); @@ -1428,10 +1652,31 @@ mod tests { let resolved = resolve_profile_monitor(&config, &config.profiles[0], &monitors) .expect("fallback monitor"); - assert_eq!(resolved.monitor.id, "secondary"); + assert_eq!(resolved.monitor.id, "primary"); assert!(resolved.is_fallback); } + #[test] + fn nearest_monitor_prefers_matching_profile_canvas() { + let mut profile = WindowAutoLayoutConfig::default().profiles.remove(0); + profile.apps[0].layout = LayoutRect { + x: 0, + y: 0, + width: 2560, + height: 1440, + }; + profile.apps.truncate(1); + let monitors = vec![ + test_monitor("primary", true, 0, 0, 1920, 1080), + test_monitor("portrait", false, 1920, 0, 1080, 1920), + test_monitor("matching", false, -2560, 0, 2560, 1440), + ]; + + let resolved = nearest_monitor_for_profile(&profile, &monitors).expect("nearest monitor"); + + assert_eq!(resolved.id, "matching"); + } + #[test] fn fallback_layout_scales_profile_canvas_to_target_monitor() { let monitor = test_monitor("secondary", false, -3072, -261, 2560, 1440); @@ -1475,8 +1720,6 @@ mod tests { }, ), ], - startup_restore: true, - enforce_after_restore: true, }; let editor = profile.apps.pop().expect("editor app"); @@ -1494,56 +1737,124 @@ mod tests { } #[test] - fn profile_signature_changes_when_tracked_window_moves_or_minimizes() { - let profile = Profile { - id: "profile".into(), - name: "Streaming".into(), - description: None, - target_monitor_id: None, - apps: vec![AppConfig::new_preset( - "discord", - "Discord", - "Discord.exe", - LayoutRect::default(), - )], - startup_restore: true, - enforce_after_restore: true, + fn keeps_exact_layout_when_it_still_intersects_monitor() { + let monitor = test_monitor("display", true, 0, 0, 1920, 1080); + let layout = LayoutRect { + x: -20, + y: 10, + width: 800, + height: 600, }; - let window = WindowInfo { - handle: "0x1".into(), - title: "Discord".into(), - class_name: "Chrome_WidgetWin_1".into(), - process_id: 10, - process_name: "Discord.exe".into(), - executable_path: None, - monitor_id: None, - x: 0, - y: 0, - width: 1000, + + assert_eq!(keep_layout_visible_on_monitor(&layout, &monitor), layout); + } + + #[test] + fn clamps_layout_back_when_saved_bounds_miss_target_monitor() { + let monitor = test_monitor("display", true, 0, 0, 1920, 1080); + let layout = LayoutRect { + x: 2400, + y: 1300, + width: 900, height: 700, - is_visible: true, - is_minimized: false, }; - let moved = WindowInfo { - x: 20, - ..window.clone() + + assert_eq!( + keep_layout_visible_on_monitor(&layout, &monitor), + LayoutRect { + x: 1020, + y: 380, + width: 900, + height: 700, + } + ); + } + + #[test] + fn clamps_layout_back_when_only_a_tiny_edge_is_visible() { + let monitor = test_monitor("display", true, 0, 0, 1920, 1080); + let layout = LayoutRect { + x: 1870, + y: 20, + width: 900, + height: 700, }; - let minimized = WindowInfo { - is_minimized: true, - ..window.clone() + + assert_eq!( + keep_layout_visible_on_monitor(&layout, &monitor), + LayoutRect { + x: 1020, + y: 20, + width: 900, + height: 700, + } + ); + } + + #[test] + fn clamps_oversized_layout_to_current_monitor_resolution() { + let monitor = test_monitor("display", true, 0, 0, 1920, 1080); + let layout = LayoutRect { + x: 0, + y: 0, + width: 3840, + height: 2160, }; - let base = profile_window_signature_from_windows(&profile, &[window]); - assert_ne!( - base, - profile_window_signature_from_windows(&profile, &[moved]) + assert_eq!( + keep_layout_visible_on_monitor(&layout, &monitor), + LayoutRect { + x: 0, + y: 0, + width: 1920, + height: 1080, + } + ); + } + + #[test] + fn fallback_scaling_accounts_for_negative_saved_offsets() { + let monitor = test_monitor("display", true, 0, 0, 1000, 500); + let app = AppConfig::new_preset( + "editor", + "Editor", + "Editor.exe", + LayoutRect { + x: -100, + y: -50, + width: 1000, + height: 500, + }, ); - assert_ne!( - base, - profile_window_signature_from_windows(&profile, &[minimized]) + let profile = Profile { + id: "profile".into(), + name: "Profile".into(), + description: None, + target_monitor_id: None, + apps: vec![app.clone()], + }; + + assert_eq!( + scaled_layout_for_monitor(&profile, &app, &monitor), + LayoutRect { + x: 0, + y: 0, + width: 1000, + height: 500, + } ); } + #[test] + fn paused_restore_has_an_explicit_non_success_status() { + let profile = WindowAutoLayoutConfig::default().profiles.remove(0); + + let result = paused_restore_result(profile, Utc::now()); + + assert_eq!(result.status, RestoreStatus::Paused); + assert!(result.results.is_empty()); + } + fn test_monitor( id: &str, is_primary: bool, diff --git a/src-tauri/src/single_instance.rs b/src-tauri/src/single_instance.rs new file mode 100644 index 0000000..f3ca7af --- /dev/null +++ b/src-tauri/src/single_instance.rs @@ -0,0 +1,92 @@ +use std::{ffi::c_void, thread}; + +use tauri::AppHandle; +use windows::{ + core::w, + Win32::{ + Foundation::{CloseHandle, GetLastError, ERROR_ALREADY_EXISTS, HANDLE, WAIT_OBJECT_0}, + System::Threading::{CreateEventW, CreateMutexW, SetEvent, WaitForSingleObject}, + }, +}; + +use crate::performance; + +pub struct SingleInstanceGuard { + mutex: HANDLE, + activation_event: Option, +} + +pub fn acquire() -> Option { + let handle = unsafe { CreateMutexW(None, true, w!("Local\\WindowAutoLayout")) }.ok()?; + if unsafe { GetLastError() } == ERROR_ALREADY_EXISTS { + signal_existing_instance(); + unsafe { + let _ = CloseHandle(handle); + } + return None; + } + + let activation_event = unsafe { + CreateEventW( + None, + false, + false, + w!("Local\\WindowAutoLayout.ShowMainWindow"), + ) + .ok() + }; + Some(SingleInstanceGuard { + mutex: handle, + activation_event, + }) +} + +impl SingleInstanceGuard { + pub fn activation_event_address(&self) -> Option { + self.activation_event.map(|event| event.0 as usize) + } +} + +pub fn start_activation_listener(event_address: usize, app: AppHandle) -> std::io::Result<()> { + thread::Builder::new() + .name("windowautolayout-activation".into()) + .spawn(move || { + performance::lower_current_thread_priority(); + let event = HANDLE(event_address as *mut c_void); + loop { + if unsafe { WaitForSingleObject(event, u32::MAX) } != WAIT_OBJECT_0 { + break; + } + crate::show_main_window(&app); + } + }) + .map(|_| ()) +} + +fn signal_existing_instance() { + let Ok(event) = (unsafe { + CreateEventW( + None, + false, + false, + w!("Local\\WindowAutoLayout.ShowMainWindow"), + ) + }) else { + return; + }; + unsafe { + let _ = SetEvent(event); + let _ = CloseHandle(event); + } +} + +impl Drop for SingleInstanceGuard { + fn drop(&mut self) { + unsafe { + if let Some(event) = self.activation_event { + let _ = CloseHandle(event); + } + let _ = CloseHandle(self.mutex); + } + } +} diff --git a/src-tauri/src/window_actions.rs b/src-tauri/src/window_actions.rs index e0a74b6..8b5de48 100644 --- a/src-tauri/src/window_actions.rs +++ b/src-tauri/src/window_actions.rs @@ -1,17 +1,21 @@ -use std::{thread, time::Duration}; +use std::{ffi::c_void, thread, time::Duration}; use windows::{ core::BOOL, Win32::{ Foundation::{GetLastError, HWND, LPARAM, RECT, WPARAM}, - Graphics::Gdi::{ - RedrawWindow, UpdateWindow, RDW_ALLCHILDREN, RDW_FRAME, RDW_INVALIDATE, RDW_UPDATENOW, + Graphics::{ + Dwm::{DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS}, + Gdi::{ + RedrawWindow, UpdateWindow, RDW_ALLCHILDREN, RDW_FRAME, RDW_INVALIDATE, + RDW_UPDATENOW, + }, }, UI::WindowsAndMessaging::{ - BringWindowToTop, EnumWindows, GetClassNameW, GetWindowTextW, GetWindowThreadProcessId, - IsIconic, PostMessageW, SetForegroundWindow, SetWindowPos, ShowWindow, HWND_TOP, - SWP_NOACTIVATE, SWP_NOZORDER, SWP_SHOWWINDOW, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, - SW_SHOW, WM_APP, + BringWindowToTop, EnumWindows, GetClassNameW, GetWindowRect, GetWindowTextW, + GetWindowThreadProcessId, IsIconic, IsZoomed, PostMessageW, SetForegroundWindow, + SetWindowPos, ShowWindow, HWND_TOP, SWP_NOACTIVATE, SWP_NOZORDER, SWP_SHOWWINDOW, + SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOW, WM_APP, }, }, }; @@ -34,18 +38,26 @@ pub fn apply_layout( ) -> AppResult<()> { let should_show = pull_hidden_window || (restore_if_minimized && unsafe { IsIconic(hwnd).as_bool() }); + let should_unmaximize = + !matches!(state, WindowStatePreference::Minimized) && unsafe { IsZoomed(hwnd).as_bool() }; if should_show { - show_window_for_restore(hwnd); + show_window_for_restore(hwnd, activate_after_show); + } else if should_unmaximize { + unsafe { + let _ = ShowWindow(hwnd, SW_RESTORE); + } + thread::sleep(Duration::from_millis(120)); } - let rect = absolute_rect(monitor, layout); + let frame_rect = absolute_rect(monitor, layout); + let window_rect = rect_for_set_window_pos(hwnd, frame_rect); let width = if force_resize { - rect.right - rect.left + window_rect.right - window_rect.left } else { 0 }; let height = if force_resize { - rect.bottom - rect.top + window_rect.bottom - window_rect.top } else { 0 }; @@ -61,8 +73,8 @@ pub fn apply_layout( SetWindowPos( hwnd, Some(HWND_TOP), - rect.left, - rect.top, + window_rect.left, + window_rect.top, width, height, flags, @@ -78,9 +90,7 @@ pub fn apply_layout( unsafe { match state { - WindowStatePreference::Normal => { - let _ = ShowWindow(hwnd, SW_RESTORE); - } + WindowStatePreference::Normal => {} WindowStatePreference::Maximized => { let _ = ShowWindow(hwnd, SW_MAXIMIZE); } @@ -91,19 +101,19 @@ pub fn apply_layout( } if activate_after_show { - wake_painted_window(hwnd); + wake_painted_window(hwnd, true); } Ok(()) } -pub fn show_window_for_restore(hwnd: HWND) { +pub fn show_window_for_restore(hwnd: HWND, activate: bool) { unsafe { let _ = ShowWindow(hwnd, SW_RESTORE); let _ = ShowWindow(hwnd, SW_SHOW); } thread::sleep(Duration::from_millis(120)); - wake_painted_window(hwnd); + wake_painted_window(hwnd, activate); } pub fn activate_qt_tray_icon_for_process(process_id: u32) -> bool { @@ -132,10 +142,12 @@ pub fn activate_qt_tray_icon_for_process(process_id: u32) -> bool { sent } -fn wake_painted_window(hwnd: HWND) { +fn wake_painted_window(hwnd: HWND, activate: bool) { unsafe { - let _ = BringWindowToTop(hwnd); - let _ = SetForegroundWindow(hwnd); + if activate { + let _ = BringWindowToTop(hwnd); + let _ = SetForegroundWindow(hwnd); + } let _ = RedrawWindow( Some(hwnd), None, @@ -203,6 +215,76 @@ fn nin_select_message() -> u32 { 0x0400 } +fn rect_for_set_window_pos(hwnd: HWND, target_frame_rect: RECT) -> RECT { + window_frame_margins(hwnd) + .map(|margins| adjust_rect_for_frame_margins(target_frame_rect, margins)) + .unwrap_or(target_frame_rect) +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct FrameMargins { + left: i32, + top: i32, + right: i32, + bottom: i32, +} + +fn window_frame_margins(hwnd: HWND) -> Option { + let mut outer = RECT::default(); + let outer_ok = unsafe { GetWindowRect(hwnd, &mut outer) }; + if outer_ok.is_err() { + return None; + } + + let mut frame = RECT::default(); + let frame_ok = unsafe { + DwmGetWindowAttribute( + hwnd, + DWMWA_EXTENDED_FRAME_BOUNDS, + &mut frame as *mut RECT as *mut c_void, + std::mem::size_of::() as u32, + ) + }; + if frame_ok.is_err() { + return None; + } + + if outer.right <= outer.left + || outer.bottom <= outer.top + || frame.right <= frame.left + || frame.bottom <= frame.top + { + return None; + } + + let margins = FrameMargins { + left: frame.left - outer.left, + top: frame.top - outer.top, + right: outer.right - frame.right, + bottom: outer.bottom - frame.bottom, + }; + let values = [margins.left, margins.top, margins.right, margins.bottom]; + if values + .iter() + .any(|value| *value < 0 || *value > MAX_FRAME_MARGIN_PX) + { + return None; + } + + Some(margins) +} + +const MAX_FRAME_MARGIN_PX: i32 = 128; + +fn adjust_rect_for_frame_margins(target_frame_rect: RECT, margins: FrameMargins) -> RECT { + RECT { + left: target_frame_rect.left - margins.left, + top: target_frame_rect.top - margins.top, + right: target_frame_rect.right + margins.right, + bottom: target_frame_rect.bottom + margins.bottom, + } +} + pub fn absolute_rect(monitor: &MonitorInfo, layout: &LayoutRect) -> RECT { RECT { left: monitor.x + layout.x, @@ -253,4 +335,28 @@ mod tests { assert_eq!(rect.left, -1820); assert_eq!(relative_rect(&monitor, rect), layout); } + + #[test] + fn adjusts_saved_frame_rect_to_outer_window_rect() { + let target = RECT { + left: -3061, + top: -244, + right: -1167, + bottom: 815, + }; + let adjusted = adjust_rect_for_frame_margins( + target, + FrameMargins { + left: 9, + top: 0, + right: 9, + bottom: 9, + }, + ); + + assert_eq!(adjusted.left, -3070); + assert_eq!(adjusted.top, -244); + assert_eq!(adjusted.right, -1158); + assert_eq!(adjusted.bottom, 824); + } } diff --git a/src-tauri/src/windows_enum.rs b/src-tauri/src/windows_enum.rs index 1b37878..d90c175 100644 --- a/src-tauri/src/windows_enum.rs +++ b/src-tauri/src/windows_enum.rs @@ -1,4 +1,4 @@ -use std::ffi::c_void; +use std::{collections::HashMap, ffi::c_void}; use windows::{ core::BOOL, @@ -7,7 +7,7 @@ use windows::{ Graphics::Dwm::{DwmGetWindowAttribute, DWMWA_EXTENDED_FRAME_BOUNDS}, UI::WindowsAndMessaging::{ EnumWindows, GetClassNameW, GetForegroundWindow, GetWindowRect, GetWindowTextLengthW, - GetWindowTextW, GetWindowThreadProcessId, IsIconic, IsWindowVisible, + GetWindowTextW, GetWindowThreadProcessId, IsIconic, IsWindowVisible, IsZoomed, }, }, }; @@ -15,15 +15,28 @@ use windows::{ use crate::{ errors::{AppError, AppResult}, models::WindowInfo, - monitors, - processes::{query_process_name, query_process_path}, + monitors, processes, }; pub fn list_windows_with_hidden(include_hidden: bool) -> AppResult> { + list_windows_with_options(include_hidden, true) +} + +fn list_windows_with_options( + include_hidden: bool, + include_executable_path: bool, +) -> AppResult> { let mut windows: Vec = Vec::new(); + let process_names = processes::list_processes() + .unwrap_or_default() + .into_iter() + .map(|process| (process.pid, process.name)) + .collect::>(); let mut context = EnumWindowsContext { windows: &mut windows, + process_names: &process_names, include_hidden, + include_executable_path, }; let lparam = LPARAM(&mut context as *mut EnumWindowsContext as isize); let ok = unsafe { EnumWindows(Some(enum_window_proc), lparam) }; @@ -41,21 +54,36 @@ pub fn list_windows_with_hidden(include_hidden: bool) -> AppResult Option { let hwnd = unsafe { GetForegroundWindow() }; - window_info_from_handle(hwnd) + window_info_from_handle_lightweight(hwnd) } struct EnumWindowsContext<'a> { windows: &'a mut Vec, + process_names: &'a HashMap, include_hidden: bool, + include_executable_path: bool, } pub fn window_info_from_handle(hwnd: HWND) -> Option { + window_info_from_handle_with_cache(hwnd, None, true) +} + +pub fn window_info_from_handle_lightweight(hwnd: HWND) -> Option { + window_info_from_handle_with_cache(hwnd, None, false) +} + +fn window_info_from_handle_with_cache( + hwnd: HWND, + process_names: Option<&HashMap>, + include_executable_path: bool, +) -> Option { if hwnd.0.is_null() { return None; } let visible = unsafe { IsWindowVisible(hwnd).as_bool() }; let minimized = unsafe { IsIconic(hwnd).as_bool() }; + let maximized = unsafe { IsZoomed(hwnd).as_bool() }; let rect = window_rect(hwnd)?; let width = rect.right - rect.left; let height = rect.bottom - rect.top; @@ -70,8 +98,19 @@ pub fn window_info_from_handle(hwnd: HWND) -> Option { let title = window_text(hwnd); let class_name = class_name(hwnd); - let process_name = query_process_name(pid); - let executable_path = query_process_path(pid); + let executable_path = if include_executable_path { + processes::query_process_path(pid) + } else { + None + }; + let process_name = process_names + .and_then(|names| names.get(&pid).cloned()) + .or_else(|| { + executable_path + .as_deref() + .and_then(processes::file_name_from_path) + }) + .unwrap_or_else(|| processes::query_process_name(pid)); let monitor_id = monitors::monitor_for_rect(rect).map(|monitor| monitor.id); Some(WindowInfo { @@ -88,6 +127,7 @@ pub fn window_info_from_handle(hwnd: HWND) -> Option { height, is_visible: visible, is_minimized: minimized, + is_maximized: maximized, }) } @@ -108,7 +148,11 @@ pub fn handle_to_string(hwnd: HWND) -> String { unsafe extern "system" fn enum_window_proc(hwnd: HWND, lparam: LPARAM) -> BOOL { let context = &mut *(lparam.0 as *mut EnumWindowsContext); - if let Some(info) = window_info_from_handle(hwnd) { + if let Some(info) = window_info_from_handle_with_cache( + hwnd, + Some(context.process_names), + context.include_executable_path, + ) { if (info.is_visible || context.include_hidden) && !is_shell_or_helper_window(&info) { context.windows.push(info); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 259b340..1cfb177 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": "WindowAutoLayout", - "version": "0.1.18", + "version": "0.1.23", "identifier": "com.rique.windowautolayout", "build": { "beforeDevCommand": "npm run dev", @@ -13,6 +13,7 @@ "windows": [ { "title": "WindowAutoLayout", + "visible": false, "width": 1180, "height": 760, "minWidth": 980, @@ -20,7 +21,16 @@ } ], "security": { - "csp": null + "csp": { + "default-src": "'self' customprotocol: asset:", + "connect-src": "ipc: http://ipc.localhost", + "img-src": "'self' asset: http://asset.localhost data:", + "style-src": "'self' 'unsafe-inline'", + "object-src": "'none'", + "base-uri": "'self'", + "frame-ancestors": "'none'" + }, + "devCsp": null } }, "bundle": { diff --git a/src/App.tsx b/src/App.tsx index e773224..1f9432e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,12 +8,12 @@ import { RefreshCw, Save, Settings, + ShieldCheck, } from "lucide-react"; -import { useCallback, useEffect, useMemo, useState } from "react"; -import { register, unregisterAll } from "@tauri-apps/plugin-global-shortcut"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { clsx } from "clsx"; -import { api, isTauriRuntime } from "./lib/api"; -import { activeProfile, patchProfile, resolveProfileMonitor } from "./lib/helpers"; +import { api } from "./lib/api"; +import { activeProfile, patchProfile, resolveProfileMonitor, statusText } from "./lib/helpers"; import type { AppConfig, LogEntry, @@ -60,6 +60,7 @@ export default function App() { const [message, setMessage] = useState(null); const [layoutLocked, setLayoutLocked] = useState(false); const [captureMonitorId, setCaptureMonitorId] = useState(null); + const workspaceContentRef = useRef(null); const profile = useMemo(() => (config ? activeProfile(config, selectedProfileId) : null), [config, selectedProfileId]); const effectiveCaptureMonitorId = useMemo(() => { @@ -92,8 +93,11 @@ export default function App() { setLogPath(nextLogPath); setValidation(nextValidation); setLayoutLocked(nextLayoutLocked); - setSelectedProfileId((current) => current ?? nextConfig.startup.defaultProfileId ?? nextConfig.profiles[0]?.id ?? null); - setSelectedAppId((current) => current ?? nextConfig.profiles[0]?.apps[0]?.id ?? null); + setSelectedProfileId((current) => + current && nextConfig.profiles.some((item) => item.id === current) + ? current + : nextConfig.startup.defaultProfileId ?? nextConfig.profiles[0]?.id ?? null, + ); setCaptureMonitorId((current) => { if (current && nextMonitors.some((monitor) => monitor.id === current)) return current; const nextProfile = activeProfile(nextConfig, nextConfig.startup.defaultProfileId ?? nextConfig.profiles[0]?.id ?? null); @@ -106,6 +110,21 @@ export default function App() { refresh().catch((error) => setMessage(String(error))); }, [refresh]); + useEffect(() => { + if (!profile) return; + setSelectedProfileId((current) => (current === profile.id ? current : profile.id)); + setSelectedAppId((current) => + current && profile.apps.some((app) => app.id === current) + ? current + : profile.apps[0]?.id ?? null, + ); + }, [profile]); + + useEffect(() => { + workspaceContentRef.current?.scrollTo({ top: 0, left: 0 }); + window.scrollTo({ top: 0, left: 0 }); + }, [page]); + const restoreSelected = useCallback(async () => { if (!config || !profile) return; setBusy(true); @@ -116,7 +135,7 @@ export default function App() { const result = await api.restoreProfile(profile.id, true); setLastRestore(result); setLogs(await api.logs()); - setMessage(`Restore finished: ${result.status}`); + setMessage(`Restore finished: ${statusText(result.status)}`); } catch (error) { setMessage(String(error)); } finally { @@ -124,28 +143,6 @@ export default function App() { } }, [config, dirty, profile]); - useEffect(() => { - if (!config?.hotkey.enabled || !config.hotkey.accelerator.trim()) { - if (isTauriRuntime) { - unregisterAll().catch(() => undefined); - } - return; - } - - if (!isTauriRuntime) { - return; - } - - const accelerator = normalizeAccelerator(config.hotkey.accelerator); - unregisterAll() - .then(() => register(accelerator, () => restoreSelected())) - .catch((error) => setMessage(`Hotkey registration failed: ${String(error)}`)); - - return () => { - unregisterAll().catch(() => undefined); - }; - }, [config?.hotkey.enabled, config?.hotkey.accelerator, restoreSelected]); - function updateConfig(next: WindowAutoLayoutConfig) { setConfig(next); setDirty(true); @@ -189,7 +186,16 @@ export default function App() { const saved = dirty ? await api.saveConfig(config) : config; setConfig(saved); setDirty(false); - const enabled = await api.setLayoutLock(!layoutLocked, profile.id); + const enabling = !layoutLocked; + if (enabling) { + const result = await api.restoreProfile(profile.id, true); + setLastRestore(result); + if (["paused", "failed", "monitorMissing"].includes(result.status)) { + setMessage(`Layout lock not enabled: ${statusText(result.status)}`); + return; + } + } + const enabled = await api.setLayoutLock(enabling, profile.id); setConfig({ ...saved, enforcement: { ...saved.enforcement, enabled, profileId: profile.id } }); setLayoutLocked(enabled); setLogs(await api.logs()); @@ -250,11 +256,22 @@ export default function App() { setValidation(nextValidation); } + function refreshFromUi() { + if (dirty) { + setMessage("Save your changes before refreshing"); + return; + } + setBusy(true); + refresh() + .catch((error) => setMessage(String(error))) + .finally(() => setBusy(false)); + } + if (!config || !profile) { return (
-
- +
+ Loading WindowAutoLayout
@@ -263,63 +280,64 @@ export default function App() { return (
-
-
); } - -function normalizeAccelerator(accelerator: string) { - return accelerator - .replace(/\bCtrl\b/gi, "CommandOrControl") - .replace(/\bControl\b/gi, "CommandOrControl") - .replace(/\s+/g, ""); -} diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..6092aa5 --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,44 @@ +import { AlertTriangle, RotateCcw } from "lucide-react"; +import { Component, type ErrorInfo, type ReactNode } from "react"; + +interface ErrorBoundaryProps { + children: ReactNode; +} + +interface ErrorBoundaryState { + failed: boolean; +} + +export class ErrorBoundary extends Component { + state: ErrorBoundaryState = { failed: false }; + + static getDerivedStateFromError(): ErrorBoundaryState { + return { failed: true }; + } + + componentDidCatch(error: Error, info: ErrorInfo) { + console.error("WindowAutoLayout interface error", error, info.componentStack); + } + + render() { + if (!this.state.failed) return this.props.children; + + return ( +
+
+ +
+

Interface recovery

+

+ WindowAutoLayout is still running. Reload the interface to reconnect. +

+
+ +
+
+ ); + } +} diff --git a/src/components/Form.tsx b/src/components/Form.tsx index 975e723..b12c9cb 100644 --- a/src/components/Form.tsx +++ b/src/components/Form.tsx @@ -2,8 +2,8 @@ import type { InputHTMLAttributes, ReactNode, SelectHTMLAttributes, TextareaHTML export function Field({ label, children }: { label: string; children: ReactNode }) { return ( -