From 1f06ada9d20a8c1b8f7be68996eb0207d8af821d Mon Sep 17 00:00:00 2001 From: cloudwithax Date: Sat, 14 Feb 2026 19:54:55 -0500 Subject: [PATCH] started implementing core features (profiles, dms, servers, text/voice, settings, etc) added icons and branding --- bun.lock | 3 + package.json | 1 + src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 5 + src-tauri/icons/128x128.png | Bin 3512 -> 1621 bytes src-tauri/icons/128x128@2x.png | Bin 7012 -> 3051 bytes src-tauri/icons/32x32.png | Bin 974 -> 417 bytes src-tauri/icons/64x64.png | Bin 0 -> 836 bytes src-tauri/icons/Square107x107Logo.png | Bin 2863 -> 1319 bytes src-tauri/icons/Square142x142Logo.png | Bin 3858 -> 1727 bytes src-tauri/icons/Square150x150Logo.png | Bin 3966 -> 1785 bytes src-tauri/icons/Square284x284Logo.png | Bin 7737 -> 3383 bytes src-tauri/icons/Square30x30Logo.png | Bin 903 -> 390 bytes src-tauri/icons/Square310x310Logo.png | Bin 8591 -> 3641 bytes src-tauri/icons/Square44x44Logo.png | Bin 1299 -> 596 bytes src-tauri/icons/Square71x71Logo.png | Bin 2011 -> 880 bytes src-tauri/icons/Square89x89Logo.png | Bin 2468 -> 1060 bytes src-tauri/icons/StoreLogo.png | Bin 1523 -> 666 bytes .../android/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../icons/android/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1041 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 1941 bytes .../android/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 1174 bytes .../icons/android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1030 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 1301 bytes .../android/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 1147 bytes .../android/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2034 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 2576 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 2351 bytes .../android/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3175 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 3811 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 3778 bytes .../android/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 4481 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 5162 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 4938 bytes .../android/values/ic_launcher_background.xml | 4 + src-tauri/icons/icon.icns | Bin 98451 -> 38476 bytes src-tauri/icons/icon.ico | Bin 86642 -> 6314 bytes src-tauri/icons/icon.png | Bin 14183 -> 6261 bytes src-tauri/icons/ios/AppIcon-20x20@1x.png | Bin 0 -> 330 bytes src-tauri/icons/ios/AppIcon-20x20@2x-1.png | Bin 0 -> 550 bytes src-tauri/icons/ios/AppIcon-20x20@2x.png | Bin 0 -> 550 bytes src-tauri/icons/ios/AppIcon-20x20@3x.png | Bin 0 -> 748 bytes src-tauri/icons/ios/AppIcon-29x29@1x.png | Bin 0 -> 397 bytes src-tauri/icons/ios/AppIcon-29x29@2x-1.png | Bin 0 -> 742 bytes src-tauri/icons/ios/AppIcon-29x29@2x.png | Bin 0 -> 742 bytes src-tauri/icons/ios/AppIcon-29x29@3x.png | Bin 0 -> 1070 bytes src-tauri/icons/ios/AppIcon-40x40@1x.png | Bin 0 -> 550 bytes src-tauri/icons/ios/AppIcon-40x40@2x-1.png | Bin 0 -> 978 bytes src-tauri/icons/ios/AppIcon-40x40@2x.png | Bin 0 -> 978 bytes src-tauri/icons/ios/AppIcon-40x40@3x.png | Bin 0 -> 1427 bytes src-tauri/icons/ios/AppIcon-512@2x.png | Bin 0 -> 15040 bytes src-tauri/icons/ios/AppIcon-60x60@2x.png | Bin 0 -> 1427 bytes src-tauri/icons/ios/AppIcon-60x60@3x.png | Bin 0 -> 2257 bytes src-tauri/icons/ios/AppIcon-76x76@1x.png | Bin 0 -> 918 bytes src-tauri/icons/ios/AppIcon-76x76@2x.png | Bin 0 -> 1862 bytes src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 2039 bytes src-tauri/src/commands/chat.rs | 70 +- src-tauri/src/commands/community.rs | 93 ++- src-tauri/src/commands/dm.rs | 312 ++++++++ src-tauri/src/commands/identity.rs | 83 +- src-tauri/src/commands/mod.rs | 2 + src-tauri/src/commands/voice.rs | 268 +++++++ src-tauri/src/crdt/document.rs | 168 ++++- src-tauri/src/crdt/mod.rs | 46 +- src-tauri/src/lib.rs | 45 ++ src-tauri/src/node/gossip.rs | 39 + src-tauri/src/node/mod.rs | 278 ++++++- src-tauri/src/node/swarm.rs | 7 +- src-tauri/src/protocol/community.rs | 12 + src-tauri/src/protocol/identity.rs | 16 + src-tauri/src/protocol/messages.rs | 99 ++- src-tauri/src/storage/disk.rs | 155 +++- src-tauri/src/verification/mod.rs | 436 +++++++++++ src/App.tsx | 425 +++++++++-- src/assets/crescent-moon.svg | 8 + src/components/auth/HumanVerification.tsx | 539 +++++++++++++ src/components/auth/SignUpScreen.tsx | 260 +++---- src/components/auth/SplashScreen.tsx | 234 ++++++ src/components/chat/Message.tsx | 32 +- src/components/chat/MessageList.tsx | 2 +- src/components/common/ProfileCard.tsx | 319 ++++++++ src/components/common/ProfileModal.tsx | 464 ++++++++++++ src/components/common/SidebarLayout.tsx | 4 + .../directory/UserDirectoryModal.tsx | 10 +- src/components/layout/AppLayout.tsx | 190 ++--- src/components/layout/ChannelList.tsx | 547 +++++++++++--- src/components/layout/ChatArea.tsx | 4 +- src/components/layout/DMChatArea.tsx | 62 +- src/components/layout/DMSidebar.tsx | 43 +- src/components/layout/HomeView.tsx | 82 +- src/components/layout/UserSidebar.tsx | 39 +- src/components/voice/VoiceChannel.tsx | 128 ++++ src/components/voice/VoiceControls.tsx | 99 +++ src/components/voice/VoiceParticipantTile.tsx | 99 +++ src/lib/tauri.ts | 154 +++- src/lib/types.ts | 133 +++- src/lib/webrtc.ts | 246 ++++++ src/stores/channels.ts | 23 +- src/stores/connection.ts | 3 + src/stores/dms.ts | 98 ++- src/stores/ui.ts | 39 +- src/stores/voice.ts | 711 ++++++++++++++++++ src/styles/app.css | 198 ++++- 103 files changed, 6797 insertions(+), 546 deletions(-) create mode 100644 src-tauri/icons/64x64.png create mode 100644 src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 src-tauri/icons/android/mipmap-hdpi/ic_launcher.png create mode 100644 src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png create mode 100644 src-tauri/icons/android/mipmap-mdpi/ic_launcher.png create mode 100644 src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png create mode 100644 src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png create mode 100644 src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png create mode 100644 src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png create mode 100644 src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 src-tauri/icons/android/values/ic_launcher_background.xml create mode 100644 src-tauri/icons/ios/AppIcon-20x20@1x.png create mode 100644 src-tauri/icons/ios/AppIcon-20x20@2x-1.png create mode 100644 src-tauri/icons/ios/AppIcon-20x20@2x.png create mode 100644 src-tauri/icons/ios/AppIcon-20x20@3x.png create mode 100644 src-tauri/icons/ios/AppIcon-29x29@1x.png create mode 100644 src-tauri/icons/ios/AppIcon-29x29@2x-1.png create mode 100644 src-tauri/icons/ios/AppIcon-29x29@2x.png create mode 100644 src-tauri/icons/ios/AppIcon-29x29@3x.png create mode 100644 src-tauri/icons/ios/AppIcon-40x40@1x.png create mode 100644 src-tauri/icons/ios/AppIcon-40x40@2x-1.png create mode 100644 src-tauri/icons/ios/AppIcon-40x40@2x.png create mode 100644 src-tauri/icons/ios/AppIcon-40x40@3x.png create mode 100644 src-tauri/icons/ios/AppIcon-512@2x.png create mode 100644 src-tauri/icons/ios/AppIcon-60x60@2x.png create mode 100644 src-tauri/icons/ios/AppIcon-60x60@3x.png create mode 100644 src-tauri/icons/ios/AppIcon-76x76@1x.png create mode 100644 src-tauri/icons/ios/AppIcon-76x76@2x.png create mode 100644 src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png create mode 100644 src-tauri/src/commands/dm.rs create mode 100644 src-tauri/src/commands/voice.rs create mode 100644 src-tauri/src/verification/mod.rs create mode 100644 src/assets/crescent-moon.svg create mode 100644 src/components/auth/HumanVerification.tsx create mode 100644 src/components/auth/SplashScreen.tsx create mode 100644 src/components/common/ProfileCard.tsx create mode 100644 src/components/common/ProfileModal.tsx create mode 100644 src/components/voice/VoiceChannel.tsx create mode 100644 src/components/voice/VoiceControls.tsx create mode 100644 src/components/voice/VoiceParticipantTile.tsx create mode 100644 src/lib/webrtc.ts create mode 100644 src/stores/voice.ts diff --git a/bun.lock b/bun.lock index 3014287..a8b4d5e 100644 --- a/bun.lock +++ b/bun.lock @@ -9,6 +9,7 @@ "@fontsource/space-grotesk": "^5.2.0", "@tauri-apps/api": "^2", "@tauri-apps/plugin-shell": "^2", + "@thisbeyond/solid-dnd": "^0.7.5", "lucide-solid": "^0.469.0", "motion": "^12.0.0", "solid-js": "^1.9.3", @@ -255,6 +256,8 @@ "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.5", "", { "dependencies": { "@tauri-apps/api": "^2.10.1" } }, "sha512-jewtULhiQ7lI7+owCKAjc8tYLJr92U16bPOeAa472LHJdgaibLP83NcfAF2e+wkEcA53FxKQAZ7byDzs2eeizg=="], + "@thisbeyond/solid-dnd": ["@thisbeyond/solid-dnd@0.7.5", "", { "peerDependencies": { "solid-js": "^1.5" } }, "sha512-DfI5ff+yYGpK9M21LhYwIPlbP2msKxN2ARwuu6GF8tT1GgNVDTI8VCQvH4TJFoVApP9d44izmAcTh/iTCH2UUw=="], + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], diff --git a/package.json b/package.json index a8684dd..35f0b16 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@fontsource/space-grotesk": "^5.2.0", "@tauri-apps/api": "^2", "@tauri-apps/plugin-shell": "^2", + "@thisbeyond/solid-dnd": "^0.7.5", "lucide-solid": "^0.469.0", "motion": "^12.0.0", "solid-js": "^1.9.3", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b2c3669..a044309 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1123,6 +1123,7 @@ dependencies = [ "tauri-build", "tauri-plugin-shell", "tokio", + "webkit2gtk", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4431e3d..860b919 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -29,6 +29,7 @@ libp2p = { version = "0.54", features = [ "noise", "yamux", "tcp", + "dns", "tokio", "identify", "macros", @@ -56,3 +57,7 @@ dotenvy = "0.15" # async utilities futures = "0.3" + +# platform-specific: webview media permissions on linux +[target.'cfg(target_os = "linux")'.dependencies] +webkit2gtk = "2.0" diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png index 6be5e50e9b9ae84d9e2ee433f32ef446495eaf3b..d6ae74ca860335865402c1679a924b2cede810ce 100644 GIT binary patch delta 1605 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 diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png index e81becee571e96f76aa5667f9324c05e5e7a4479..54c8a3d3e4d772ddc5ef40b2fcb5c00a6835f8d8 100644 GIT binary patch literal 3051 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 F{sZI4VPyaS literal 7012 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 Sh@|8yk@)+z^B;6_01RAkWMI(eL+}HE zj@a;w#!-L_0#2gx*P8+zAw@?AJov`Iu;4MO*g8|f>4J%xDSvvyb4;;SrgU_`!8e#< zHbVGAfvOJp@Eg0hw*;LWz|V?Z+(m>=4sgI>QMfdnisAst0jvw;xqwBpEOxn7&*kBd*0IE#p8Zt1%%i-1xlDpu5sEDwEqwn!o zOn56JP$)ceXMbS$_=kaEKd_Lw@DUFOtTyS delta 953 zcmV;q14jIz1I`DKBYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yPYe~|0>}wMPLT8jm@Y!H33Sz}5aFI6M9Lzqz|;A*0sGs=27i|Alfd@({CV%spP6rf ze;o)bf|~g>UnV~jkGjJ}<}W3{CRG%T?@stpm0p{GXu#O2vKTYY*TMqm>uwo{YT&Fm z&V3b&clullScJT_tMh-wKS(D38?GRgSD*JYU>y(dKEtX4IP7Im@Z3Xe@UxDGot9+B zBA~*=We-hcB!3bKu$?N{gz0{hj>T>@W{$>lYSRIWjyNX_*-n8ZNGT%hXYPw)L40tc2P@0*DCA%V@V0K`ue3T5tf9gtcfxwn-ELLB4t0Ki<6Qp9jcAVk-C` zeq13nX&#e_sJTc%QJxLYLFOMkwqAkwInKk+%R;M?qdpl8e% zz~nk_Qj=U_0yHHPHDsDRW_s?^i3Mb@dzxKNGZ@O)I+M(<0uvFs62p$?X_!dBc6%Ti z%8VST-rvt1_1W$wQ< zz3)YCphBMrVaP(O_j_+b9dmisnY8Ran!K25A^{weA{)CvpL5X*#7Rg(A&LFNOSRM4 zFbjoga@nP6w_x%dO5D058rj@3M8%)A+y{1Kn}5`w*B|@?cJg}3HE!J(5P`V@h*0$j zu;`a;gJ>VeVc-uFC^7jN%t1hamjuD`o$bAYtp*P|2Mi}D-|PK%xt655>kxM`@=+az zKpBcESo=MCn2?NKK4rXn?AUbdjwX-$d~h=N4{`>?AP@nwkP%J|S00ObRSDV@hGFEn z_J7ZE_NI5a_Bna=mt~%Xsgg&%zn4qgJ!8L! z`C diff --git a/src-tauri/icons/64x64.png b/src-tauri/icons/64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1d31006157e1368b34e30ff2b05a307ab26d5f GIT binary patch literal 836 zcmV-K1H1f*P)LDyU$laAxSk(jXOW^!}M1Svt=9nm6Np=fE(FcW3UqzkBYz=lstN0GNl5EdZaJ z01yBIKmZ5;0U!VbfB+Bx9@<*f>+uk9tr-aZd4oG+z{n&pJPthn4ov;_=3Pn(nGCHj z2hKMDosCPMMHPtd55U6|FqhU8fML6Wz(Dw~H~eoMqrk1WdeM1J0T|vu2rcWDe;%I# z_C5uY)0zS>AjI0TdxGH&H)HPgSz1gx@{d^{5?#4XPYZBqhnl$(cls<-pRQtpkebQ( zWn^>qHixQ!X|*v%ziGAvtSklEu@}JoghoqX@lrVVDtEhkyMdZD8Umm_NSbT+Y`?Sp zplAWm3wl$z+tpP7XX-QrKpXgKuH6lFG6YIB1TZpTzU|R!4FOEdns0ld!RH9b1NvL-B`{b<9ezCtZ)I_AhLo;r7pbzh zKV^<0<6{UKba4)v-wbcvjPO3HQd#|D`*lM{bpcA!iNl3GHbec+>V=N7L3Vt0v~Yu` z>pLx$I!=dsV!-7$-VdIAI;{%1RvR1|&uoAPtGpZhm3Jt<@_0vmMx)QS+q*IIc`J@` zV;ny4@9E&yZog-6m0XbE5y^6uTi(D~?@g}4D>5usv0`&^JFstq_1K=_ZJ#ceq*%0| zZqLY%0nv%jQZa+U6H{7db-uVJ2e~OK00e*l5C8%|00;m9AOHkFp=<&8Da(1-TMps? O00003YBb literal 0 HcmV?d00001 diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png index 0ca4f27198838968bd60ed7d371bfa23496b7fe5..194b9c74acff76ca5380b8ae13d28a3e9872700a 100644 GIT binary patch delta 1301 zcmaKs`#aMM0EZoyCD%2h9g!SDEFG6x?V(f%vnbCvD4tf+X>M7e zC2i)C+ry5ehmcqiww=js*f4E$jMMoCdVhG|=lT2rpI1heS_Kw>y2RW4I41eaVzD0{ z^9QWU5ArN$e=))0P!N?J#Lk8El?Un^8Wf*^_LbA)@~Va-3wdbHeaV++Wun&&WghY7 z!CM93xpId+cd8D9&`|MKgH>Ii^q<5k5ZdX0f}bRPe*}ETN)gH5m~N4_2yO~ehE!a# zptmdL_JiTxEI=Iv`H`PFI~9jy-7sQ_vBKUIH6oVFqMZfsEj zk;{NF=7X-&txpp=tMFe)1~+uJldkSqi-*0IXQ!x@Y!9mVKwg85I0B^h_IU^quL=9r zu=+hPJg8}+Oc2?mooS0=jw4k?D5IfSUfM)_f?z&NWN4i$56s z+k*UScO5-qYBNe$}u;Oj{%(X;4bY6U&s$9~#>)Jcv&XYniF zh)SpOUE3fdw4HEiM>E+QaUFJi0A4_BM_m5iohlXbDY0y{V>W>5z~>$8eNppD zW5wy?-HD@`CN>1)RV(}SAxc2_<9C>dNGNvry}{ppCEr3?zSGz*F6wk0J4Lf7DI?vxa zcyLw;;*u(!$52~+Wa1xluwB$~tYuA|Gft6wjSq(7#4$Qs2MNX-2quYktbtC4hMZmv zVbE8xER)%J{ROjYcmTsHa(}q!TYz+g2g?}*^I?_US?7G+W61-3?9l}KV530dYh3~0 z$Ev;(Kph(^y=u#4F^ZbHrT+A>_T%lk+}bim=}4G*zTX%Y#=w}u<%TVi&5<z z;cxZ&XH6TRC1<2dUh-K*Wk#kgTqbM8J3!G9gW5U8hCtJtW|UZ_K~U^Xy5Qf>lvqn( z`ZdL59>a_V#z&%8 zT-&Uhw=E>Z2mv3jq7|g$h;L{@&r9z@S&4`r*wORXmNIQ=$C9%C=_Hu;VrHU`T-myO zhDQeU;t}Z_i-L;4$u2L(y5ad)vaxr2C(3I)pTzFV=rHECCCp3D6^*mDknGANVa64` zuNnk$%D15*JosC;%ihn^V=26~OQOn={^|AqH-o}=W zuIzT=@egt))xS*`VoDdq@*ARl$k1@1hr7lk6&uIF+S;+~kl>(>ZCc|LMpy3X!QCDY6XahYhwlIY delta 2857 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 literal 3858 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 literal 3966 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 Y2S8W#vM)6=T>t<807*qoM6N<$f*y@n<^TWy diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png index c021d2ba76619c08969ab688db3b27f29257aa6f..db7ebd4a87d69558fd2fdc232f9b3c7108e594fd 100644 GIT binary patch literal 3383 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 diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png index 621970023096ed9f494ba18ace15421a45cd65fa..261937600812838f78b7644ae3d248060f35c0d4 100644 GIT binary patch delta 364 zcmV-y0h9iR2ZjTXBYy!+Nkl#e>^oPG$xMRwf1pCMf^I zZ_>?RBFEzIe<2zRlo=S_djYeBKLbOB8pJ`w0!B)+Q-T}=!+b*oKkzgI!-i*s^?}^j zK#9c{K0=)DAOhh>NHZ|}1bXGjTN?Wq1O!+a7#_GWFz_R#n13Lk&(}YravY-rP~uwu z993+cDgHQTqE_}e@CH*1l=x_F@q=%eVr`mquox82q=-|k;go;eOmBfwD3=F@3&TO}^IWsj*)Nuc|j z5}%S>JAn#(P}z&C7z8CGP@MkxN5h5ydXSUT^kE!r(2rV7D*yo8Bu~mZN&mF~0000< KMNUMnLSTZfteuDe delta 881 zcmV-%1CIQL1BVBYBYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yP2+CUKPMqaqGiH;zb!R4$B-WXS^YPmyx`A%2~!(9 zlH^ygDKV3p{Mk(=Xu`Wk{D@#IGk_gPQV&dinMYoVnA6*V3f_c6n`cZswXQR5@9G>J znhN<@*4bB}41X%vU2>E|D#2?#wmFX{G-a=92L)iYZ4U2%FU9H$9f`ktCuA&iizSf&?&-uZ+;0$pk>ntSJ}O^`}5`KJhipib(HjhGn0 zN^@i@#!6RG1|rZaEb*cJccER=BB?KFZhV$c^nL*l8x*UYZv4WK|j?~Jt6~~F%{pk~z z5A*>^M`?r5m9@RJ_x|uEtX(6Vk@Y()MVto*93wr)%3m%|#OZ~srm>zF(JvDuTq*@; zd&^>_BJm5hOU`3FjG70L#Vzv9I?`<7$T@Ry00000NkvXX Hu0mjf6i$)B diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png index f9bc04839491e66c07b16ab03743c0c53b4109cc..fbd7bd2f79eb710ff21be89211484cf10318d5f8 100644 GIT binary patch literal 3641 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 literal 8591 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 KMNUMnLSTZd#uHos delta 1280 zcmV+b1^@cg1d|GoBYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yP}x#CqR3GU7ujt6U06NkcaF#4@P;6g@bZ};3_9&yplTI1Alm>kwzea^R(XsKSNK? zN2}-So&mVWJt7eB34z0Ek=}}{uXE9~=ddI8N>~y!pbbK_0HF$ZWY@6iHyixmipY;3 z2lhr7$3Ix~+J!ht9bB@vMBToE4A_}4MYRNm_?bRdArFMO5Kmq`-P#;>z>4gUK9-UV z&;=PuNh~Qv)_<@ez~(kNUVxlPA?wnw7ZAXeN`U56DMVc&-%;jN!IV#_2^)|*!Z@zY z;$$V!vrUoGrcr=TY3@bZ++2id!455Wsf_XlI)eq7L}@ZBR&L&O4{w~|H!uHaC6eGmVu-(GuJZ;n#6+q@ zqA@;KMzorqnegGSPOtFZpCJUin;V9A>&Dh+6#(oj!)s-TBY+oC2O3?63_8qFEi61< zu)!YJxPSdTPFVI68aEteN)1~XS5rk>-nSzB?e(nWFZ>}UR5Z6%%eLuE@fGZVjf6R} zOR`vs{D2e{1Cm8PfUzdoT=8TwPFe=G#Ks&p7rv#E6@UZpvv=j`qe`OoE?Y;mlwp>u zQ%FX1lL@djcIgr3RPey-D$XqD(b2{t!G(nK^?z!W&-0|-;v-D)V`y72w1iW2xNyYDu@Z>G-sSg+kbQ{C#ZaGO3t8-+8X9L!pu#KTYc;PjR~ggjv}6oE? zTEeoOq`o(z00_-(H8$O^$H)CXJzs13urkgve?w`0O{F<>hak}Q9{khH6G3kL!GFXy zpuA9F*>v9=AC(~^QdPo4KdOtgn7R1!95RCBkF*!g*JLGxVL=XTJcJ&;bovwyD>{oJ z9UPpxCuKKnEx(p0Ic;-AliYQ8n8m9ty9dh4Q zt01R>kA73vm+XbG+$bNs;p)ye4tW%G`UqU<5TQtaq?Bm3BU$M`i!r4KQCq?>m?%yduoNih-!_BddVWNS`gEaLTt17G7Lz%>+IY+ zyR&o87X}vh&Up4S=iYnfoHH>1%Mh)pm>>{10!QEo9DyTn1b>de5jY}&BXDXTPI9Al zYyi4bK%@0JzX&{=wZEI32NnvzpTE_yEfSQc@?D#OOdHU@WA%4WEm$``0*~{+?}CAF z9Ho=M=use1#HVjg0arf&b4v!op&H^q_Bha9UwjN94ZZVs%0+^j>>{B1M{G|jrGw)@ zZq6SYqCwp$IDc(=o&&FcmLB)23%I<;y2}xRJjYQ-!k%J@b@tV})4=(c){j{>z;hgN zJ0Ezn{3A?4s=50EOm6jQCCgu@tRuvP6E3xyEENyOb%9!lxn zSMM3YsDDb)&2KQ{ieRXb=_&+)i`L!fO8PgICex+M!EQB{uL2x)JM^T~vu$fd!JJAu z9usa&sdZ&2RUbIDew?-wP#1F6G??*j2)&Toby}l0ZhfTIjS*F?XY=mxE@wNfsc^!o zPPW?Xh1+$7!QGQi`+S{XXqRf6igMkGiKL}7tAGE_27uhW?N!b}h&eta$4rX`5$YJ1IQ}w_w;Ol##uMI_8vWo`M zFd7&JFxoSL4xma;G5$Z@V0`VesMI1|lRbennA<7i4L`)|^7?*(saSsw;~F+#547lk zl2Zv|A2N&jtX=mtm$$2NvE|eCm?<6XjI3FSbP8@PpE&P6Ovt+rkhf+8j=&K(B7q}t k1dhNFI08rD2pj|S4-&fObn$&3d;kCd07*qoM6N<$f_sOa*#H0l delta 1998 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 KMNUMnLSTaPcL4VQ delta 2459 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 Z9~7@qMtVKz_LBer002ovPDHLkV1ge=tT6xp diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png index 455638826192851ad1ae604d66f2ca352979442c..a301f3545bb8dad99069d43479d2520d1653fddf 100644 GIT binary patch delta 642 zcmV-|0)74S3z`LxBYy&6Nkl;Zd+ zXTP4y>XSX#4$R#Gp7hkm-fRQuBJjEl92`jkQqyEFurSg%KD7?KD47RxwX)V44ghQM z#_>-SZg<}To4dxJ?QZ3Ue7^%cU27cgqrJ3|1mc~NfUq(YMw!q5zqcAS4&yqHGQR&J z@L|09{Tn&`VSm>0H^Tb(tNB}DE#IM(?Un$9mH*cK9`6~>a<&hx+WAtsfBKyEtaw^J zw>R?RkM^92kOZNn6<(~_0ZBl#6uScW+av%P32M&?`y~Jg2-M!)KAZcI2VD*^Ru7#3 z5}-5WkrO~tH^ufx%~jeGWQ?lYXV=B&vo*FINFPUE`GtzOzZXuwLmlSb;d(+m zq*&=q3r_ZppTNsV^BoUQ`&7-3IG5A07*qoM6N<$f`<1vGynhq delta 1506 zcmV<81s(dD1@jA#BYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yPN?3#xh7$lM zzK8K=2xV(ktZjJ6YWNPc&1V{V}FP}?(UhfO@8@FySBTh zd-`>CRlRBe#u#G^8xWotR4zFD;evvffXeAKw}1i<0=UAJS_MXcCn3U%p8}<}0BISB zN!ZZ>#8dEtJtpPBfEYOuI)Agp|L^eEDaZ=Mqd^Icj7VsO93HX-)?hgBk)v%UbDCw) zNQi`fps>te9e>MX>=)FE-il(a1dHJwF8{U*DKRvW$RDr@dJ?>FI^cy@@Tcl|Y@9sr z@(MP%-!;r$!sXgAq`>e*-oN4FL?unn0Y@b{@2$i+%7qedhWM2e>uT{aE2i<8p@?)A zaH#3o;+^~%GN5xjPxxyAdRHjcTuBHQZ7++Fm5`Thl*8`FTd%e?v%Ou^T@dFbH ztq~msapEH(z`N%TLgE48F$`$EuOp}1u-I4_5KLr?Ur>!Z@hCv&g?(PyR!?K(D>c)Y zk>wGm+MM!=(?-XRd;nG<3cH>y8g=}o8Eds3*`bKY;-B3H8w7zQ!B*q#+`4vQQMTWY zHP^%^On*_0&WjS#|8snzQ*>+E`2_>}$m~UZH-FM*u>cn2AtPR2G@Z6;pKvrONJx2ntwR0zRj_HCj7Ti`&d}?{ep{75CX38{XcpSw zS0fTBLDmIK(TCzoZBGDy#h(QWQWFtNkn+nc&42qRBxorL^p1{Tj5Hulzf}DL^ec-K zv?_#DM1+Ko1`-In?a9y6pB7$SX$J=&(aF=#EcwTPexLBbf>b`jBz6eM>2BlSp7LS6 zzBF&!@i57;!>{zKW7_3#x@R01KfXjBSdd7Bqm#>vF7>{HJfHlP>!oi!NP&*%o2K{0 z<$tijrz@M7>_`%)cM`DHC&?B;=$8kmcD=Xr9%Mvn6_CTtu7DUJ0P9$*kBDyo^w!*L zjic*@*;F;cAP6;Fyvk%Pmn7w_7V$AyjkhWP&MFEe+vjiE;rVVX&Q%}-m_&hnsXs{) z>?Mu0T7;0?SWB(G^qtYUXD%BD`P=rNe19Cv@{fNvoye+*2>l`o2)&Upg*5~T;kP$Z zNs(iEQX~t@l+E79$;olpcB)llGLur7wb+4{goIpzZAbw-kyr>sGRJa6+|af&nP;~z zw0#{bu*xN!jPY!uGLB3VB|xQ}^!3H>PCU=_j00tpG&*ZNknkWShAVYDxS5>fDt{4; zJBMgYW*WJ}sy8DEft3g!3$OQgpxs$1s1O5V!fFTYW5e6K^;9b?p4?hy646u^5UN_N z!FWXOC!THh2}Bl?gjn(x4GKVfP%I$zen8Vh)%&*2*^l)de%Wq!TYKX3H(s%5JVrCW z)>kor0+MRoPyBssdv=ttOB9g>F@LK0yRRg|7!%a>4|8YyaRwP6Ni=uoyZrU*K~+Oy z%|3fsm-y~>x3wuh?JZ7wFa$)5BC7AhdS8yLln4sk#*cFY-O40JEhOsOp`;|21WBHf z`5)?iAt8!-P!fVfBK5`jBmSs#w@H%A-@PcOl^@;ckmys?Iixih0;%#yo`2f!`tk%H z2eHh|$HqpQIm8cUFB>QNvVabZ6=q7LzSo+&_*CLhdT8jbaNm(12-kR~q;On8P^V9o z?MHSSKl@9483R=y^c^A + + + + \ No newline at end of file diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..eb1f6a34921e2b3134040508fce1537208cd2027 GIT binary patch literal 1041 zcmV+s1n&EZP)S2RZ9WFJ4SMd-DL8c=P7T zghXS4ghVf5H2ivK1g(~~`<&@}&t2QCv~;&@NjKRv<-xxBX1@7m<}Fd|f-71FQ3p|7 z5HcjTin13%Wc-#kTQvs2)3#lk6SA&OZmtT4!0Z_*gYl54W+Wm)-5J`!mj2lt7zj4@ zSPO8Z8Tk4e`1BL_o_0|{gYg4Ipmh3?0rtj#`vc10RRZ&V9hhDQ-X~mrWp%0$!{D6Z61Y>fgKx6`f3C^Tqt{Zv~#81_oN43bm31Zp{Hxi|TjFNPJOB zvGe7!bppp|mk%4jI2oMEsLPK?9<<5jYs%dhFb>p@==pUK{HwE@5$^ zRBJS(>J$^IDqrcN9;!hZEIc@sq>8?g2_Xos4{2@mZE7*1QKd!&6_%`7regOcSzgt( zs&O=7>caynW~2M)d)8?V^Fi>;!4e!1&fobCqR}cGKSiF=!nG##ee)1-_o({fWnAvD z1a5ZSkzwB>VLUfT%5tGwZDLEuNa50d31_W|cDUCMJQ-FCOe3!-Sd`ES>Yt{UoH`Lm z1IR}5!=KTB)4>zlN7Z6;_}#5^0~y{&)%Ogw5EJD6Qyoe^r7XUoAP`SK12^84G`eno zC^GcuBrRVUqfV4QUw;GU)>Ze(V0y{;E>fS1)CYAnD~d?FxaLbOy*#>}+-4VBb}Mdx zuvAWs>V6^ON(RF(lF5v%qW3=l936|IdVPjwjm45@?#fzm!++-P_^f(@O>=XKJem4M zQc9nhO+~M$DDEW_0S3U&DFc8%Ly^!1u%XvzB71xS=#J~e&8pz!tClg`(n-vVt9r(s ztZ>HO_GITiq1fN31{$6RxSh_?%htCEou%)rQlU_tcDO0P0}bcOP@C#TxtZf$h+7G+ z#9YX@4lotpRCewZ%#lsLEOI-|-6%J6+zW9lkqGDn(AR?kbJohW#H(0swH~UoSd;j| zLr!G?2jQYd-%p5L_om1y^JOIJ@3E^GiLggQ)I4?S|JzXq5%Bc~MyXOL;Sg+300000 LNkvXXu0mjfM3d)r literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..375e730ced2ae650b14e20c1002096b44e44d9cc GIT binary patch literal 1941 zcmbW2X*`sR0>*We203{RgQn4VOGK8jG#L&VF9u^djxEQQy~c9JQmAAsd56hTP8!|G zv6XTN$u`m@#xlnd$u^cc*R^H2#0)iKZujf`bbt55^MC#yp6?Ic)!9x?=9r9xgoKKnVZP-qE>!@l;Am3!jU8p| zok^#)$)irkhkMiLwp8mG*cN$7!wic9$c_0b$bf<@$bSnVd#py$z!i1n3>|ym>1QKf z!_g+eeKVs)OQX4>X+NX5>tA*(7ln(Pd5Q%V2Y&g3R4gG6NB{?b1M%9C^PI4~>t=C_<>U_6er4qf5p-C(E+|L^QytuAzXUDzq)#d<0Lay6yu}={Dst#^ zBX_^fh#gFV$Su{gFIt4uU|QTbj#_@Dx)H})q^~|eLxnO>hQe?{7%Q@SaKO&S zg7uGP2K>N~-S#FVLBVicmQz}8XJDK05$at?)YKog|AVn1;*qSNcu2vo(J-m84?na! z?nJ@HSm$iF#{aOISIp@ZuTEXye93|=HXc)?&gfRg@%IwPDnj$S1<%Uk2eCar5zvIY z*E^g8eNF>FDb#kqr(`MDaGCN|#{hyPPZj)0-+K3=llI&J$^auRPl&S}#msHZJ1|0n zq161yg^wZllY?&O!m5mH`*Jp?=ISu4b#<(C$lr;NnX-9pfdNVpY&{Ke?j55pp$6EM zj|N8qxo6e$5Z3RS%~^uc8=;>jFlXi zHql~x6zDXi`ku{(u~f`F5o*aQKHS~kQwAdh29(Hs4&D7x8joBBg2ase;OTa+&vY1Z zjcLf4Vf&qK0)AZeIQff>hX$BNgO|2SQv0)U#l5mS#htqE%cm=%<$><0Vtp`eS;tBq zXV)kXbedFC?y*f#0Butp%=Y3Y>zu}d=O5QRI(Gq*9Io5J;o?lxKm|EgoCpOv_~Xxe z({E>U8!p33`FUYedwL~)Aq=ggL9~yLJ=HJk5P)%VJ%=ah#Z=os)~o)3F-krEWT*mu z3|Vw!^iJ%}J2>#Mxt_0A_{Q}pi<74sKX+{f>L&3b`x8tgAw|Jn*V=8$N6d;YUGao{c8%}JA43r3y{ewN<(Q2 zqnM<%^h%MiAFDhziy3&zVh4vs;Wqi0fnxrk$Hwa!pCCOqND718ul|WlO1gW2j4b@sZZ*a79r%57 zj+D49Wb@-nP*lqk0qE8mf%duoHpi@SCw|h=E`K>?xGC-?QQxSjwK*XE*812u^%7fi zZNbTd=3!SrZBe-La4&7Se?Z(3`L8H}K5)@JJ;J(_Tj9t*d~3o2Dm+zvGQqr;oLr?E zE4p^BNgUqxA@5w>xow(S1-iH|5jLA`Vw zz&SX|E4_Z8**b`93ja`oLxS4K^nPw<bTVHO{+k1acrBDKKH+^^+C z;DsyF*Tc#3^+(iS7Ise&HW#Mr)fBjGsjWzy_I&ZvtL(_NG|TmYywp}D9N~5(B04nj z6ID=cG$mT8@l95D^XyH9wJM`3yj_u=2&d{#W3^s+T`L+)i(0vpK@Ky`{#6x0SIXL_ z;irI0T#B}TJu(wU*p!EPglbh4dg~D>JYY>8(7Gp^3a7#nFak#WZ}Q*Mz=vW9dy4Qt U&(>(%x4V_Fw{eDQiGgYV1`;xWA^-pY literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..2e43c102b122b527744b90c66a0286829623b6d4 GIT binary patch literal 1174 zcmV;H1Zn$;P)6#u;0RnszmR9b?O5(*_$Yf(f+3Pn`^K$q@y>0Wf`P{*K)&@nm)ohv#-K?xlq z3Gz}zKMs{YK(qDt?#%RF@4JqQt~0Z41C_||NbR9AF}@(XtTF@;cnzxz0R&!)ifOz>o|hbXh#T4qR49l@yL84pIPA62L|{F$U1?*kY5mPRAirf zP<;h(zZ*E;!XOxcW$6WjO|zVKmdrrpJ#v@?`6Yy8(L^L$$xus4CvV8dvUkWid|6UdNRtNZ%nn790Aw! ze3C8c@78nBUMMyYj`6rq?DMhZ(IA5|)d*Z^S5Ov(2N6qKF_Z?<(?DfH3*XY!uXX^< z8x$bbbUD+T{^KS*4RNkPOIT5a*hM8CNn8`JCLs>C{vO zWL$rnyd)qb-|aj(Cuy{Og8@rr1|nzAE^b5GYqUS7RX}X!luFh4H_$4D;Mrf#hH_zB zuvg!_QW&cfWjJ>dW2Lxl;Uaf(D}Rw)n|*A)Zq^Q0Cn%0oI>Vjp=^czAV|u4mF8sv+ z2PZv67-=LZWZsFf;@!QQf$N>#URX;U$i^R@^Jq7+jV&zU=K37+Nqu}#g{1(tavI%c zan#ws)M>8~1#^5i3Q+EKqoPEHi#*R-=DR9OJ(^*!w`~OOr8JEe z=Jmd{))B4oc+{if$cvri>fQao*=7YI#YnvDxE>J4d^hhXkc+LX>JIWfe9o}euC(%d zYm%eX_c<7dq~D%LjQlvI8o8g1ddxccA%EUZYWOD>w2f}$Cw8*vIkgQq%3Wy>Gf|RN zU1mFQ(g;939xlj%Ds=+W?d6}*hBOFbu1g$@fAe|pz&okEA>EP{` z6^8F6t$GG@PyCr)u(xeaCp)7*JElqe0-y++N!QO5qoY0H7q!$`4d=?vc zj2Sp0mZ{#EJY8FbspL^k#fvi9C&M~RsjtBI69t2a`wdZ1Ub2)D3>9PALFEP@?4W?k o3BW)9GXAgnw+Q_ISD}cG->0v10OP3;@&Et;07*qoM6N<$f`8yBod5s; literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..fee7745d7046ecdf159be3aaedb9c50c06566952 GIT binary patch literal 1030 zcmV+h1o``kP)ug<6i=bMys1^~li2i{nis-Sa zMNve7EmA=(LmKR%;-hq&xqaV!=Wy@%KxgJ&y%TfbqMkdR^ZT9e_q~pWQQ#w7Bv2&a zKLI-cI91j!0s?$qyjB5$pB2}C=>v8#3Yo=8u@*fkTTaD%_1n9Bvp`76lSt*YiCPo_ z4D`e*U{4HqHUPvYfltGk?~``^1bmgymp?#D4RF5!_(=r1MuFaO;8F+B|JOld2VFv^ z>wr7E^l_1V;zZ&`4{)_h$8zl_fs&AsiE-XjYk}K4fe2+DrG(6*Z@|e9z+fUP5^5od z%#*XNC<11q7J#KuqEDK*a9q%O4xL-W9zUw zNJ%X|kzH1{vIS$ih^Tppx(l>x+knH=AJ|F9A2PxyS)h9iXdf1`o?F0xIj{n#E)gQO zULdTTZY$kJ!l^R* z_oTe9A&u8lMm$EKBH%9d4<>h(> znomuM-skcawpO@A8k?hU7pWsNJuGL<$4x*J`NRZuR8cF_{Fa)#G&cSbBJl5i0Eb>n zSGK_ZIKPg}*5G)<);Dx|{RBQL%kqgT4cwhc4PfId>CfnsH{h)tlUvRba)-$C6yMLR zmy$TWqLx)cYoC);dOjrc?69o)E1gT+)Vod2%?Q`?ToQ9tSxF~cq03{=u$-hg&Ufd3 zt>XQy#PrC)B{5f(rZD63fHQ2n4;NdWU8^YFNtt|5uvd$wgix-M*yGDxwPcsOeq2Zw z{2w?h4=QF9|IF$`N2Urv{{<(P;=dXc3HUJn0ow~lll=N9sQ>@~07*qoM6N<$g2i;? AHvj+t literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..dedacf7b0c3462b6770cdb176375946bca5c8076 GIT binary patch literal 1301 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 N002ovPDHLkV1lqN6+Zv~ literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2dceb6d0941ec262f01ee9db40ef3c45b30454f3 GIT binary patch literal 2034 zcmVo?a z+8|U@vV{c#fB+yQ00;m=0)PM@luZC!VI!!tzbH(PiKj{!Ut1t7VSZxdiV@BLS+e?T zD+M9}5(fwXqJBgI1OOocKmZUD0OHR9xB@`@ltT{B$pJXX-ARWTUUH{qx{V*=E#AEX zKnyFJ__%xyz+1NhJhBj=qXl4W0$~4nfL|{GoWN@kuX6=}kqIA|JjVQGxBh@oS&joX zb^z>HjX*38jMU<*cn#p)VSpbm02~+t7{2NQQFQ8u$C(9yREt^NFWt;Q%x^;GmT*#v zKlkK2kCJf~;FB`|?~eeSzRHuPds31H)vyvkOeVEL1H5+uz=wSRx3uGX2!f?QBamA1 zWHR4;tsY zDkY>Icf_(2D`*D3gDd-c1j5c&25G@%>3KpW9|U6ylmHMx3S9Q}uOMT0A_(OodrL0- z4+tv&wsuv5C;)_{k`A;!8wL2`0;{6wyc`1ppuygC2f&^4)0G0NQFp>g3a%j#pNQpjAJHNx2hO zX6A60buQ`IZcg}_XjuS=Sd{b4IrdT241&1=8tvsM1>3v)_XL2j0B8h`j?X-t^cap{ zJ$@5FcM4L_&;S^seS)$(Gc`m2OrjL@Vl>@xW- z8-fGpldYt)8o4rh>oP1)K`*9Mu0EmW>fF&U>HhU-cwgw@U@FQahb{>KRq1_7 zAuK@8W#>A8HcTUwL#C5Gt&`(Q>qw_@)B^x2rQa|c?{D`4Y*@%OqG2{vT%8f63TrBJ z&#VN{%F9htot6~9Z>#}$ekJ~9G5l_pm%OvNyq$UsG7A8$ND5@;+PZXK#S4T2zx>eE z%-^vV|1L*+u2;yF=iUOEgRL@{j5B(-11It#8pB1+JQ-ITN)?guMzZLco%rmJ??&eL za=Bp?i7V@J_QA8<*Z~R0a8{D5pH|NAS2(AB_#y6SF_Sd4J2M5tFg>psZ*u&b(9hrB z5AZ}6dpwl?v7+uB-~;xa;jS7QW0H*=D#_|-;}TMd$9MMwEJ2@q*KfF5{{;B@uS#jL z1I-fd6l$gv=x8#o9GfdjQO2sPOgYP5ipx@CsA9QGyjat~k63uCIDpEM_?9 zEkaT?RCY*!su-&$yeesYZr``ux}@UUhOB*qhNBxFXkyPCVKroQKD7~*3S34`GtMIz zZTR^dyjpUa?*+ccDf?C-BOt(7mEw5*W&W@~CQGH;O>d>$ zy<%26O_(N5o{UO)(q03G;@=K3Kc~_^%Ah7)k|sW&)kZs3)R{snkx~djkRX8qE$`X7 zO_g;1?%CR=8WeT%jy_t?E-L5}@tleeh>AvShf~a3q*1%_%m(soUdKS~DU5D=ZeW*l zvgjLV6+*{X994kNKaBz3d&3-L1>03;{ZR!$Mo>-uwl1#ErxJ0hQl@~77-3H4vs9#_F)}i4&bY^L;F;wOA}pa?0@ee=Y|RZ0)UVJAOHwK{q_eaVUtLJ03cM` z9WhZu32k_Z1Z1d5PoyA$wg~xesu}xlszTxg2>?O@fB+yQ00;m=0zmfZAEM2tF0g_w Qq5uE@07*qoM6N<$g1IcCBLDyZ literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..f81a6f375197f34d51dd193b1553277e16fab524 GIT binary patch literal 2576 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..619cf14ec92405a6539cc73b208ab98abf03263e GIT binary patch literal 3811 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..d2cf59d7ee9ab2b620d5722aca898f707bd9deec GIT binary patch literal 3778 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 sc@cpO0gwytM*si-07*qoM6N<$g3QJY1ONa4 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..33f442707173220bec32f304f1956bd078811d99 GIT binary patch literal 4481 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 hSpH9Mf~3e0o07h>IwN%xe`2iwbTkcdOV9WStP% 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 E0DN^cR{#J2 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/android/values/ic_launcher_background.xml b/src-tauri/icons/android/values/ic_launcher_background.xml new file mode 100644 index 0000000..ea9c223 --- /dev/null +++ b/src-tauri/icons/android/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #fff + \ No newline at end of file diff --git a/src-tauri/icons/icon.icns b/src-tauri/icons/icon.icns index 12a5bcee268851fdab744ec4a31f75d3d008e031..70d6064e660c1ed70dcc4d0773cd9a9f1bd339c5 100644 GIT binary patch literal 38476 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

!P(m`y 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

-9nrp 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 literal 98451 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∓t$dRJGIadE?vc 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 Kx8Vjl{{H|h@<;Lj diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico index b3636e4b22ba65db9061cd60a77b02c92022dfd6..ea842989e09e95b6a9ae3a0faa388853f747118d 100644 GIT binary patch literal 6314 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 AUH||9 literal 86642 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 AKmY&$ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png index e1cd2619e0b5ec089cbba5ec7b03ddf2b1dfceb6..4b9fa7b9b65b6fccd2d1aab4025acf3466178dc7 100644 GIT binary patch literal 6261 zcmbVQc|6qH`#&?oU@W7gpCmKgZY6Sc$(m(Ek!!0^*^@nE%@V^575bLAgf3~OQbd*_ zTh??FvXgzwzHeh4GxI&u>-Ycn_3E!PpYxn&dq2;4p6AScQ)4|rj5r1WAb3Gv_Ywd| z_!9|u(Qu&$b?yKlrhY+J+bpPWVUYh@lFMzLWwKTNz291sqzjXDo)_8lwf^v!sz$t2 zJfFcWlGB*<*z=DRj|(3i8#|vw_x?DX`p(F@{akXpW23tbS8QAFBl*T#k}Bz6EW^*X zAwL|?d|XS*pW660@oac(?9y^&3zKnF_ig&u^_7YicInbw<>HSSsgUHXAf+7ObtgO&uE(A}gEV60Fx} zZ;+V_$r}s9A$2$ESOqw?bZ<%a+FBY&}ff3q#yiuf83IIOrSIc48E=K5P`V87fRDet zpT`pGfWgaAo74od7qVt@Foj&cAK*7=8qVDbkTmWA;hn0$n7_(Htmw%Jk zqJJ5`*`I@f`o|NCxD9wqCgL|(2O8golLsDq^i0gf06YMyJ3aQj`(10@!bNg017)vE z$EUebQ80YAMdIF@Z=K7RKL@Z?8%g2+W}gWZll*1!qMF z0H~CU=g*e~JliMC1(}Usd=r#P;JSI37pfS4g|32q24wLv3?|6&-2!~A%p=%<#1ep zof7@g(ltQ>0Cy?UiN|V8a*D;FR9=Jy>gS%y2`CQFmA-zQn-%n-6h@UIYzlwu0ag3)*;V6MU+ILm z0LT^vxcI5r$EZonOg>0pyBF!5PkXf=s(2tf7=QA%*`Y_Lr*_Bx=1#NaiAs5gaAPF_UQ ztUQLhx8HfkTS_dXHPJuY%`3b@kP#e{|aHX?9nxz4ZlUj5MI{+g&~7x^9dfh+aH znvM9re#Gbf!1SMgv%B!(sQa=2zkW!tP*hlt3;w1Vq5e0anm@vJKnx(T7MDp#t zHp|%(N8Vg(EvR48=p?l=((5olSTMZniC@^Nm)9wIF$B;L5l1#+jTa%nTK~Kdg5dr| zn!l*{^@IerJfK_+CXehj?yEa~{?plAerGbIV2%WnMXT>qp3c@&_GoVJ0hGd#2K#If zs_bO8Dp$~nK!AKqoOmj7P%;{TtK9l&M&Vz$>+pCd5NvY*V-|^O3yfWIJ6p}H55MDn zog2`it{}c~M~A_NfS*LhRnk! z?P72IygE&2rtX#YB0tQt;J!htPCQdx+|?`}(hC*~1%<6RB}szs_l$heeD8QQcyTov z9IIK3_Jc%j_|YbC_2ozBtZ;bzWfJl79Wh~;BAq1|0z2nP+Qa3?9H~ZbTqgy?>BDwS zrYHoU@yHJ6qBF)suDJ8=1Hj=Rgm(`BWy5`G#wbT1j&yl=kp}_r#;DFo*0ADXQvjy_ zY~-eNC^?zQZzBC&6XK^}v2G2B^1O5>{M2eTgkTmXKfc26_qdMYp!ed?EFXz{C2Fdh zN*uIH$HEekk0HUcJMs1FXTMo+Y@|uQM!}gvD93W?wyco`%IM4(&O`wDyNymJO&O?5hVu zb2#cPK$gPPuHzT6pOjEh0c=$+0W$Xb9R5Df^gQ$!s(fkQ}^7?y}F{ zZ4yxASkXDD;eP6>XJwBPG;rj1C?Dz+?uY#V8s%^hc3}dDCUWM6pC6PSG*ma8QAb1w z+<)_uqdQuX(pS#-jUz3ynUTQ>Ex{jFsxPr-Ff5eWZ&jv(kUh(#tq!h)3{Ny-U zWiOVtDXkcNp8_EvIzKYMGb;ZnK@WNp0z)x*lH-j7nm|1EG=~G)({p)EbIlhaUp0o{ zKjiqE{X--gg1%;H1z`e_wWn)cBfCCbaOdRJBk%%&W;FQM|C=rr5Kgj-zgbs^ zailen5S;tkCCk344o!(h6QGrro};>o6jvmdyS!&QnxKqy;0Do)NcJyvi=QFGA8kx5yt^ma3f4vQ<{XTK2jqKK z$;wtm<}iX3?fk91KlvISw|!wpaL^BMVMBqleshi-LiD6oSyL?e6-2BWSo)TV(<1~w zcEWgx;r))6Z1He`>V7Son^Oo5x<97vh)NYS&RIe^)9yJM8qih2Ox^9a+Bjs!LAsyp zzfqnE4^WEPC49m^cLunk;k_H9GB!7cL!J#}aHxLluIh(860u;)OL? zQyh2ohg)`AB(jBw%j*jqv(mk6*h#GZvD7M#U-&ZCO9b==UpLQ~+lfUJxByME*wA>t zv02m;0NqP}afBRbnk?yOd$B&VDgtG1c z5VRGtb!8%9jzd)6)!5BmTVCU6d=uJ0jUu09!%H}{dw+rq17AzM%7WKRo%4zA`o|#d znOHJLlJ$923rVnf*3-XDxJR!J8vd}Rv3p}1hoFR;CbfqZWv|s(YT6&RDZAuUE{6;I zyjlgSDVAlger`9ezlrKI%`S|mp`%7St`kw}HzBoNzAq5xp__^{!*B^bX z!17(HEc3Q6qqe@8Ija*{*z2|JU#~86QR4del?ApH0)MAVAZY4_9NXnpe;J)yMOr`7 zyNbM^jwRdXl9X<5@dJSuEuLx{)Wk|kJH@}__w~a%?}xR_N7AuWBaX3xAJt-%^khQv zoh}r8!|;7r%?f+7>0`pVVXq{&z%0>>yr(KB zuwhKT@{VkpQ$F^%GTB^YFV%tvL3z&jq-a-qXK9|1XSeFQ`i`1) zP<6(Zz0gFue>6FpJJfITN=j682Aq^4jkhBi1^yYr;E$z&qxKPa)f!u}>d@4viCtm~ z9!r)1>1WWW^?Re*63p-9x-QSp1BiWrMBb|-Gy zM4rFBHMTH}p@>o%Ag>v@I)1XSdhBD@2P1Wl4?UZ21iIV{qh_}2!V?17LBn7nYfAEJvCH+gycA(tw(CHXr=gB9MJ!5iHTQ*&P z88UT1=1sMc$w~e0aX<9Zrc?&H!K@~vC^N8ZK4oZiq`OBC?K8>lWS`p7g9AqJ?aX@BmTPG@ILHz2Q@G}Qu9X-4hfhFOUpgoo|l8s4YP!62d;kXunJQxEB1b& z5&Dxp(;HdMdMorcsBG=opx7Wo}3A(%}9R8vV@Om=v*{kcr6YSATfP6yxsn4*kdYo^Ih$GFT0`XIvlHI z^@inIHC6Td@R{K5k15J*C#x=PKob=~R;^7sZronjU1K`Ot|}u&yS0YN^9|a3f}sa2 zPX~T_$DmIjsI}e4O%8QQJP1yVQeP;XEgf$f{&U3y;ERwHl{FJ<9>ZAa;noRtIfAiw zS6)<=DDdD0@942`%;E-Z>n0wEINL#tRILW^{alU1k`WZlrX_sw3BYUT1pfw>G7A<04l(Z2j_zj+@0L_Jo63vB<1 zJG;(I5Qo`hHg0ORp=bhaSQ-vE48y|r1PeZA+Bxu33dx$)Zxd$$(W0_WV|Ncw`I2&I z5pI{vxUZki7^ zhCKlGYAoy(cRAf+8bKpY8tGenv*7uPf4HeQibYUzl{nQfT#bNUcEA-d_W=Do>!an1 zn+f$(ncVd5q>6gc&5vENVqChxv(lrhH6LbGKTudw!)GK}ynvp*TC+a6^!p~!oL@zB zBIGq`DQN2me6$ED9yDBHUUzXg5U1(Clf3kgj*<&}Qd<7#TdAKdodtCYH=W))N5NN_ za8r1kK?>8E<&qJI=0vDa)qAISotyBeXGv~YM3M#T+aG%)p3L(gf!lT~jmNovFPzr4 z<*quFzzHnzV4H_7bM9dLrgi%M^#2@XYwcY09ids`0b$?>;oBOlzhJ>R!?00@K5Gt&?8UpDxrV z4`uGBKMG{xuT?gw*l_`|xGoC0?8^m2`}!f)gDX~xdhq{<6NFn^uz4S#l_JO*M_{dR zuUVE6%qCaWl!kG^VIOg+-j~hjc3;&26tUxm4_CMm;OTz6?7)=W_QOSZL|=J>=j5~b zByIVTT2hkdyOvl0B7o#B9#HTU9+(k$-jN#U@GYx?kpcerkfD)Iu+7e8S%sySVi6#V z582T|9NKU$^^g*^`+oV$h9{}!4h{h>%}In;JxLk}cw^Z)(p(qc;_3ScX7bm+LXm#W zCalHcx0u2eBKwHe1s z-*$za#^R%~N-p%`B?THBcU^liHHFTYQ7gNI@=%8g1)hf9-8?Uo%I!wS4*sEKZ9u_X z;rkLZeK(^0FVjV7*M0--+XZq38;wI1Q5tZDH6E~5nSASbw&31!+3R=9Moo`Dbt`Gv z-MYA`D4v9_aB2!;CN#Zg2Bx}&RJpPk9ZfBP6`9wtT)>_Xu~p=}6av7R6N2+g3m)=8 xIlr<{AnUJc{za7>Q-4(@UEP-v97&PEK|+vvX&6XYSnlec!}dTN-n*A7cjqfXn2P;S~UY zLx*sHjRpFlJRYS&KS;kz4*meZ!T;|I175!of&PT~UopM_RDCs#mpz{dm* z+I40CP^Xy~>f1hst(sm!stqil+5R3%vrLgnC*MQ4d&;9 z;#YCkVE=nijZ2oA&dg$~*dLv_6klcUz7sXWtz@@nzE~+QLAmPNQ10W&z^aJ+*{z+z zt-jG-nm6Hv%>O@s2=9)k5=H0YTwx6IkHBFr70X+2Kfcr`H(y{fR z8Q<7Y37J#y=Kn5k;}svC@8y;k%s8IeiS9W5+_UWF*7kR-CtmhCKsAN~BK3Ojr_5q*Urhq{djxt3B<3W0RE@xz&;xiz;*JqY4s_gI4FUqmME@*3Wu>7lh_8& zB$3)u5php6pcfT~!%No9%OBoWCk_1S(^XeLrK~Vz*_#5FV}6cA0z453@b=X>+lDBN zch$4uT8yz18o_n~DmW=h5lu#OsWf|8?Q?Y~UvZMSV=8<2jnQZ_07yu{0QluMTf*z7 zz()`I6F$DfxX!E+iYt$JP2Ch1BzT|!T#s(*?$`C_hx;S?s=!bZ0EqPu9KNAcJiQ5s zNx}f_>rWX4>nl^Z>Y!)&ZZ2QEOl3oE@JAE_f<|z__L}RQ)qFjdoIK}NuxuUbqZN8U zy^K9S?h=4wUu9w3d^r*>Udo;y`R{yXclT?Ul5HeAEEud&gVtyZgeUN7YR$1K7RwH7b3(fRy}50|?$WJ%>i1m1@UG!Wgl zM~Jw{8I29T{4WTe8ifE(@^XYKU*%*kFofQO$?~?x!$GD+CS^IO1;dL?ph{S{`8Bz$ z+3Rh}(HG%Byj}zT(L#7oWx_*D@zZ)B+7J$KM%ZBFWEScH7N`Q}bLiy7J%B|I4p3rk zFxnkn05zEnmrFUUo?$1Rh{R}HH{k8_CQN@e1H$=mz&XEh4DUL<#v1y&9Hwy>Njhx{ z;QYr)_{=;il0nX>VEHpn9JmjEqsI(rGCd7vv)oJ5*ARa!j)NWs>g{|2;X5CJmk-EK zv^tPoETjJ_0De6*A?RcyypRQ7I013v5LzCx1NCcw-^B-sV+RWCDTgR_9#IeV!Iya( z$O1z+t~Ag}|KJ0Pry|`OIekM>To(;IzY;V)JsV@S0(o{=T(K3+-$#E`J&Jp;VQ&Gw9_7mzJ39HdS7WBj2hu>RK@AZc>+DtZ97&R$;ONX zA}>#G6M5ksnvL$nK`XM+YjvREi{N}rnk=i@wq34B>DhNqYVN;At|cO(a0o!(z0YdJ znLzBf+CAf0aj&D@?O^l8>(De=#D*wRKQ`d!>4sdkR%k$M^3u$H==}1XP-Q$SJtS=t z<>&Zd2mi@1alLgs`+8#v<^)$t0tolJE5fV(xCwLi=WMxv;Ug^c%|EOM5r#&1H^+K? zuewVttC9LA1ghD#aEURO0Fv4vjPZVXufT04CA?N2)b2@+5PYku%$CcyD}V%Ai>BOs z$1$^lluni>GavLpUVXfVlf$Q2+_a(`)ACnom>F$$ivy}SI%8hE$1Ln$LhpK?EvhvY z8L@DN$!KFla`|aeF+J>&4T*~ncpRgE)p;zcKIv zf`ROvVnV~01}M37dV@r%Hgw(7weTfLvK1_rz}##QVWD3H-Ki**{=??71MhK3vON$> z$Z9-Ff7Q%D&JJjx^sGAlT(e~p(W;jDA!~PXzOD7CSU@ms zkM41VQ8k^na;s+gi5__`g&sH+(CK$DXw*7==4%3TngKJAW}C{`leYBf^_^j17)QDb z)SOo2`A^#D4{PahKET#;UWry0mwQ)^&5}|Bo4E=ov0gh%W2DHv)R6 zt1Iu;Zj8GvX(ih~kxa=f>2|zj3kU+Xrtj<-(}|-eWQu>QKQR}7hrp=msOBIi87jSB$axtJt0QnD1iN^| zWfb=-EX$qL_lbP@H=En;JbmYoVf|6Uub>og-)g3}H%FC8%LO4so|5EYGfT-T5@;Z^ zltw{qklaj%P``y9^I13K@jhsKp?nc4dGA*ehGb-B-gvgbkK`SL%SIyretz;wo-`&? zv!=C1&geB?u7haS2K$#+2q1-jbtP{pR7K%LU}td|qUZf(W)Tc@mxhfcSeM@_{N`q} z4?q2sMJgfl*_B~X^YP+V;DLX!_R5PgIWZn~@*>g>_dp6p7-tTq1_jZB2aXFS5p#wp zxlzyL2$@NMJMFU;y`+F|GDbmrEbOusQ;1!H96=K*cps@vKl3-CyuZt?=n9h64yPgs zBRpmfq7KC{uE6A$$F1G<4o`Bvi1-4nSRVY-D?}Y~=P*jHN`#&BuI{a?csJTr>+^g- z{7Brs`OjTyT^43-?P_(oGKE!Xej6~VM~m3PzC?@xD(cN`wMsv+lqGR)$_6hg1#4F1 z>9}PH_Bp!kpGM`H4Ze!nA`2-or$Z0K<2okvs{H<^G5zoYje|s6Gf(r8(3ZgJlmITEnnmW5+=gk+X0ts!tNRpE5Jzk4)k@xh<)3BpV${G~HD)O7 zO&@C%0Ga+2g&g7Rr1MV+g>RX0SH`!%0t!`cWp;%4=~l1oo2`gb5A6VAHFN!T#g{(_ z5tssyS~!)W<)lH@*x~~puJLxDG8GTi8Xdg)C?ejt%aB7vm$Zv;ZwXUgJvmIJMwqTV z#&CSNW-F$GhQ`Go!vj#6>{eewXMM99aj!pPW#5%q#FH#ydFci$D))O)QlCi_0EM{r$W{SkJg`Ic3Y(t3i8=o`n#ziabr z5u$TNp+`u$?&8i&2D1My<)2rMJeLL(L;)PN#DEg3yTH-|2y8Hca#L=m8CZ zsdOnOC=^!y|ia&g?BlXg)XP{0d|T8Nwhfat~l z^w##=Fn@B7fBk}p#M?Cd#M$i)jc#V-PJmp_O!6-(KRm~aAdd400*00CHJEHgmtrr? z{MKr>GYPT+$^1cNJaoCrj_2Aj7| zuCpx4(fR~fB0w-hG1D8?qs17kMu&{e4=WwTB{_B?d_e7m%nMp&m9yR6?C{`^HFH@S`Ey0K9Dk^+berIidxcQvOgnin#^-O>I zNF(l_XJgQF-KE^~GGT<#MuM*uZOyoi-gj%mA`)apRZ%Yr&`tzt5oQ7i2k{w|pPsb0 zz;&P%WbPF!qjefP{yR^gkP|#%Z{|FNS5z?_^oZ1l`HLt83$&>Y@PPG0*|sG?iNE!#k<9vt`aps~m8rA=`QXa(YV{8vDwjk5 z8qW}xn20VZ$tMjiu$YDSC-dO znG6L`L2EiX}$a8Onl~{PzxAn%rIn zJNM~=!OI}ZlJWb3r-k1Yx%M)oAWjVOrio4XjjFn$-;cg%bYYx98=-fU>*<0Wviq6Z z@*1!wztr?7-8s~$;&t_6wJ&=Yh?y5%VJFjPMw#2Bw<^guDXdvy&;M?$H#UbL&_N0?VNk)as8Y*!5)|8hr8rI3bUn*@3e z9t$Q4=~u-Fu0q?R~EXBlK$R--by1SCTyQU13HNSDYY|%p60rI zCThl)A+>lEP%q?)TTAXKnnUs7#6;j-N!(AvVd-&dTcSYS&53#d!K7R)p*c?+OHhFt zu!iY}7CWs4izL;NOiZ)^DMJ62`{Xfx3Na zx3MI$BXIsU41N*L!xo8Ayg7aw^UhYhHBLkZGRi|!^1ML|Eq%?-@^enGRSNQvwA{^D zggCHKj_N=O_uq6<7O^XrL5(tZ{1U<~O(&x^4)(rGvHlR?{6hAB6rZ2~lxsjQh@9!P zd4HTdCR`}9D(30hFO$y|UEaqEAzcg!*m4AdU~}MumD*#bt4v?7mtHT&*xI4_qi`EB0 zxH_3fe{#;nF^IY@_9}o0q+WJZG0alF{F*yx6x6NzZO7Eg4o`4gewgfp(D#cj+ zoFo5kbKX#IG3nArL@%DGbb?+&x_}09GlQps&B+-15th20HvHho?~RTbmf`houEWB> z4u>mH{wJyVZR~_p8R^0x@K`)=U)Y8B%{(0Iu{lYD+$^9fLC7&1W0nn`0B^tW@I?cH zLI3^0M+;pI&uspdUEjBuK8 z^itfn`6__A%iE;|guR7ZUq8_~>}KhG&MIJir|#JR0(>~X@ZB86)@<9LNzdyX5Cv=j zsy^KMa`!8+x$E0*u1-&Dqp*4Ku*o=10elGplcNF4NQ-jb# z(*r!T#L5*oQ4==X@hy`X#1+|nE4v5sr1UOT?X;B>kzhAv;)Ve&m7RJ4Zp~XoQA$!N z$j-6C7LK{`c54$XkPIeU`*r+UI_XAisJyP~1?GInw+ZritPp3`h;8+LF~%X~(lj)I z1-o&$*EeD>)dU;Xkjj*^r}}2^wi|vo}_z5DE(j`*u=_yu`62TW68d=daMJF z>8{4-<(XxLf71f!Z{fd`do)_chDWNcwK`^xqG$Mm7=bvt^cfO)I}-I$j)^8sZ~qh(lq zZAr(i7Tdb)jpA?eL*3x<`qUuVUKQ;L_=$7EEcM&hh?zZnnunW>RO;&SurY!F(+#Vl zCuUDYDDn~E;EqSOVP#y*;MNfpZ)kKCOHf=upFFH2S0pxbYXY~BBi&$bT>ij?ES_i6 zOHu8>Bg*CHr0fqm^fF13#NtBlUGG zc4T_|`qP_zUaEVe;U^9qV9Gy8dtL6A0GT_Cp0=J{3SLe^a{sqTHs_$JMf&#LhiTn& zc1;~t=`;6TzJ|7~#ZSzoHT?bi0ebXbqX`N@qOHp^kOEUw6rq-T!@|du1l9 z(A?=_?B5{GiLa6F?$hv0oV?PmvsI-8?BO0QYnPRFRh#Z4>~;&C)+r9l#2GHUjq3H@ zZ>cAI5+nqv`PBIR4oX`T;9JV}!=Be5Qsgs{?!FZx>tXCh#m%pgC%`X1ld`je) zAWlVDB8Ty!9S^V>vz1`?P6`-7Q}5>6w*A{qM=Mep5q|rO<)I{V%x%E$tSw;rpGuCq z4CuXrO(Ah3zU+m7uU2I`umNa5x_t9b%h=ard^lP={?Ryv6@h*p0v;K_ns%rW_*|ZB zhj*tBuJOTB-j|FCU4iku>e3bjix!R6wEpGlsizXVF_1O#_y|}|_qiO}vjP4{1X8

5l#v3A#xI3*z~1~fvo9Q(N^(==!|_FZ z*duZ=+M1~)8E|otX8KNZlr?qels#x_1Xq@9IIw~@9uAREJVH)Xw^}UclF6327}E42 zT)E&?U%TK?(+K7%R!`H5oX0i)4Qn5??Iw3p5J~6_u+aWehY{DSn}3V2p$bgjnAu?o)v@iC254fXeMv50$9YrpU`N?u@QIWs)T?SP|fa}(|9 zqAX+!7`cx=4)cCBg5h~pu(?@9`)aCr#oyz$ld=#RFxYCNZCZls@4v2~*e-t6PEVvV z&bbK3b3wt(Coc!ufAbXXC<**#HQ%J9k`New6iG<5RjtO4XVO?dCvwxD{kJ#tfQr(X zg^NTwF-FwAeS_{V4bfel8l`~NbfrTR2s!G>WduFWxH(t~aK4q=6rEE^$+Uox>gJO2 z{L<;6Q6nHa5#ZEM>H58not!)z(6*_=^~8}jWf*IG$AUKVWOZ4?)GfF z+BM#*wKKmLFD7E~W3U!$IVm$k_k1f&Kz6WV8@55P?r~bcg-Za-!rvW?ns&)KOGT2~ zlkAyqhQj=P$Eg3w#K~}zH@J5bo-BfHjInKSz$@?+Z)NPD4pHj^_Qxmi`UqoTy=`sV zLVxrXGuBr=QRm|}wg75yetQQK4fY3#P_~J}zEfPnb2C4Wo!E(d*(cA;b?7$g2in<( zPn)ghX}nzJPmb6(3Dpeg_GW~Hc}Lt=lgsSZz z!5QXyz7KaR;D`3Ee}d`af{H>WWZ|Io1QI3~4Ll_`g1(cRnhLK73Ro)7zPCd={1W2x zRp%Xlvv4>!<2@}$hz|!V{T}_eHx2xkLl^hQoZTCnsjCl|W_@5Fx2(+j0ogy&Y+;L- z<)G$*CiN7hOm^s!{U>1F7U=iNk{+u~dAC!eDz%=|glFW0jEZU1&o(G_c#wTxUjnG} z#cg3>jEpUi#Mlq@t?Msg_#geK^Lx@DyHWf7=AS5vVyM7YOjvUVCfcpVR<(+5!H?9- zySI6s>o3m&*zr||=wcPGyBkQV`EWJl@bH8qobjOp+sXL*)=&yX)8aAbf~tGv?a2SN zu^Ddo-z?DWk9h9Yz#5p^NU#x~wYSd?H@w@!2Gb4G)6-utEMV~~M85Br5ff(v5O1|T z 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..4c4491d4ebb71f8b513935ec62fb7effb41503ce GIT binary patch literal 550 zcmV+>0@?kEP){fz87KbO0T|UI4lzz(biLUP?%x zvmZdY0=#|e&n+7PSfNf@BAADFAnpfVmVn|i@RR^HLx9`WeQwE&M!g;Y_9KArUwyVR zz)_CAtZDvO{-o?s7EtQKd5*6RmT)RJTy0Omf`g=Fa+tVeaF4Lk`ZbZ+qpszuOU z6OyHX3x4(IT2sb!z|esD^RUNaH?ulwW4kr&Bft^$J?wle1KgX`-lH}06f@^=TtguF zFKy2#>s6tsNoWR%_4xqX52Qj{l309ac&j0`b07*qoM6N<$f_1R@U;qFB literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x.png b/src-tauri/icons/ios/AppIcon-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4c4491d4ebb71f8b513935ec62fb7effb41503ce GIT binary patch literal 550 zcmV+>0@?kEP){fz87KbO0T|UI4lzz(biLUP?%x zvmZdY0=#|e&n+7PSfNf@BAADFAnpfVmVn|i@RR^HLx9`WeQwE&M!g;Y_9KArUwyVR zz)_CAtZDvO{-o?s7EtQKd5*6RmT)RJTy0Omf`g=Fa+tVeaF4Lk`ZbZ+qpszuOU z6OyHX3x4(IT2sb!z|esD^RUNaH?ulwW4kr&Bft^$J?wle1KgX`-lH}06f@^=TtguF zFKy2#>s6tsNoWR%_4xqX52Qj{l309ac&j0`b07*qoM6N<$f_1R@U;qFB literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-20x20@3x.png b/src-tauri/icons/ios/AppIcon-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..04da6d59f4bddc9f20f3d175d44f94a1622de9c8 GIT binary patch literal 748 zcmV|z5H5xGc78N!W6EG{k+TS#X>yWu zDa;iXf&q^dqMd=nD?IX1NfM0n=U6-;ckb-Y?cU7JgDdW4c6WX^Z{C~tpG^QbLWC@V zh?xbpz!um7TVM-pfi19^z^&qGms^2*smk|48Q9qeb`OE|J>c+nEHyi4~V_{cI14&@@8j!59xNdw9?LXB$ zFCKOf`Me9<`dGXD{V4GGl9-v8Av5g8y`A-acTEiT$Pi#>Hm|og7CMe5vKL?Lw@-Eh zk1lGyhO3RiDPOAJXQsct7ia}c%m4U)pX`v>F~to5e&+)CTuUX$83DX=;4bgJzT$0` zn+{mU#yboFUM;)pH`x`j8D^T2b?c@CW;Ny3(x(j&0D4>8_e~~D0G62HGbc57X_kvJ zz+-1MpW(4~L`%ebcwVl5p{y}*rbo`5Y1{jn0w+%ZuhR0@QSsCgI6oqvVrZ0iwF90_ zd#iC5w&Yb!>9jQ5rWST?NIpoe%CDTGoA8&kEK!oz;vN`@y~w0 z2|Vlb2FmMry&tLOLD8E??@6^}g>o?dH%cxFl_D!n2?})z_lZuSKa0=pPH(}f+BSXx z7ghoUrg3)YlE=Axb#5GN^A8AxrxCt%=_leu;AMZX5&h{GpsXgE;^WLMH}+%9 zvss-E#0gH_c&gidP~$q~c5zAfR~`sYb&>g)8k8f;uz25&!b>f%?`c_J3v7Wcum!fj e7T5wCXnz2h_`}ZJmcu9j0000+|(<;%D^z+ zh=CzM0>V$Z$iOh~A#s*7QkrEz7AMF;*bl!mFc|D-VEFKx#+HJ7eBOb9L4gY)Cb$j1 z#Y~hY3XtIw?xBiZa0L2>k%pFnz{cmOe0g9ZOO~f$@WQ}HjW5Ny+}qr1(hfd+#rVTe*-LKK0?GDgn?KDe+WDR z`cPpP?!q5$;Q%UE-+PgsuqY~fK^j2@Jo-VLWgvBgEF`LM02u%ZDtvJSi$jn)LKc!- r_JZOWRJ0+NG<0n_jJ5_xEky00000NkvXXu0mjfPC=Rn literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..0d6215b60e0af3fa1ced6e45a46e40d30ae66be6 GIT binary patch literal 742 zcmV*?cJgU zJqW?tiv}yA7Oe*{jY=!FTIXRKEJ>H{>_?K>eVApqsbj(3+&J$fKv!P@D=9FQLM23uDPq5ow87@D%b-r8sduUO1*Q0jUPC@k1tKf43C z)E)xR_p>T6t&&y-)4-k$hJ#YW)2p}P6gD1o!~tk#lYKfe26SfLS-Tr)!$GNu@6JZG zagE`i`QOgkr8XK4nq2Fw-T9q{*P|kN~W`jW!_0HRJof-?;vn?W4N+dvARhiba zH3Fd5QhM#5+!NX3yLUVa@gEFj60#{Rdz(-pw zdvo}RyXjgSO*aO&D;JP<#^mv3&cGL|bDCU*dFz)ifYFq8CJSZeNIOeYNA08TjBVF; z=dFFf#od*S(3h2=J@^Kd^>t}I-s=F)Y_AODgU`UZtb5nqlYz}DKX(GywJuo5kH1u* z{iuotHaq46@NEYWj8zCX=-j)8?r0zKRf>QLsDKKnfC{L93TPGe Y4`sx-oSw|!u>b%707*qoM6N<$f-?JK0ssI2 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x.png b/src-tauri/icons/ios/AppIcon-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d6215b60e0af3fa1ced6e45a46e40d30ae66be6 GIT binary patch literal 742 zcmV*?cJgU zJqW?tiv}yA7Oe*{jY=!FTIXRKEJ>H{>_?K>eVApqsbj(3+&J$fKv!P@D=9FQLM23uDPq5ow87@D%b-r8sduUO1*Q0jUPC@k1tKf43C z)E)xR_p>T6t&&y-)4-k$hJ#YW)2p}P6gD1o!~tk#lYKfe26SfLS-Tr)!$GNu@6JZG zagE`i`QOgkr8XK4nq2Fw-T9q{*P|kN~W`jW!_0HRJof-?;vn?W4N+dvARhiba zH3Fd5QhM#5+!NX3yLUVa@gEFj60#{Rdz(-pw zdvo}RyXjgSO*aO&D;JP<#^mv3&cGL|bDCU*dFz)ifYFq8CJSZeNIOeYNA08TjBVF; z=dFFf#od*S(3h2=J@^Kd^>t}I-s=F)Y_AODgU`UZtb5nqlYz}DKX(GywJuo5kH1u* z{iuotHaq46@NEYWj8zCX=-j)8?r0zKRf>QLsDKKnfC{L93TPGe Y4`sx-oSw|!u>b%707*qoM6N<$f-?JK0ssI2 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-29x29@3x.png b/src-tauri/icons/ios/AppIcon-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a9189992e5b6f695041d3e17cd2ba94b4b0156a GIT binary patch literal 1070 zcmV+}1kwA6P)e!OwJ19Ig%s`dS+@4(|J>-X=!0h8+I z>3PC+tocO+aL)QFhzHJQ0(;_CzqVxX|Z-O+y^Ja!V%TmUrX|Noj>sSX8fxCwSk7B=iRQNd4zkZN?UOhugiUzvMf#QVV*GkA}d=AVl5UvrxqS9`l ze>!~qi|}%)BUwUa4=^}m@A|$9;9{N{Q9h1bM=@ANaH7rJM<%?}Pt}7Pe)33}fV~cP zLgl)1D*ZaP&EEBe307)%=Oah1Z9Ocr78`bDdIU#c1F7Mev+Gap0xsloLbIiTFTlMC zXZKv)2b3fct}V5`aej|v5wVek8&qABz{srg`>yOKTw8J)8btNkz}|SmwKaOzqP7yk z4XVyH=C9=`dPnbugezK0+!dY6B3xr|CH6)|5Uw#5B@nJL)npK^G1X-gE=+I46K(({ zZwc-G)EL4IsNxVOrSz?!;|2jvCfuM6IdUsfLvQ0q3P#d*AY9W;~|5rzser{J2L$j)?8J$H)t1ej_G-zBP1XAt; z7sC~`6sK%GEVeH1*`XRX6{48$4+2gQfHyW8+@)yVk zcT$vP=QKS+S5w@5{nb83oaF*YY?)q>sVW~MClS)o#uwfIEB!Q8K4q*XLdubD9t2M8 zbT8Q3AAnO&JXjMU9hQ#E18hdH#t$gn3OF2K!*crT2ke#@Ed2-v*s#~3t#=l&p=*ET z!6cv5wO{IFfgqn7PO$4*K`Be+cC`mlmTc}bWUrvMZxg?7K_H*c(r4TBk5t*+;+sPL zNUZYW=oaJgT0jfX4!+|Cw*9eU0@?kEP){fz87KbO0T|UI4lzz(biLUP?%x zvmZdY0=#|e&n+7PSfNf@BAADFAnpfVmVn|i@RR^HLx9`WeQwE&M!g;Y_9KArUwyVR zz)_CAtZDvO{-o?s7EtQKd5*6RmT)RJTy0Omf`g=Fa+tVeaF4Lk`ZbZ+qpszuOU z6OyHX3x4(IT2sb!z|esD^RUNaH?ulwW4kr&Bft^$J?wle1KgX`-lH}06f@^=TtguF zFKy2#>s6tsNoWR%_4xqX52Qj{l309ac&j0`b07*qoM6N<$f_1R@U;qFB literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..faa5a09a3ca2a321375c0cb446e0075bdd2f2dc7 GIT binary patch literal 978 zcmV;@11uG`XjC>8MGP2;z(zMN(1mdaMqFxe?Lz(oL6?5joiWj3TM&A|OBl zBtQbB2#^2?kN_zHBtQZrK#Bmp4)EY^;N~Hqw|?VqZ@&YR^T1dF__PSbmViHh^FLM} z99$1K{$TptP*5E>01P$(l^Note+qa!yYnD@ZmCEgtpr9p zGDBPg`EW-4s1*WC8`2|fKyyXr`(}OtC*J^bzX{OtOcb4;P{8B%j;F|N+lI&j(DNa? zd&4Jy+d(x;eD;lJm%0Ys22r*!5qGxjq;jOc=d;5I2rlD!zMwB6( zy1mH($iRM;6YB^tMWf%6SGIbta$;>M0j4PQHMjfUoi@9uxE|n(92bW`8E_>)fa{uH z&Mk~Z_nK7|rHBAGa$zF(XZjilFl8~xRi(atvi4lCf&e$ZOf2Y5kN~yRu}?pY zJq-}6B{BlkkZv9<2!Ne_jc2RDwx&)P9^XrVS=9wIEhGe34K~)H(Ie4aNj(j)w*jQ+|I3#jV8ScP;#I2IdnCa@E|}5-B62}cZo5{a{z~e*|#%cQzgf> z0B@@mU9y1ay1BH!g`4*596YgU3?4T3zH1+m|9ar(pUMQ;lFUnX=Dcv5nMK27 z{xbqlLSS4uMI&8$RS{&Uw8*=AYRta(>XaEXrV(#UnX)J?ox^&gd-zMzMWv%ad2+EZ z4Q@>(FC7F>)ZduwbYWAcOkj?v#`nT<_MzHSyL#2wml9<5-H*Xp?kurO#LfT>rRm#_ zk;P;aTxRC{^44NNx8K~>B$H;9YqjyUISa5+dz%<{;%A+`4XS%(*7|F-q%Q-zFyUNy zGB(q`Y2!VSu<|4iPdg8uj42#ioVl{T9crtxEe?fgQAwyeQ7l&6{nzHpveP`KXte zdBogk8l->=dFimBfD~WK-6O!MDp;=PNlD7{$6W=ce9j3_@v5{|ZG|eZqyZ#7j3^IW zgGc@;0wh2JBtVJ)36KB@kN_zHBtQZrK+1yt0V3l2Ubik7lK=n!07*qoM6N<$f-#A| APyhe` literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x.png b/src-tauri/icons/ios/AppIcon-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..faa5a09a3ca2a321375c0cb446e0075bdd2f2dc7 GIT binary patch literal 978 zcmV;@11uG`XjC>8MGP2;z(zMN(1mdaMqFxe?Lz(oL6?5joiWj3TM&A|OBl zBtQbB2#^2?kN_zHBtQZrK#Bmp4)EY^;N~Hqw|?VqZ@&YR^T1dF__PSbmViHh^FLM} z99$1K{$TptP*5E>01P$(l^Note+qa!yYnD@ZmCEgtpr9p zGDBPg`EW-4s1*WC8`2|fKyyXr`(}OtC*J^bzX{OtOcb4;P{8B%j;F|N+lI&j(DNa? zd&4Jy+d(x;eD;lJm%0Ys22r*!5qGxjq;jOc=d;5I2rlD!zMwB6( zy1mH($iRM;6YB^tMWf%6SGIbta$;>M0j4PQHMjfUoi@9uxE|n(92bW`8E_>)fa{uH z&Mk~Z_nK7|rHBAGa$zF(XZjilFl8~xRi(atvi4lCf&e$ZOf2Y5kN~yRu}?pY zJq-}6B{BlkkZv9<2!Ne_jc2RDwx&)P9^XrVS=9wIEhGe34K~)H(Ie4aNj(j)w*jQ+|I3#jV8ScP;#I2IdnCa@E|}5-B62}cZo5{a{z~e*|#%cQzgf> z0B@@mU9y1ay1BH!g`4*596YgU3?4T3zH1+m|9ar(pUMQ;lFUnX=Dcv5nMK27 z{xbqlLSS4uMI&8$RS{&Uw8*=AYRta(>XaEXrV(#UnX)J?ox^&gd-zMzMWv%ad2+EZ z4Q@>(FC7F>)ZduwbYWAcOkj?v#`nT<_MzHSyL#2wml9<5-H*Xp?kurO#LfT>rRm#_ zk;P;aTxRC{^44NNx8K~>B$H;9YqjyUISa5+dz%<{;%A+`4XS%(*7|F-q%Q-zFyUNy zGB(q`Y2!VSu<|4iPdg8uj42#ioVl{T9crtxEe?fgQAwyeQ7l&6{nzHpveP`KXte zdBogk8l->=dFimBfD~WK-6O!MDp;=PNlD7{$6W=ce9j3_@v5{|ZG|eZqyZ#7j3^IW zgGc@;0wh2JBtVJ)36KB@kN_zHBtQZrK+1yt0V3l2Ubik7lK=n!07*qoM6N<$f-#A| APyhe` literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-40x40@3x.png b/src-tauri/icons/ios/AppIcon-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..7b150bb9094325178c7563ea5896eaa649dea581 GIT binary patch literal 1427 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 TU%_)*0QT-O{3Gpm>+}Bw*aZ+q literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-60x60@2x.png b/src-tauri/icons/ios/AppIcon-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7b150bb9094325178c7563ea5896eaa649dea581 GIT binary patch literal 1427 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-76x76@1x.png b/src-tauri/icons/ios/AppIcon-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..a4720aaa9034d85e8899fa979dc26baa02777056 GIT binary patch literal 918 zcmV;H18Mw;P)o!zN(36F9eH{V^kRz@-^r>8k+y%i4zH8;>El z3on3`ZvyO>jx+(|U8P-gwR)$4)S|m<3Hss9L?DaA*`p(?g?ndBB zTyvMCc7}mh$IOpc`S$dkg%z!AJZ){?tFO@*Sn;S~MVI$!?2>lel8WAP9!B}r!swPy zKU$k}F{ZIgQkgFn<5J_$8wzR+Y$ph9U?Tz$eE*IF%^W0PVUd=W#x-qZ$_1sG{*sNtumB z(&dx?zPfL`FPwR3b!*Q)+{hW?5Deo&w?m!qq?*PQWpzn*)X+MrQB~P0zy;Clt4&;! z%C1DEm2Vaorh0%xv^rq%kUH>4ZL7NSRsrs3Ge?28I&WdU{S3tJ_@JSV3*EMfQbZ{ s025#WOn?b6kpL550!)AjFi~m!1V-TbD!{8Y2LJ#707*qoM6N<$f<=R}yZ`_I literal 0 HcmV?d00001 diff --git a/src-tauri/icons/ios/AppIcon-76x76@2x.png b/src-tauri/icons/ios/AppIcon-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..95a78b45b1c5b85eaf95851c3e586deba4ef9b55 GIT binary patch literal 1862 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 Y>I1DGe*-) -> Re state.crdt_engine.clone(), state.storage.clone(), app, + state.voice_channels.clone(), ) .await?; // capture profile info for announcement before dropping identity lock - let profile_announcement = ProfileAnnouncement { + let mut profile_announcement = ProfileAnnouncement { peer_id: id.peer_id.to_string(), display_name: id.display_name.clone(), bio: id.bio.clone(), @@ -32,7 +36,11 @@ pub async fn start_node(app: tauri::AppHandle, state: State<'_, AppState>) -> Re .duration_since(UNIX_EPOCH) .unwrap() .as_millis() as u64, + verification_proof: id.verification_proof.clone(), + signature: String::new(), }; + profile_announcement.signature = + verification::sign_announcement(&id.keypair, &profile_announcement); drop(identity); { @@ -114,6 +122,41 @@ pub async fn start_node(app: tauri::AppHandle, state: State<'_, AppState>) -> Re .send(NodeCommand::RegisterRendezvous { namespace }) .await; } + + // subscribe to all existing dm conversation topics + let local_peer_str = { + let identity = state.identity.lock().await; + identity + .as_ref() + .map(|i| i.peer_id.to_string()) + .unwrap_or_default() + }; + if let Ok(conversations) = state.storage.load_all_dm_conversations() { + for (_, meta) in &conversations { + let dm_topic = gossip::topic_for_dm(&local_peer_str, &meta.peer_id); + let _ = handle + .command_tx + .send(NodeCommand::Subscribe { topic: dm_topic }) + .await; + } + } + + // subscribe to personal dm inbox so first-time dms from any peer land + let inbox_topic = gossip::topic_for_dm_inbox(&local_peer_str); + let _ = handle + .command_tx + .send(NodeCommand::Subscribe { topic: inbox_topic }) + .await; + + // register personal rendezvous namespace so any peer can discover + // and connect to us for dms even without sharing a community + let personal_ns = format!("dusk/peer/{}", local_peer_str); + let _ = handle + .command_tx + .send(NodeCommand::RegisterRendezvous { + namespace: personal_ns, + }) + .await; } Ok(()) @@ -242,3 +285,28 @@ fn find_community_for_channel( channel_id )) } + +// attempts tcp connections to well-known hosts to distinguish +// between a general internet outage and the relay being unreachable +#[tauri::command] +pub async fn check_internet_connectivity() -> Result { + let hosts = vec![ + ("www.apple.com", 80), + ("www.google.com", 80), + ("www.yahoo.com", 80), + ]; + + let connect_timeout = Duration::from_secs(5); + + let futures: Vec<_> = hosts + .into_iter() + .map(|(host, port)| { + let addr = format!("{}:{}", host, port); + timeout(connect_timeout, TcpStream::connect(addr)) + }) + .collect(); + + let results = futures::future::join_all(futures).await; + + Ok(results.iter().any(|r| matches!(r, Ok(Ok(_))))) +} diff --git a/src-tauri/src/commands/community.rs b/src-tauri/src/commands/community.rs index c43ad3c..744f43e 100644 --- a/src-tauri/src/commands/community.rs +++ b/src-tauri/src/commands/community.rs @@ -5,7 +5,7 @@ use tauri::State; use crate::node::gossip; use crate::node::NodeCommand; -use crate::protocol::community::{ChannelKind, ChannelMeta, CommunityMeta, Member}; +use crate::protocol::community::{CategoryMeta, ChannelKind, ChannelMeta, CommunityMeta, Member}; use crate::protocol::messages::PeerStatus; use crate::AppState; @@ -224,6 +224,8 @@ pub async fn create_channel( community_id: String, name: String, topic: String, + kind: Option, + category_id: Option, ) -> Result { let mut hasher = Sha256::new(); hasher.update(community_id.as_bytes()); @@ -236,12 +238,19 @@ pub async fn create_channel( let hash = hasher.finalize(); let channel_id = format!("ch_{}", &hex::encode(hash)[..12]); + let channel_kind = match kind.as_deref() { + Some("voice") | Some("Voice") => ChannelKind::Voice, + _ => ChannelKind::Text, + }; + let channel = ChannelMeta { id: channel_id, community_id: community_id.clone(), name, topic, - kind: ChannelKind::Text, + kind: channel_kind, + position: 0, + category_id, }; let mut engine = state.crdt_engine.lock().await; @@ -278,6 +287,59 @@ pub async fn get_channels( engine.get_channels(&community_id) } +#[tauri::command] +pub async fn create_category( + state: State<'_, AppState>, + community_id: String, + name: String, +) -> Result { + let mut hasher = Sha256::new(); + hasher.update(community_id.as_bytes()); + hasher.update(name.as_bytes()); + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64; + hasher.update(now.to_le_bytes()); + let hash = hasher.finalize(); + let category_id = format!("cat_{}", &hex::encode(hash)[..12]); + + let category = CategoryMeta { + id: category_id, + community_id: community_id.clone(), + name, + position: 0, + }; + + let mut engine = state.crdt_engine.lock().await; + engine.create_category(&community_id, &category)?; + drop(engine); + + // broadcast the change via document sync + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let sync_topic = "dusk/sync".to_string(); + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: sync_topic, + data: community_id.as_bytes().to_vec(), + }) + .await; + } + + Ok(category) +} + +#[tauri::command] +pub async fn get_categories( + state: State<'_, AppState>, + community_id: String, +) -> Result, String> { + let engine = state.crdt_engine.lock().await; + engine.get_categories(&community_id) +} + #[tauri::command] pub async fn get_members( state: State<'_, AppState>, @@ -442,3 +504,30 @@ pub async fn generate_invite( Ok(invite.encode()) } + +#[tauri::command] +pub async fn reorder_channels( + state: State<'_, AppState>, + community_id: String, + channel_ids: Vec, +) -> Result, String> { + let mut engine = state.crdt_engine.lock().await; + let channels = engine.reorder_channels(&community_id, &channel_ids)?; + drop(engine); + + // broadcast the reordering to peers via document sync + // the change will propagate through the existing gossipsub sync mechanism + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let sync_topic = "dusk/sync".to_string(); + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: sync_topic, + data: community_id.as_bytes().to_vec(), + }) + .await; + } + + Ok(channels) +} diff --git a/src-tauri/src/commands/dm.rs b/src-tauri/src/commands/dm.rs new file mode 100644 index 0000000..180f621 --- /dev/null +++ b/src-tauri/src/commands/dm.rs @@ -0,0 +1,312 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +use tauri::State; + +use crate::node::gossip; +use crate::node::NodeCommand; +use crate::protocol::messages::{ + DMConversationMeta, DMTypingIndicator, DirectMessage, GossipMessage, +}; +use crate::AppState; + +// send a direct message to a peer +// creates the conversation on disk if it doesn't exist, +// publishes the message over gossipsub on the pair topic +#[tauri::command] +pub async fn send_dm( + state: State<'_, AppState>, + peer_id: String, + content: String, +) -> Result { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64; + + let local_peer_id = id.peer_id.to_string(); + let display_name = id.display_name.clone(); + drop(identity); + + let msg = DirectMessage { + id: format!("dm_{}_{}", local_peer_id, now), + from_peer: local_peer_id.clone(), + to_peer: peer_id.clone(), + from_display_name: display_name.clone(), + content: content.clone(), + timestamp: now, + }; + + // derive the conversation id and persist the message + let conversation_id = gossip::dm_conversation_id(&local_peer_id, &peer_id); + + state + .storage + .append_dm_message(&conversation_id, &msg) + .map_err(|e| format!("failed to persist dm: {}", e))?; + + // ensure conversation metadata exists on disk + // try to load existing meta to preserve peer's display name, + // fall back to what we know from the directory + let existing_meta = state.storage.load_dm_conversation(&conversation_id).ok(); + let peer_display_name = existing_meta + .as_ref() + .map(|m| m.display_name.clone()) + .unwrap_or_else(|| { + // look up in directory + state + .storage + .load_directory() + .ok() + .and_then(|d| d.get(&peer_id).map(|e| e.display_name.clone())) + .unwrap_or_else(|| peer_id.clone()) + }); + + let meta = DMConversationMeta { + peer_id: peer_id.clone(), + display_name: peer_display_name, + last_message: Some(content), + last_message_time: Some(now), + unread_count: existing_meta.map(|m| m.unread_count).unwrap_or(0), + }; + + state + .storage + .save_dm_conversation(&conversation_id, &meta) + .map_err(|e| format!("failed to save dm conversation: {}", e))?; + + // publish to the dm gossipsub topic + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let data = serde_json::to_vec(&GossipMessage::DirectMessage(msg.clone())) + .map_err(|e| format!("serialize error: {}", e))?; + + // publish to the pair topic (for when both peers are already subscribed) + let pair_topic = gossip::topic_for_dm(&local_peer_id, &peer_id); + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: pair_topic, + data: data.clone(), + }) + .await; + + // also publish to the recipient's inbox topic to guarantee delivery + // on first-time dms where the peer isn't subscribed to the pair topic yet + let inbox_topic = gossip::topic_for_dm_inbox(&peer_id); + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: inbox_topic, + data, + }) + .await; + + // discover the peer via rendezvous in case we're not connected over wan + let discover_ns = format!("dusk/peer/{}", peer_id); + let _ = handle + .command_tx + .send(NodeCommand::DiscoverRendezvous { + namespace: discover_ns, + }) + .await; + } + + Ok(msg) +} + +// load dm messages for a conversation with a specific peer +#[tauri::command] +pub async fn get_dm_messages( + state: State<'_, AppState>, + peer_id: String, + before: Option, + limit: Option, +) -> Result, String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let local_peer_id = id.peer_id.to_string(); + drop(identity); + + let conversation_id = gossip::dm_conversation_id(&local_peer_id, &peer_id); + + state + .storage + .load_dm_messages(&conversation_id, before, limit.unwrap_or(50)) + .map_err(|e| format!("failed to load dm messages: {}", e)) +} + +// load all dm conversations for the sidebar +#[tauri::command] +pub async fn get_dm_conversations( + state: State<'_, AppState>, +) -> Result, String> { + let conversations = state + .storage + .load_all_dm_conversations() + .map_err(|e| format!("failed to load dm conversations: {}", e))?; + + Ok(conversations.into_iter().map(|(_, meta)| meta).collect()) +} + +// mark all messages in a dm conversation as read +#[tauri::command] +pub async fn mark_dm_read(state: State<'_, AppState>, peer_id: String) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let local_peer_id = id.peer_id.to_string(); + drop(identity); + + let conversation_id = gossip::dm_conversation_id(&local_peer_id, &peer_id); + + let mut meta = state + .storage + .load_dm_conversation(&conversation_id) + .map_err(|e| format!("failed to load conversation: {}", e))?; + + meta.unread_count = 0; + + state + .storage + .save_dm_conversation(&conversation_id, &meta) + .map_err(|e| format!("failed to save conversation: {}", e)) +} + +// delete a dm conversation and all its messages +#[tauri::command] +pub async fn delete_dm_conversation( + state: State<'_, AppState>, + peer_id: String, +) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let local_peer_id = id.peer_id.to_string(); + drop(identity); + + let conversation_id = gossip::dm_conversation_id(&local_peer_id, &peer_id); + + // unsubscribe from the dm topic + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let topic = gossip::topic_for_dm(&local_peer_id, &peer_id); + let _ = handle + .command_tx + .send(NodeCommand::Unsubscribe { topic }) + .await; + } + + state + .storage + .remove_dm_conversation(&conversation_id) + .map_err(|e| format!("failed to delete conversation: {}", e)) +} + +// send a typing indicator in a dm conversation +#[tauri::command] +pub async fn send_dm_typing(state: State<'_, AppState>, peer_id: String) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let local_peer_id = id.peer_id.to_string(); + drop(identity); + + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64; + + let indicator = DMTypingIndicator { + from_peer: local_peer_id.clone(), + to_peer: peer_id.clone(), + timestamp: now, + }; + + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let topic = gossip::topic_for_dm(&local_peer_id, &peer_id); + let data = serde_json::to_vec(&GossipMessage::DMTyping(indicator)) + .map_err(|e| format!("serialize error: {}", e))?; + + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { topic, data }) + .await; + } + + Ok(()) +} + +// open a dm conversation with a peer (creates metadata on disk and subscribes to topic) +// used when clicking "message" on a peer's profile +#[tauri::command] +pub async fn open_dm_conversation( + state: State<'_, AppState>, + peer_id: String, + display_name: String, +) -> Result { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let local_peer_id = id.peer_id.to_string(); + drop(identity); + + let conversation_id = gossip::dm_conversation_id(&local_peer_id, &peer_id); + + // check if conversation already exists + if let Ok(existing) = state.storage.load_dm_conversation(&conversation_id) { + // subscribe to make sure we're listening + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let topic = gossip::topic_for_dm(&local_peer_id, &peer_id); + let _ = handle + .command_tx + .send(NodeCommand::Subscribe { topic }) + .await; + + // discover the peer via rendezvous to ensure wan connectivity + let discover_ns = format!("dusk/peer/{}", peer_id); + let _ = handle + .command_tx + .send(NodeCommand::DiscoverRendezvous { + namespace: discover_ns, + }) + .await; + } + return Ok(existing); + } + + let meta = DMConversationMeta { + peer_id: peer_id.clone(), + display_name, + last_message: None, + last_message_time: None, + unread_count: 0, + }; + + state + .storage + .save_dm_conversation(&conversation_id, &meta) + .map_err(|e| format!("failed to create dm conversation: {}", e))?; + + // subscribe to the dm topic so we receive messages + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let topic = gossip::topic_for_dm(&local_peer_id, &peer_id); + let _ = handle + .command_tx + .send(NodeCommand::Subscribe { topic }) + .await; + + // discover the peer via rendezvous to establish wan connectivity + // through the relay circuit before any messages are sent + let discover_ns = format!("dusk/peer/{}", peer_id); + let _ = handle + .command_tx + .send(NodeCommand::DiscoverRendezvous { + namespace: discover_ns, + }) + .await; + } + + Ok(meta) +} diff --git a/src-tauri/src/commands/identity.rs b/src-tauri/src/commands/identity.rs index 02a5857..4ffde8a 100644 --- a/src-tauri/src/commands/identity.rs +++ b/src-tauri/src/commands/identity.rs @@ -5,10 +5,44 @@ use tauri::State; use crate::node::gossip; use crate::node::NodeCommand; use crate::protocol::identity::{DirectoryEntry, DuskIdentity, PublicIdentity}; -use crate::protocol::messages::{GossipMessage, ProfileRevocation}; +use crate::protocol::messages::{GossipMessage, ProfileAnnouncement, ProfileRevocation}; use crate::storage::UserSettings; +use crate::verification::{self, ChallengeSubmission}; use crate::AppState; +// build a signed profile announcement and publish it on the directory topic +// so all connected peers immediately learn about the updated profile. +// silently no-ops if the node isn't running yet. +async fn announce_profile(id: &DuskIdentity, state: &AppState) { + let mut announcement = ProfileAnnouncement { + peer_id: id.peer_id.to_string(), + display_name: id.display_name.clone(), + bio: id.bio.clone(), + public_key: hex::encode(id.keypair.public().encode_protobuf()), + timestamp: SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64, + verification_proof: id.verification_proof.clone(), + signature: String::new(), + }; + announcement.signature = verification::sign_announcement(&id.keypair, &announcement); + + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let msg = GossipMessage::ProfileAnnounce(announcement); + if let Ok(data) = serde_json::to_vec(&msg) { + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: gossip::topic_for_directory(), + data, + }) + .await; + } + } +} + #[tauri::command] pub async fn has_identity(state: State<'_, AppState>) -> Result { Ok(state.storage.has_identity()) @@ -37,8 +71,30 @@ pub async fn create_identity( state: State<'_, AppState>, display_name: String, bio: Option, + challenge_data: Option, ) -> Result { - let new_identity = DuskIdentity::generate(&display_name, &bio.unwrap_or_default()); + // require challenge data and re-validate behavioral analysis in rust + let challenge = challenge_data.ok_or("verification required")?; + let result = verification::analyze_challenge(&challenge); + if !result.is_human { + return Err("verification failed".to_string()); + } + + let mut new_identity = DuskIdentity::generate(&display_name, &bio.unwrap_or_default()); + + // generate a cryptographic proof binding the verification to this keypair + let proof = verification::generate_proof( + &challenge, + &new_identity.keypair, + &new_identity.peer_id.to_string(), + )?; + + state + .storage + .save_verification_proof(&proof) + .map_err(|e| format!("failed to save verification proof: {}", e))?; + + new_identity.verification_proof = Some(proof); new_identity.save(&state.storage)?; // also save initial settings with this display name so they're in sync @@ -64,6 +120,8 @@ pub async fn update_display_name(state: State<'_, AppState>, name: String) -> Re id.display_name = name; id.save(&state.storage)?; + announce_profile(id, &state).await; + Ok(()) } @@ -80,7 +138,12 @@ pub async fn update_profile( id.bio = bio; id.save(&state.storage)?; - Ok(id.public_identity()) + let public = id.public_identity(); + + // re-announce so connected peers see the change immediately + announce_profile(id, &state).await; + + Ok(public) } #[tauri::command] @@ -98,13 +161,23 @@ pub async fn save_settings( ) -> Result<(), String> { // also update the identity display name if it changed let mut identity = state.identity.lock().await; + let mut name_changed = false; if let Some(id) = identity.as_mut() { if id.display_name != settings.display_name { id.display_name = settings.display_name.clone(); id.save(&state.storage)?; + name_changed = true; } } + // re-announce if the display name was updated through settings + if name_changed { + if let Some(id) = identity.as_ref() { + announce_profile(id, &state).await; + } + } + drop(identity); + state .storage .save_settings(&settings) @@ -192,14 +265,16 @@ pub async fn reset_identity(state: State<'_, AppState>) -> Result<(), String> { let id = identity.as_ref().ok_or("no identity loaded")?; // build the revocation message before we destroy the identity - let revocation = ProfileRevocation { + let mut revocation = ProfileRevocation { peer_id: id.peer_id.to_string(), public_key: hex::encode(id.keypair.public().encode_protobuf()), timestamp: SystemTime::now() .duration_since(UNIX_EPOCH) .unwrap() .as_millis() as u64, + signature: String::new(), }; + revocation.signature = verification::sign_revocation(&id.keypair, &revocation); // broadcast revocation on the directory gossip topic let node_handle = state.node_handle.lock().await; diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index c736c74..cd459bb 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1,3 +1,5 @@ pub mod chat; pub mod community; +pub mod dm; pub mod identity; +pub mod voice; diff --git a/src-tauri/src/commands/voice.rs b/src-tauri/src/commands/voice.rs new file mode 100644 index 0000000..34a9946 --- /dev/null +++ b/src-tauri/src/commands/voice.rs @@ -0,0 +1,268 @@ +use tauri::State; + +use crate::node::gossip; +use crate::node::NodeCommand; +use crate::protocol::messages::{GossipMessage, VoiceMediaState, VoiceParticipant}; +use crate::AppState; + +#[tauri::command] +pub async fn join_voice_channel( + state: State<'_, AppState>, + community_id: String, + channel_id: String, +) -> Result, String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + + let peer_id = id.peer_id.to_string(); + let display_name = id.display_name.clone(); + drop(identity); + + let media_state = VoiceMediaState { + muted: false, + deafened: false, + video_enabled: false, + screen_sharing: false, + }; + + // subscribe to the voice topic for this channel + let voice_topic = gossip::topic_for_voice(&community_id, &channel_id); + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let _ = handle + .command_tx + .send(NodeCommand::Subscribe { + topic: voice_topic.clone(), + }) + .await; + + // publish our join announcement + let msg = GossipMessage::VoiceJoin { + community_id: community_id.clone(), + channel_id: channel_id.clone(), + peer_id: peer_id.clone(), + display_name: display_name.clone(), + media_state: media_state.clone(), + }; + let data = + serde_json::to_vec(&msg).map_err(|e| format!("serialize error: {}", e))?; + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: voice_topic, + data, + }) + .await; + } + + // add ourselves to the local voice channel tracking + let key = format!("{}:{}", community_id, channel_id); + let mut vc = state.voice_channels.lock().await; + let participants = vc.entry(key.clone()).or_insert_with(Vec::new); + participants.retain(|p| p.peer_id != peer_id); + participants.push(VoiceParticipant { + peer_id, + display_name, + media_state, + }); + + let result = participants.clone(); + drop(vc); + + log::info!("joined voice channel {}:{}", community_id, channel_id); + + Ok(result) +} + +#[tauri::command] +pub async fn leave_voice_channel( + state: State<'_, AppState>, + community_id: String, + channel_id: String, +) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let peer_id = id.peer_id.to_string(); + drop(identity); + + let voice_topic = gossip::topic_for_voice(&community_id, &channel_id); + + // publish our leave announcement before unsubscribing + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let msg = GossipMessage::VoiceLeave { + community_id: community_id.clone(), + channel_id: channel_id.clone(), + peer_id: peer_id.clone(), + }; + let data = + serde_json::to_vec(&msg).map_err(|e| format!("serialize error: {}", e))?; + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: voice_topic.clone(), + data, + }) + .await; + + // unsubscribe from the voice topic + let _ = handle + .command_tx + .send(NodeCommand::Unsubscribe { + topic: voice_topic, + }) + .await; + } + + // remove ourselves from local tracking + let key = format!("{}:{}", community_id, channel_id); + let mut vc = state.voice_channels.lock().await; + if let Some(participants) = vc.get_mut(&key) { + participants.retain(|p| p.peer_id != peer_id); + if participants.is_empty() { + vc.remove(&key); + } + } + drop(vc); + + log::info!("left voice channel {}:{}", community_id, channel_id); + + Ok(()) +} + +#[tauri::command] +pub async fn update_voice_media_state( + state: State<'_, AppState>, + community_id: String, + channel_id: String, + media_state: VoiceMediaState, +) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let peer_id = id.peer_id.to_string(); + drop(identity); + + let voice_topic = gossip::topic_for_voice(&community_id, &channel_id); + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let msg = GossipMessage::VoiceMediaStateUpdate { + community_id: community_id.clone(), + channel_id: channel_id.clone(), + peer_id: peer_id.clone(), + media_state: media_state.clone(), + }; + let data = + serde_json::to_vec(&msg).map_err(|e| format!("serialize error: {}", e))?; + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: voice_topic, + data, + }) + .await; + } + + // update local tracking + let key = format!("{}:{}", community_id, channel_id); + let mut vc = state.voice_channels.lock().await; + if let Some(participants) = vc.get_mut(&key) { + if let Some(p) = participants.iter_mut().find(|p| p.peer_id == peer_id) { + p.media_state = media_state; + } + } + drop(vc); + + Ok(()) +} + +#[tauri::command] +pub async fn send_voice_sdp( + state: State<'_, AppState>, + community_id: String, + channel_id: String, + to_peer: String, + sdp_type: String, + sdp: String, +) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let from_peer = id.peer_id.to_string(); + drop(identity); + + let voice_topic = gossip::topic_for_voice(&community_id, &channel_id); + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let msg = GossipMessage::VoiceSdp { + community_id, + channel_id, + from_peer, + to_peer, + sdp_type, + sdp, + }; + let data = + serde_json::to_vec(&msg).map_err(|e| format!("serialize error: {}", e))?; + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: voice_topic, + data, + }) + .await; + } + + Ok(()) +} + +#[tauri::command] +pub async fn send_voice_ice_candidate( + state: State<'_, AppState>, + community_id: String, + channel_id: String, + to_peer: String, + candidate: String, + sdp_mid: Option, + sdp_mline_index: Option, +) -> Result<(), String> { + let identity = state.identity.lock().await; + let id = identity.as_ref().ok_or("no identity loaded")?; + let from_peer = id.peer_id.to_string(); + drop(identity); + + let voice_topic = gossip::topic_for_voice(&community_id, &channel_id); + let node_handle = state.node_handle.lock().await; + if let Some(ref handle) = *node_handle { + let msg = GossipMessage::VoiceIceCandidate { + community_id, + channel_id, + from_peer, + to_peer, + candidate, + sdp_mid, + sdp_mline_index, + }; + let data = + serde_json::to_vec(&msg).map_err(|e| format!("serialize error: {}", e))?; + let _ = handle + .command_tx + .send(NodeCommand::SendMessage { + topic: voice_topic, + data, + }) + .await; + } + + Ok(()) +} + +#[tauri::command] +pub async fn get_voice_participants( + state: State<'_, AppState>, + community_id: String, + channel_id: String, +) -> Result, String> { + let key = format!("{}:{}", community_id, channel_id); + let vc = state.voice_channels.lock().await; + let participants = vc.get(&key).cloned().unwrap_or_default(); + Ok(participants) +} diff --git a/src-tauri/src/crdt/document.rs b/src-tauri/src/crdt/document.rs index 6ceac07..c17907e 100644 --- a/src-tauri/src/crdt/document.rs +++ b/src-tauri/src/crdt/document.rs @@ -1,7 +1,7 @@ use automerge::{transaction::Transactable, AutoCommit, ObjType, ReadDoc, ROOT}; use std::time::{SystemTime, UNIX_EPOCH}; -use crate::protocol::community::{ChannelKind, ChannelMeta, CommunityMeta}; +use crate::protocol::community::{CategoryMeta, ChannelKind, ChannelMeta, CommunityMeta}; use crate::protocol::messages::ChatMessage; // initialize a new community document with metadata and a default general channel @@ -24,15 +24,20 @@ pub fn init_community_doc( doc.put(&meta, "created_at", now as i64)?; let channels = doc.put_object(ROOT, "channels", ObjType::Map)?; + let _categories = doc.put_object(ROOT, "categories", ObjType::Map)?; let members = doc.put_object(ROOT, "members", ObjType::Map)?; let _roles = doc.put_object(ROOT, "roles", ObjType::Map)?; // create a default general channel - let general_id = format!("ch_{}", &hex::encode(&sha2_hash(format!("{}_general", name).as_bytes()))[..12]); + let general_id = format!( + "ch_{}", + &hex::encode(&sha2_hash(format!("{}_general", name).as_bytes()))[..12] + ); let general = doc.put_object(&channels, &general_id, ObjType::Map)?; doc.put(&general, "name", "general")?; doc.put(&general, "topic", "general discussion")?; doc.put(&general, "kind", "text")?; + doc.put(&general, "position", 0i64)?; let _messages = doc.put_object(&general, "messages", ObjType::List)?; // add the creator as the first member with owner role @@ -55,6 +60,23 @@ pub fn add_channel( .map(|(_, id)| id) .ok_or_else(|| automerge::AutomergeError::InvalidObjId("channels not found".to_string()))?; + // calculate next position if channel.position is 0 + let position = if channel.position == 0 { + let keys: Vec = doc.keys(&channels).collect(); + keys.iter() + .filter_map(|k| { + doc.get(&channels, k) + .ok() + .flatten() + .and_then(|(_, id)| get_i64(doc, &id, "position")) + }) + .max() + .map(|p| p + 1) + .unwrap_or(0) as u32 + } else { + channel.position + }; + let ch = doc.put_object(&channels, &channel.id, ObjType::Map)?; doc.put(&ch, "name", channel.name.as_str())?; doc.put(&ch, "topic", channel.topic.as_str())?; @@ -66,11 +88,93 @@ pub fn add_channel( ChannelKind::Voice => "voice", }, )?; + doc.put(&ch, "position", position as i64)?; + if let Some(ref cat_id) = channel.category_id { + doc.put(&ch, "category_id", cat_id.as_str())?; + } let _messages = doc.put_object(&ch, "messages", ObjType::List)?; Ok(()) } +// add a new category to the community document +pub fn add_category( + doc: &mut AutoCommit, + category: &CategoryMeta, +) -> Result<(), automerge::AutomergeError> { + let categories = doc + .get(ROOT, "categories")? + .map(|(_, id)| id) + .ok_or_else(|| { + // backwards compat: create categories map if it doesnt exist yet + automerge::AutomergeError::InvalidObjId("categories not found".to_string()) + }); + + let categories = match categories { + Ok(id) => id, + Err(_) => doc.put_object(ROOT, "categories", ObjType::Map)?, + }; + + // calculate next position if category.position is 0 + let position = if category.position == 0 { + let keys: Vec = doc.keys(&categories).collect(); + keys.iter() + .filter_map(|k| { + doc.get(&categories, k) + .ok() + .flatten() + .and_then(|(_, id)| get_i64(doc, &id, "position")) + }) + .max() + .map(|p| p + 1) + .unwrap_or(0) as u32 + } else { + category.position + }; + + let cat = doc.put_object(&categories, &category.id, ObjType::Map)?; + doc.put(&cat, "name", category.name.as_str())?; + doc.put(&cat, "position", position as i64)?; + + Ok(()) +} + +// read all categories from the community document +pub fn get_categories(doc: &AutoCommit, community_id: &str) -> Result, String> { + let categories_obj = doc.get(ROOT, "categories").map_err(|e| e.to_string())?; + + // backwards compat: older docs may not have categories + let categories_obj = match categories_obj { + Some((_, id)) => id, + None => return Ok(Vec::new()), + }; + + let mut result = Vec::new(); + let keys = doc.keys(&categories_obj); + + for key in keys { + let cat_obj = doc + .get(&categories_obj, &key) + .map_err(|e| e.to_string())? + .map(|(_, id)| id); + + if let Some(cat_id) = cat_obj { + let name = get_str(doc, &cat_id, "name").unwrap_or_default(); + let position = get_i64(doc, &cat_id, "position").unwrap_or(0) as u32; + + result.push(CategoryMeta { + id: key.to_string(), + community_id: community_id.to_string(), + name, + position, + }); + } + } + + result.sort_by_key(|c| c.position); + Ok(result) +} + // read all channels from the community document pub fn get_channels(doc: &AutoCommit, community_id: &str) -> Result, String> { let channels_obj = doc @@ -96,6 +200,8 @@ pub fn get_channels(doc: &AutoCommit, community_id: &str) -> Result ChannelKind::Voice, _ => ChannelKind::Text, }; + let position = get_i64(doc, &ch_id, "position").unwrap_or(0) as u32; + let category_id = get_str(doc, &ch_id, "category_id"); result.push(ChannelMeta { id: key.to_string(), @@ -103,10 +209,15 @@ pub fn get_channels(doc: &AutoCommit, community_id: &str) -> Result Result Result, String> { + let channels_obj = doc + .get(ROOT, "channels") + .map_err(|e| e.to_string())? + .map(|(_, id)| id) + .ok_or("channels key not found")?; + + // update position for each channel + for (index, channel_id) in channel_ids.iter().enumerate() { + if let Some((_, ch_obj)) = doc + .get(&channels_obj, channel_id) + .map_err(|e| e.to_string())? + { + doc.put(&ch_obj, "position", index as i64) + .map_err(|e| e.to_string())?; + } + } + + // return updated channels sorted by position + get_channels(doc, community_id) +} + // -- helpers for reading automerge values -- fn get_str(doc: &AutoCommit, obj: &automerge::ObjId, key: &str) -> Option { @@ -270,7 +408,7 @@ pub fn get_message_by_id( .ok_or("channels key not found")?; let keys = doc.keys(&channels_obj); - + for channel_key in keys { let ch_obj = doc .get(&channels_obj, &channel_key) @@ -298,7 +436,8 @@ pub fn get_message_by_id( id: id.clone(), channel_id: channel_key.to_string(), author_id: get_str(doc, &msg_id, "author_id").unwrap_or_default(), - author_name: get_str(doc, &msg_id, "author_name").unwrap_or_default(), + author_name: get_str(doc, &msg_id, "author_name") + .unwrap_or_default(), content: get_str(doc, &msg_id, "content").unwrap_or_default(), timestamp: get_i64(doc, &msg_id, "timestamp").unwrap_or(0) as u64, edited: get_bool(doc, &msg_id, "edited").unwrap_or(false), @@ -315,10 +454,7 @@ pub fn get_message_by_id( } // delete a message by id from any channel in the community -pub fn delete_message_by_id( - doc: &mut AutoCommit, - message_id: &str, -) -> Result<(), String> { +pub fn delete_message_by_id(doc: &mut AutoCommit, message_id: &str) -> Result<(), String> { let channels_obj = doc .get(ROOT, "channels") .map_err(|e| e.to_string())? @@ -326,7 +462,7 @@ pub fn delete_message_by_id( .ok_or("channels key not found")?; let keys: Vec = doc.keys(&channels_obj).collect(); - + for channel_key in keys { let ch_obj = doc .get(&channels_obj, &channel_key) @@ -350,8 +486,7 @@ pub fn delete_message_by_id( if let Some(msg_obj_id) = msg_obj { let id = get_str(doc, &msg_obj_id, "id").unwrap_or_default(); if id == message_id { - doc.delete(&msgs_id, i) - .map_err(|e| e.to_string())?; + doc.delete(&msgs_id, i).map_err(|e| e.to_string())?; return Ok(()); } } @@ -364,9 +499,7 @@ pub fn delete_message_by_id( } // get all members from the community document -pub fn get_members( - doc: &AutoCommit, -) -> Result, String> { +pub fn get_members(doc: &AutoCommit) -> Result, String> { let members_obj = doc .get(ROOT, "members") .map_err(|e| e.to_string())? @@ -385,7 +518,7 @@ pub fn get_members( if let Some(member_id) = member_obj { let display_name = get_str(doc, &member_id, "display_name").unwrap_or_default(); let joined_at = get_i64(doc, &member_id, "joined_at").unwrap_or(0) as u64; - + // get roles list let roles: Vec = doc .get(&member_id, "roles") @@ -419,10 +552,7 @@ pub fn get_members( } // remove a member from the community -pub fn remove_member( - doc: &mut AutoCommit, - peer_id: &str, -) -> Result<(), String> { +pub fn remove_member(doc: &mut AutoCommit, peer_id: &str) -> Result<(), String> { let members_obj = doc .get(ROOT, "members") .map_err(|e| e.to_string())? diff --git a/src-tauri/src/crdt/mod.rs b/src-tauri/src/crdt/mod.rs index 6e0750f..55b616d 100644 --- a/src-tauri/src/crdt/mod.rs +++ b/src-tauri/src/crdt/mod.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use automerge::AutoCommit; -use crate::protocol::community::{ChannelMeta, CommunityMeta}; +use crate::protocol::community::{CategoryMeta, ChannelMeta, CommunityMeta}; use crate::protocol::messages::ChatMessage; use crate::storage::DiskStorage; @@ -91,6 +91,50 @@ impl CrdtEngine { document::get_channels(doc, community_id) } + // reorder channels in a community + pub fn reorder_channels( + &mut self, + community_id: &str, + channel_ids: &[String], + ) -> Result, String> { + let doc = self + .documents + .get_mut(community_id) + .ok_or("community not found")?; + + let channels = document::reorder_channels(doc, community_id, channel_ids)?; + self.persist(community_id)?; + Ok(channels) + } + + // add a category to a community + pub fn create_category( + &mut self, + community_id: &str, + category: &CategoryMeta, + ) -> Result<(), String> { + let doc = self + .documents + .get_mut(community_id) + .ok_or("community not found")?; + + document::add_category(doc, category) + .map_err(|e| format!("failed to add category: {}", e))?; + + self.persist(community_id)?; + Ok(()) + } + + // get all categories in a community + pub fn get_categories(&self, community_id: &str) -> Result, String> { + let doc = self + .documents + .get(community_id) + .ok_or("community not found")?; + + document::get_categories(doc, community_id) + } + // append a message to a channel within a community pub fn append_message( &mut self, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 5527864..c2cb315 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -3,12 +3,15 @@ mod crdt; mod node; mod protocol; mod storage; +mod verification; +use std::collections::HashMap; use std::sync::Arc; use tokio::sync::Mutex; use crate::crdt::CrdtEngine; use crate::protocol::identity::DuskIdentity; +use crate::protocol::messages::VoiceParticipant; use crate::storage::DiskStorage; // shared application state accessible from all tauri commands @@ -17,6 +20,8 @@ pub struct AppState { pub crdt_engine: Arc>, pub storage: Arc, pub node_handle: Arc>>, + // tracks which peers are in which voice channels, keyed by "community_id:channel_id" + pub voice_channels: Arc>>>, } impl AppState { @@ -36,6 +41,7 @@ impl AppState { crdt_engine, storage, node_handle: Arc::new(Mutex::new(None)), + voice_channels: Arc::new(Mutex::new(HashMap::new())), } } } @@ -48,6 +54,28 @@ pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .manage(AppState::new()) + .setup(|app| { + // grant microphone/camera permissions on linux webkitgtk + // without this, getUserMedia is denied by default + #[cfg(target_os = "linux")] + { + use tauri::Manager; + if let Some(window) = app.get_webview_window("main") { + window + .with_webview(|webview| { + use webkit2gtk::PermissionRequestExt; + use webkit2gtk::WebViewExt; + let wv = webview.inner(); + wv.connect_permission_request(|_webview, request| { + request.allow(); + true + }); + }) + .ok(); + } + } + Ok(()) + }) .invoke_handler(tauri::generate_handler![ commands::identity::has_identity, commands::identity::load_identity, @@ -67,6 +95,7 @@ pub fn run() { commands::chat::send_typing, commands::chat::start_node, commands::chat::stop_node, + commands::chat::check_internet_connectivity, commands::community::create_community, commands::community::join_community, commands::community::leave_community, @@ -77,6 +106,22 @@ pub fn run() { commands::community::delete_message, commands::community::kick_member, commands::community::generate_invite, + commands::community::reorder_channels, + commands::community::create_category, + commands::community::get_categories, + commands::voice::join_voice_channel, + commands::voice::leave_voice_channel, + commands::voice::update_voice_media_state, + commands::voice::send_voice_sdp, + commands::voice::send_voice_ice_candidate, + commands::voice::get_voice_participants, + commands::dm::send_dm, + commands::dm::get_dm_messages, + commands::dm::get_dm_conversations, + commands::dm::mark_dm_read, + commands::dm::delete_dm_conversation, + commands::dm::send_dm_typing, + commands::dm::open_dm_conversation, ]) .run(tauri::generate_context!()) .expect("error while running dusk"); diff --git a/src-tauri/src/node/gossip.rs b/src-tauri/src/node/gossip.rs index b677f6d..61ec51d 100644 --- a/src-tauri/src/node/gossip.rs +++ b/src-tauri/src/node/gossip.rs @@ -32,3 +32,42 @@ pub fn topic_for_directory() -> String { pub fn topic_for_sync() -> String { "dusk/sync".to_string() } + +// voice signaling topic for webrtc sdp/ice exchange and presence +pub fn topic_for_voice(community_id: &str, channel_id: &str) -> String { + format!( + "dusk/community/{}/channel/{}/voice", + community_id, channel_id + ) +} + +// personal inbox topic for receiving first-time dms from peers we haven't +// subscribed to yet. every peer subscribes to their own inbox on startup. +pub fn topic_for_dm_inbox(peer_id: &str) -> String { + format!("dusk/dm/inbox/{}", peer_id) +} + +// dm topic between two peers, sorted alphabetically so both peers derive the same topic +pub fn topic_for_dm(peer_a: &str, peer_b: &str) -> String { + let (first, second) = if peer_a < peer_b { + (peer_a, peer_b) + } else { + (peer_b, peer_a) + }; + format!("dusk/dm/{}/{}", first, second) +} + +// derive a stable conversation id from two peer ids +pub fn dm_conversation_id(peer_a: &str, peer_b: &str) -> String { + let (first, second) = if peer_a < peer_b { + (peer_a, peer_b) + } else { + (peer_b, peer_a) + }; + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + let mut hasher = DefaultHasher::new(); + first.hash(&mut hasher); + second.hash(&mut hasher); + format!("dm_{:016x}", hasher.finish()) +} diff --git a/src-tauri/src/node/mod.rs b/src-tauri/src/node/mod.rs index 7fe7d0e..d642f31 100644 --- a/src-tauri/src/node/mod.rs +++ b/src-tauri/src/node/mod.rs @@ -3,7 +3,7 @@ pub mod discovery; pub mod gossip; pub mod swarm; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use tauri::async_runtime::JoinHandle; use tauri::Emitter; @@ -11,12 +11,11 @@ use tokio::sync::Mutex; use crate::crdt::CrdtEngine; use crate::protocol::identity::DirectoryEntry; +use crate::verification; -// default relay address - override with DUSK_RELAY_ADDR env var -// format: /ip4//tcp//p2p/ -// left empty because 0.0.0.0 is a listen address, not a routable dial target. -// users must set DUSK_RELAY_ADDR to a reachable relay for WAN connectivity. -const DEFAULT_RELAY_ADDR: &str = ""; +// default public relay - override with DUSK_RELAY_ADDR env var +const DEFAULT_RELAY_ADDR: &str = + "/dns4/relay.duskchat.app/tcp/4001/p2p/12D3KooWGQkCkACcibJPKzus7Q6U1aYngfTuS4gwYwmJkJJtrSaw"; // relay reconnection parameters const RELAY_INITIAL_BACKOFF_SECS: u64 = 2; @@ -24,6 +23,9 @@ const RELAY_MAX_BACKOFF_SECS: u64 = 120; const RELAY_BACKOFF_MULTIPLIER: u64 = 2; // max time to hold pending rendezvous registrations before discarding (10 min) const PENDING_QUEUE_TTL_SECS: u64 = 600; +// grace period before warning the frontend about relay being down, +// prevents banner flashing on transient disconnections +const RELAY_WARN_GRACE_SECS: u64 = 8; // resolve the relay multiaddr from env or default fn relay_addr() -> Option { @@ -119,6 +121,50 @@ pub enum DuskEvent { }, #[serde(rename = "profile_revoked")] ProfileRevoked { peer_id: String }, + #[serde(rename = "relay_status")] + RelayStatus { connected: bool }, + #[serde(rename = "voice_participant_joined")] + VoiceParticipantJoined { + community_id: String, + channel_id: String, + peer_id: String, + display_name: String, + media_state: crate::protocol::messages::VoiceMediaState, + }, + #[serde(rename = "voice_participant_left")] + VoiceParticipantLeft { + community_id: String, + channel_id: String, + peer_id: String, + }, + #[serde(rename = "voice_media_state_changed")] + VoiceMediaStateChanged { + community_id: String, + channel_id: String, + peer_id: String, + media_state: crate::protocol::messages::VoiceMediaState, + }, + #[serde(rename = "voice_sdp_received")] + VoiceSdpReceived { + community_id: String, + channel_id: String, + from_peer: String, + sdp_type: String, + sdp: String, + }, + #[serde(rename = "voice_ice_candidate_received")] + VoiceIceCandidateReceived { + community_id: String, + channel_id: String, + from_peer: String, + candidate: String, + sdp_mid: Option, + sdp_mline_index: Option, + }, + #[serde(rename = "dm_received")] + DMReceived(crate::protocol::messages::DirectMessage), + #[serde(rename = "dm_typing")] + DMTyping { peer_id: String }, } // extract the community id from a gossipsub topic string @@ -128,12 +174,17 @@ fn community_id_from_topic(topic: &str) -> Option<&str> { .and_then(|rest| rest.split('/').next()) } +// voice channel participant tracking type alias for readability +pub type VoiceChannelMap = + Arc>>>; + // start the p2p node on a background task pub async fn start( keypair: libp2p::identity::Keypair, crdt_engine: Arc>, storage: Arc, app_handle: tauri::AppHandle, + voice_channels: VoiceChannelMap, ) -> Result { let mut swarm_instance = swarm::build_swarm(&keypair).map_err(|e| format!("failed to build swarm: {}", e))?; @@ -159,6 +210,9 @@ pub async fn start( let relay_peer_id = relay_multiaddr.as_ref().and_then(peer_id_from_multiaddr); // if a relay is configured, dial it immediately + // don't emit RelayStatus here -- the store defaults to connected=true so + // no warning shows during the initial handshake. the warning only appears + // if the dial actually fails (OutgoingConnectionError) or the connection drops. if let Some(ref addr) = relay_multiaddr { log::info!("dialing relay at {}", addr); if let Err(e) = swarm_instance.dial(addr.clone()) { @@ -172,6 +226,10 @@ pub async fn start( // track connected peers for accurate count let mut connected_peers: HashSet = HashSet::new(); + // dedup set for dm message ids -- messages arrive on both the pair topic + // and inbox topic so we need to skip duplicates + let mut seen_dm_ids: HashSet = HashSet::new(); + // track whether we have a relay reservation let mut relay_reservation_active = false; @@ -193,6 +251,9 @@ pub async fn start( // relay reconnection state with exponential backoff let mut relay_backoff_secs = RELAY_INITIAL_BACKOFF_SECS; + // deferred warning timer -- only notify the frontend after the grace + // period expires so transient disconnections don't flash the banner + let mut relay_warn_at: Option = None; // next instant at which we should attempt a relay reconnect let mut relay_retry_at: Option = if relay_multiaddr.is_some() { // schedule initial retry in case the first dial failed synchronously @@ -304,6 +365,18 @@ pub async fn start( }); } crate::protocol::messages::GossipMessage::ProfileAnnounce(profile) => { + // reject announcements with invalid signatures + if !verification::verify_announcement(&profile.public_key, &profile) { + log::warn!("rejected unsigned/invalid profile from {}", profile.peer_id); + continue; + } + + // reject unverified identities + if profile.verification_proof.is_none() { + log::warn!("rejected unverified profile from {}", profile.peer_id); + continue; + } + // cache the peer profile in our local directory let entry = DirectoryEntry { peer_id: profile.peer_id.clone(), @@ -326,6 +399,12 @@ pub async fn start( }); } crate::protocol::messages::GossipMessage::ProfileRevoke(revocation) => { + // reject revocations with invalid signatures + if !verification::verify_revocation(&revocation.public_key, &revocation) { + log::warn!("rejected unsigned revocation for {}", revocation.peer_id); + continue; + } + // peer is revoking their identity, remove them from our directory let _ = storage.remove_directory_entry(&revocation.peer_id); @@ -333,6 +412,133 @@ pub async fn start( peer_id: revocation.peer_id, }); } + crate::protocol::messages::GossipMessage::VoiceJoin { + community_id, channel_id, peer_id, display_name, media_state, + } => { + let participant = crate::protocol::messages::VoiceParticipant { + peer_id: peer_id.clone(), + display_name: display_name.clone(), + media_state: media_state.clone(), + }; + + // track the participant in shared voice state + let key = format!("{}:{}", community_id, channel_id); + let mut vc = voice_channels.lock().await; + let participants = vc.entry(key).or_insert_with(Vec::new); + // avoid duplicates if we receive a repeated join + participants.retain(|p| p.peer_id != peer_id); + participants.push(participant); + drop(vc); + + let _ = app_handle.emit("dusk-event", DuskEvent::VoiceParticipantJoined { + community_id, channel_id, peer_id, display_name, media_state, + }); + } + crate::protocol::messages::GossipMessage::VoiceLeave { + community_id, channel_id, peer_id, + } => { + let key = format!("{}:{}", community_id, channel_id); + let mut vc = voice_channels.lock().await; + if let Some(participants) = vc.get_mut(&key) { + participants.retain(|p| p.peer_id != peer_id); + if participants.is_empty() { + vc.remove(&key); + } + } + drop(vc); + + let _ = app_handle.emit("dusk-event", DuskEvent::VoiceParticipantLeft { + community_id, channel_id, peer_id, + }); + } + crate::protocol::messages::GossipMessage::VoiceMediaStateUpdate { + community_id, channel_id, peer_id, media_state, + } => { + // update tracked media state for this participant + let key = format!("{}:{}", community_id, channel_id); + let mut vc = voice_channels.lock().await; + if let Some(participants) = vc.get_mut(&key) { + if let Some(p) = participants.iter_mut().find(|p| p.peer_id == peer_id) { + p.media_state = media_state.clone(); + } + } + drop(vc); + + let _ = app_handle.emit("dusk-event", DuskEvent::VoiceMediaStateChanged { + community_id, channel_id, peer_id, media_state, + }); + } + crate::protocol::messages::GossipMessage::VoiceSdp { + community_id, channel_id, from_peer, to_peer, sdp_type, sdp, + } => { + // only forward sdp messages addressed to us + let local_id = swarm_instance.local_peer_id().to_string(); + if to_peer == local_id { + let _ = app_handle.emit("dusk-event", DuskEvent::VoiceSdpReceived { + community_id, channel_id, from_peer, sdp_type, sdp, + }); + } + } + crate::protocol::messages::GossipMessage::VoiceIceCandidate { + community_id, channel_id, from_peer, to_peer, candidate, sdp_mid, sdp_mline_index, + } => { + // only forward ice candidates addressed to us + let local_id = swarm_instance.local_peer_id().to_string(); + if to_peer == local_id { + let _ = app_handle.emit("dusk-event", DuskEvent::VoiceIceCandidateReceived { + community_id, channel_id, from_peer, candidate, sdp_mid, sdp_mline_index, + }); + } + } + crate::protocol::messages::GossipMessage::DirectMessage(dm_msg) => { + // only process dms addressed to us (ignore our own echoes) + let local_id = swarm_instance.local_peer_id().to_string(); + if dm_msg.to_peer == local_id { + // dedup: messages arrive on both the pair topic and inbox + // topic so skip if we've already processed this one + if !seen_dm_ids.insert(dm_msg.id.clone()) { + continue; + } + // cap the dedup set to prevent unbounded memory growth + if seen_dm_ids.len() > 10000 { + seen_dm_ids.clear(); + } + + // if this arrived on the inbox topic, the sender might be + // someone we've never dm'd before -- auto-subscribe to the + // pair topic so subsequent messages use the direct channel + if topic_str.starts_with("dusk/dm/inbox/") { + let pair_topic = gossip::topic_for_dm(&dm_msg.from_peer, &dm_msg.to_peer); + let ident_topic = libp2p::gossipsub::IdentTopic::new(pair_topic); + let _ = swarm_instance.behaviour_mut().gossipsub.subscribe(&ident_topic); + } + + // persist the incoming message + let conversation_id = gossip::dm_conversation_id(&dm_msg.from_peer, &dm_msg.to_peer); + let _ = storage.append_dm_message(&conversation_id, &dm_msg); + + // update or create conversation metadata + let existing = storage.load_dm_conversation(&conversation_id).ok(); + let meta = crate::protocol::messages::DMConversationMeta { + peer_id: dm_msg.from_peer.clone(), + display_name: dm_msg.from_display_name.clone(), + last_message: Some(dm_msg.content.clone()), + last_message_time: Some(dm_msg.timestamp), + unread_count: existing.map(|m| m.unread_count + 1).unwrap_or(1), + }; + let _ = storage.save_dm_conversation(&conversation_id, &meta); + + let _ = app_handle.emit("dusk-event", DuskEvent::DMReceived(dm_msg)); + } + } + crate::protocol::messages::GossipMessage::DMTyping(indicator) => { + let local_id = swarm_instance.local_peer_id().to_string(); + if indicator.to_peer == local_id { + let _ = app_handle.emit("dusk-event", DuskEvent::DMTyping { + peer_id: indicator.from_peer, + }); + } + } } } } @@ -388,6 +594,8 @@ pub async fn start( )) => { log::info!("relay reservation accepted by {}", relay_peer_id); relay_reservation_active = true; + relay_warn_at = None; + let _ = app_handle.emit("dusk-event", DuskEvent::RelayStatus { connected: true }); // now that we have a relay reservation, process any pending // rendezvous registrations that were queued before the relay was ready @@ -487,6 +695,13 @@ pub async fn start( if Some(failed_peer) == relay_peer { log::warn!("failed to connect to relay: {}", error); log::info!("scheduling relay reconnect in {}s", relay_backoff_secs); + // defer the warning so transient failures don't flash the banner + if relay_warn_at.is_none() { + relay_warn_at = Some( + tokio::time::Instant::now() + + std::time::Duration::from_secs(RELAY_WARN_GRACE_SECS), + ); + } relay_retry_at = Some( tokio::time::Instant::now() + std::time::Duration::from_secs(relay_backoff_secs), ); @@ -516,8 +731,11 @@ pub async fn start( if Some(peer_id) == relay_peer && !relay_reservation_active { // reset backoff on successful connection relay_backoff_secs = RELAY_INITIAL_BACKOFF_SECS; - // cancel any pending retry + // cancel any pending retry and deferred warning relay_retry_at = None; + relay_warn_at = None; + // clear the banner if it was already showing + let _ = app_handle.emit("dusk-event", DuskEvent::RelayStatus { connected: true }); if let Some(ref addr) = relay_multiaddr { let relay_circuit_addr = addr.clone() @@ -543,6 +761,33 @@ pub async fn start( libp2p::swarm::SwarmEvent::ConnectionClosed { peer_id, num_established, .. } => { if num_established == 0 { connected_peers.remove(&peer_id.to_string()); + + // remove disconnected peer from all voice channels and notify frontend + let peer_id_str = peer_id.to_string(); + let mut vc = voice_channels.lock().await; + let mut empty_keys = Vec::new(); + for (key, participants) in vc.iter_mut() { + let before_len = participants.len(); + participants.retain(|p| p.peer_id != peer_id_str); + if participants.len() < before_len { + // parse the key back into community_id and channel_id + if let Some((cid, chid)) = key.split_once(':') { + let _ = app_handle.emit("dusk-event", DuskEvent::VoiceParticipantLeft { + community_id: cid.to_string(), + channel_id: chid.to_string(), + peer_id: peer_id_str.clone(), + }); + } + } + if participants.is_empty() { + empty_keys.push(key.clone()); + } + } + for key in empty_keys { + vc.remove(&key); + } + drop(vc); + let _ = app_handle.emit("dusk-event", DuskEvent::PeerDisconnected { peer_id: peer_id.to_string(), }); @@ -556,6 +801,13 @@ pub async fn start( if Some(peer_id) == relay_peer { relay_reservation_active = false; log::warn!("lost connection to relay, scheduling reconnect in {}s", relay_backoff_secs); + // defer the warning so quick reconnections don't flash the banner + if relay_warn_at.is_none() { + relay_warn_at = Some( + tokio::time::Instant::now() + + std::time::Duration::from_secs(RELAY_WARN_GRACE_SECS), + ); + } relay_retry_at = Some( tokio::time::Instant::now() + std::time::Duration::from_secs(relay_backoff_secs), @@ -626,6 +878,18 @@ pub async fn start( } } + // deferred relay warning -- only tell the frontend after the grace + // period so transient disconnections don't flash the banner + _ = tokio::time::sleep_until( + relay_warn_at.unwrap_or_else(|| tokio::time::Instant::now() + std::time::Duration::from_secs(86400)) + ), if relay_warn_at.is_some() => { + relay_warn_at = None; + // grace period expired and we still don't have a relay connection + if !relay_reservation_active { + let _ = app_handle.emit("dusk-event", DuskEvent::RelayStatus { connected: false }); + } + } + cmd = command_rx.recv() => { match cmd { Some(NodeCommand::Shutdown) | None => break, diff --git a/src-tauri/src/node/swarm.rs b/src-tauri/src/node/swarm.rs index 5607d03..2e9512d 100644 --- a/src-tauri/src/node/swarm.rs +++ b/src-tauri/src/node/swarm.rs @@ -41,6 +41,8 @@ pub fn build_swarm( noise::Config::new, yamux::Config::default, )? + // resolve dns4/dns6 multiaddrs (needed for relay.duskchat.app) + .with_dns()? // add relay client transport so we can connect through relay circuits .with_relay_client(noise::Config::new, yamux::Config::default)? .with_behaviour(|key, relay_client| { @@ -71,10 +73,11 @@ pub fn build_swarm( kademlia, mdns, identify, - ping: ping::Behaviour::default(), + // ping every 30s to keep the relay connection alive + ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(30))), } })? - .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(60))) + .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(300))) .build(); Ok(swarm) diff --git a/src-tauri/src/protocol/community.rs b/src-tauri/src/protocol/community.rs index 84a1a95..36ed2e3 100644 --- a/src-tauri/src/protocol/community.rs +++ b/src-tauri/src/protocol/community.rs @@ -9,6 +9,15 @@ pub struct CommunityMeta { pub created_at: u64, } +// user-defined grouping for channels within a community +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CategoryMeta { + pub id: String, + pub community_id: String, + pub name: String, + pub position: u32, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChannelMeta { pub id: String, @@ -16,6 +25,9 @@ pub struct ChannelMeta { pub name: String, pub topic: String, pub kind: ChannelKind, + pub position: u32, + // channels without a category sit at the top level + pub category_id: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src-tauri/src/protocol/identity.rs b/src-tauri/src/protocol/identity.rs index e61113e..353b393 100644 --- a/src-tauri/src/protocol/identity.rs +++ b/src-tauri/src/protocol/identity.rs @@ -11,6 +11,7 @@ pub struct DuskIdentity { pub display_name: String, pub bio: String, pub created_at: u64, + pub verification_proof: Option, } impl DuskIdentity { @@ -29,6 +30,7 @@ impl DuskIdentity { display_name: display_name.to_string(), bio: bio.to_string(), created_at, + verification_proof: None, } } @@ -44,6 +46,7 @@ impl DuskIdentity { let peer_id = PeerId::from(keypair.public()); let profile = storage.load_profile().unwrap_or_default(); + let verification_proof = storage.load_verification_proof().ok().flatten(); Ok(Self { keypair, @@ -51,6 +54,7 @@ impl DuskIdentity { display_name: profile.display_name, bio: profile.bio, created_at: profile.created_at, + verification_proof, }) } @@ -86,6 +90,7 @@ impl DuskIdentity { public_key: hex::encode(public_key_bytes), bio: self.bio.clone(), created_at: self.created_at, + verification_proof: self.verification_proof.clone(), } } } @@ -97,6 +102,17 @@ pub struct PublicIdentity { pub public_key: String, pub bio: String, pub created_at: u64, + pub verification_proof: Option, +} + +// cryptographic proof that the identity was created through human verification +// the signature binds this proof to a specific keypair so it cannot be reused +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VerificationProof { + pub metrics_hash: String, + pub signature: String, + pub timestamp: u64, + pub score: f64, } // profile data stored on disk alongside the keypair diff --git a/src-tauri/src/protocol/messages.rs b/src-tauri/src/protocol/messages.rs index 91d0992..f0dde6c 100644 --- a/src-tauri/src/protocol/messages.rs +++ b/src-tauri/src/protocol/messages.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use super::identity::VerificationProof; + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatMessage { pub id: String, @@ -34,6 +36,8 @@ pub enum PeerStatus { } // peer profile announcement broadcast on the directory topic +// includes a verification proof and a signature over all fields +// so peers can reject unverified or spoofed identities #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProfileAnnouncement { pub peer_id: String, @@ -41,14 +45,64 @@ pub struct ProfileAnnouncement { pub bio: String, pub public_key: String, pub timestamp: u64, + pub verification_proof: Option, + pub signature: String, } // broadcast when a user resets their identity, tells peers to purge their data +// signed to prevent unauthorized revocation of another peer's identity #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProfileRevocation { pub peer_id: String, pub public_key: String, pub timestamp: u64, + pub signature: String, +} + +// media state for a participant in a voice channel +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VoiceMediaState { + pub muted: bool, + pub deafened: bool, + pub video_enabled: bool, + pub screen_sharing: bool, +} + +// a peer currently connected to a voice channel +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VoiceParticipant { + pub peer_id: String, + pub display_name: String, + pub media_state: VoiceMediaState, +} + +// a direct message between two peers +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DirectMessage { + pub id: String, + pub from_peer: String, + pub to_peer: String, + pub from_display_name: String, + pub content: String, + pub timestamp: u64, +} + +// typing indicator scoped to a dm conversation +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DMTypingIndicator { + pub from_peer: String, + pub to_peer: String, + pub timestamp: u64, +} + +// metadata for a persisted dm conversation +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DMConversationMeta { + pub peer_id: String, + pub display_name: String, + pub last_message: Option, + pub last_message_time: Option, + pub unread_count: u32, } // envelope for all gossipsub-published messages @@ -58,8 +112,49 @@ pub enum GossipMessage { Typing(TypingIndicator), Presence(PresenceUpdate), MetaUpdate(super::community::CommunityMeta), - DeleteMessage { message_id: String }, - MemberKicked { peer_id: String }, + DeleteMessage { + message_id: String, + }, + MemberKicked { + peer_id: String, + }, ProfileAnnounce(ProfileAnnouncement), ProfileRevoke(ProfileRevocation), + DirectMessage(DirectMessage), + DMTyping(DMTypingIndicator), + VoiceJoin { + community_id: String, + channel_id: String, + peer_id: String, + display_name: String, + media_state: VoiceMediaState, + }, + VoiceLeave { + community_id: String, + channel_id: String, + peer_id: String, + }, + VoiceMediaStateUpdate { + community_id: String, + channel_id: String, + peer_id: String, + media_state: VoiceMediaState, + }, + VoiceSdp { + community_id: String, + channel_id: String, + from_peer: String, + to_peer: String, + sdp_type: String, + sdp: String, + }, + VoiceIceCandidate { + community_id: String, + channel_id: String, + from_peer: String, + to_peer: String, + candidate: String, + sdp_mid: Option, + sdp_mline_index: Option, + }, } diff --git a/src-tauri/src/storage/disk.rs b/src-tauri/src/storage/disk.rs index 469484c..1b714c6 100644 --- a/src-tauri/src/storage/disk.rs +++ b/src-tauri/src/storage/disk.rs @@ -6,7 +6,8 @@ use std::io; use std::path::PathBuf; use crate::protocol::community::CommunityMeta; -use crate::protocol::identity::{DirectoryEntry, ProfileData}; +use crate::protocol::identity::{DirectoryEntry, ProfileData, VerificationProof}; +use crate::protocol::messages::{DMConversationMeta, DirectMessage}; // user settings that persist across sessions #[derive(Debug, Clone, Serialize, Deserialize)] @@ -56,6 +57,7 @@ impl DiskStorage { fs::create_dir_all(base_dir.join("identity"))?; fs::create_dir_all(base_dir.join("communities"))?; fs::create_dir_all(base_dir.join("directory"))?; + fs::create_dir_all(base_dir.join("dms"))?; Ok(Self { base_dir }) } @@ -110,6 +112,25 @@ impl DiskStorage { self.base_dir.join("identity/keypair.bin").exists() } + // -- verification proof -- + + pub fn save_verification_proof(&self, proof: &VerificationProof) -> Result<(), io::Error> { + let json = serde_json::to_string_pretty(proof) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + fs::write(self.base_dir.join("identity/verification.json"), json) + } + + pub fn load_verification_proof(&self) -> Result, io::Error> { + let path = self.base_dir.join("identity/verification.json"); + if !path.exists() { + return Ok(None); + } + let data = fs::read_to_string(path)?; + let proof = serde_json::from_str(&data) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Ok(Some(proof)) + } + // -- automerge documents -- pub fn save_document(&self, community_id: &str, doc_bytes: &[u8]) -> Result<(), io::Error> { @@ -225,7 +246,131 @@ impl DiskStorage { } } - // wipe all user data - identity, communities, directory, settings + // -- direct messages -- + + // save a dm conversation's metadata + pub fn save_dm_conversation( + &self, + conversation_id: &str, + meta: &DMConversationMeta, + ) -> Result<(), io::Error> { + let dir = self.base_dir.join(format!("dms/{}", conversation_id)); + fs::create_dir_all(&dir)?; + let json = serde_json::to_string_pretty(meta) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + fs::write(dir.join("meta.json"), json) + } + + // load a single dm conversation's metadata + pub fn load_dm_conversation( + &self, + conversation_id: &str, + ) -> Result { + let path = self + .base_dir + .join(format!("dms/{}/meta.json", conversation_id)); + let data = fs::read_to_string(path)?; + serde_json::from_str(&data).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) + } + + // load all dm conversations + pub fn load_all_dm_conversations( + &self, + ) -> Result, io::Error> { + let dms_dir = self.base_dir.join("dms"); + if !dms_dir.exists() { + return Ok(Vec::new()); + } + + let mut conversations = Vec::new(); + for entry in fs::read_dir(dms_dir)? { + let entry = entry?; + if entry.file_type()?.is_dir() { + if let Some(conv_id) = entry.file_name().to_str() { + let meta_path = entry.path().join("meta.json"); + if meta_path.exists() { + if let Ok(data) = fs::read_to_string(&meta_path) { + if let Ok(meta) = serde_json::from_str::(&data) { + conversations.push((conv_id.to_string(), meta)); + } + } + } + } + } + } + Ok(conversations) + } + + // remove a dm conversation and all its messages + pub fn remove_dm_conversation(&self, conversation_id: &str) -> Result<(), io::Error> { + let dir = self.base_dir.join(format!("dms/{}", conversation_id)); + if dir.exists() { + fs::remove_dir_all(&dir)?; + } + Ok(()) + } + + // append a message to a dm conversation's message log + pub fn append_dm_message( + &self, + conversation_id: &str, + message: &DirectMessage, + ) -> Result<(), io::Error> { + let dir = self.base_dir.join(format!("dms/{}", conversation_id)); + fs::create_dir_all(&dir)?; + + let messages_path = dir.join("messages.json"); + let mut messages: Vec = if messages_path.exists() { + let data = fs::read_to_string(&messages_path)?; + serde_json::from_str(&data).unwrap_or_default() + } else { + Vec::new() + }; + + messages.push(message.clone()); + + let json = serde_json::to_string_pretty(&messages) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + fs::write(&messages_path, json) + } + + // load dm messages with optional pagination + pub fn load_dm_messages( + &self, + conversation_id: &str, + before: Option, + limit: usize, + ) -> Result, io::Error> { + let messages_path = self + .base_dir + .join(format!("dms/{}/messages.json", conversation_id)); + if !messages_path.exists() { + return Ok(Vec::new()); + } + + let data = fs::read_to_string(&messages_path)?; + let messages: Vec = serde_json::from_str(&data) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + let filtered: Vec = if let Some(before_ts) = before { + messages + .into_iter() + .filter(|m| m.timestamp < before_ts) + .collect() + } else { + messages + }; + + // return the last `limit` messages (most recent) + let start = if filtered.len() > limit { + filtered.len() - limit + } else { + 0 + }; + Ok(filtered[start..].to_vec()) + } + + // wipe all user data - identity, communities, directory, dms, settings // used when resetting identity to leave no traces on this client pub fn wipe_all_data(&self) -> Result<(), io::Error> { let identity_dir = self.base_dir.join("identity"); @@ -243,10 +388,16 @@ impl DiskStorage { fs::remove_dir_all(&directory_dir)?; } + let dms_dir = self.base_dir.join("dms"); + if dms_dir.exists() { + fs::remove_dir_all(&dms_dir)?; + } + // recreate the directory tree so the app can still function fs::create_dir_all(self.base_dir.join("identity"))?; fs::create_dir_all(self.base_dir.join("communities"))?; fs::create_dir_all(self.base_dir.join("directory"))?; + fs::create_dir_all(self.base_dir.join("dms"))?; Ok(()) } diff --git a/src-tauri/src/verification/mod.rs b/src-tauri/src/verification/mod.rs new file mode 100644 index 0000000..3041637 --- /dev/null +++ b/src-tauri/src/verification/mod.rs @@ -0,0 +1,436 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +use libp2p::identity; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; + +use crate::protocol::identity::VerificationProof; +use crate::protocol::messages::{ProfileAnnouncement, ProfileRevocation}; + +// -- challenge data structures received from the frontend -- + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MouseSample { + pub x: f64, + pub y: f64, + pub t: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SegmentData { + pub from_target: u32, + pub to_target: u32, + pub samples: Vec, + pub click_time: f64, + pub start_time: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TargetCircle { + pub id: u32, + pub x: f64, + pub y: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ChallengeSubmission { + pub segments: Vec, + pub circles: Vec, + pub total_start_time: f64, + pub total_end_time: f64, +} + +pub struct AnalysisResult { + pub is_human: bool, + pub score: f64, +} + +const HUMAN_THRESHOLD: f64 = 0.35; + +// -- behavioral analysis functions -- +// these mirror the typescript implementations exactly, running in compiled rust +// so the analysis logic is not exposed in the inspectable webview + +fn score_timing_variance(segments: &[SegmentData]) -> f64 { + if segments.len() < 2 { + return 0.0; + } + + let intervals: Vec = segments.iter().map(|s| s.click_time - s.start_time).collect(); + let mean = intervals.iter().sum::() / intervals.len() as f64; + if mean == 0.0 { + return 0.0; + } + + let variance = intervals.iter().map(|v| (v - mean).powi(2)).sum::() / intervals.len() as f64; + let cv = variance.sqrt() / mean; + + // humans have natural variance in click timing + // bots tend to be metronomic or instantaneous + if cv < 0.03 { + 0.0 + } else if cv < 0.08 { + 0.3 + } else if cv < 0.12 { + 0.6 + } else { + 1.0 + } +} + +fn score_path_curvature(segments: &[SegmentData]) -> f64 { + let mut ratios = Vec::new(); + + for seg in segments { + if seg.samples.len() < 3 { + continue; + } + + let first = &seg.samples[0]; + let last = &seg.samples[seg.samples.len() - 1]; + let straight_dist = ((last.x - first.x).powi(2) + (last.y - first.y).powi(2)).sqrt(); + + // skip very short movements where curvature is meaningless + if straight_dist < 10.0 { + continue; + } + + let mut path_length = 0.0; + for i in 1..seg.samples.len() { + let dx = seg.samples[i].x - seg.samples[i - 1].x; + let dy = seg.samples[i].y - seg.samples[i - 1].y; + path_length += (dx * dx + dy * dy).sqrt(); + } + + ratios.push(path_length / straight_dist); + } + + if ratios.is_empty() { + return 0.0; + } + + let avg_ratio = ratios.iter().sum::() / ratios.len() as f64; + + // humans never move in perfectly straight lines + if avg_ratio < 1.02 { + 0.0 + } else if avg_ratio < 1.06 { + 0.3 + } else if avg_ratio < 1.10 { + 0.6 + } else if avg_ratio > 4.0 { + 0.5 + } else { + 1.0 + } +} + +fn score_speed_variance(segments: &[SegmentData]) -> f64 { + let mut all_speed_cvs = Vec::new(); + + for seg in segments { + if seg.samples.len() < 5 { + continue; + } + + let mut speeds = Vec::new(); + for i in 1..seg.samples.len() { + let dx = seg.samples[i].x - seg.samples[i - 1].x; + let dy = seg.samples[i].y - seg.samples[i - 1].y; + let dt = seg.samples[i].t - seg.samples[i - 1].t; + if dt > 0.0 { + speeds.push((dx * dx + dy * dy).sqrt() / dt); + } + } + + if speeds.len() < 3 { + continue; + } + + let mean = speeds.iter().sum::() / speeds.len() as f64; + if mean == 0.0 { + continue; + } + + let variance = speeds.iter().map(|v| (v - mean).powi(2)).sum::() / speeds.len() as f64; + let cv = variance.sqrt() / mean; + all_speed_cvs.push(cv); + } + + if all_speed_cvs.is_empty() { + return 0.0; + } + + let avg_cv = all_speed_cvs.iter().sum::() / all_speed_cvs.len() as f64; + + // humans accelerate and decelerate naturally + if avg_cv < 0.1 { + 0.0 + } else if avg_cv < 0.25 { + 0.4 + } else if avg_cv < 0.4 { + 0.7 + } else { + 1.0 + } +} + +fn score_approach_jitter(segments: &[SegmentData], circles: &[TargetCircle]) -> f64 { + let mut jitter_scores = Vec::new(); + + for (i, seg) in segments.iter().enumerate() { + if i >= circles.len() || seg.samples.len() < 5 { + continue; + } + + let target = &circles[i]; + + // isolate the last stretch approaching the target + let approach_samples: Vec<&MouseSample> = seg + .samples + .iter() + .filter(|s| { + let dx = s.x - target.x; + let dy = s.y - target.y; + (dx * dx + dy * dy).sqrt() < 60.0 + }) + .collect(); + + if approach_samples.len() < 4 { + continue; + } + + // count direction changes via cross product sign flips + let mut direction_changes = 0u32; + for j in 2..approach_samples.len() { + let dx1 = approach_samples[j - 1].x - approach_samples[j - 2].x; + let dy1 = approach_samples[j - 1].y - approach_samples[j - 2].y; + let dx2 = approach_samples[j].x - approach_samples[j - 1].x; + let dy2 = approach_samples[j].y - approach_samples[j - 1].y; + + let cross = dx1 * dy2 - dy1 * dx2; + if j > 2 { + let prev_dx1 = approach_samples[j - 2].x - approach_samples[j - 3].x; + let prev_dy1 = approach_samples[j - 2].y - approach_samples[j - 3].y; + let prev_cross = prev_dx1 * dy1 - prev_dy1 * dx1; + if cross * prev_cross < 0.0 { + direction_changes += 1; + } + } + } + + let jitter_ratio = direction_changes as f64 / (approach_samples.len() - 2).max(1) as f64; + jitter_scores.push(jitter_ratio); + } + + // not enough data to judge, give a neutral score + if jitter_scores.is_empty() { + return 0.5; + } + + let avg_jitter = jitter_scores.iter().sum::() / jitter_scores.len() as f64; + + // humans have micro-corrections from motor noise + if avg_jitter < 0.01 { + 0.2 + } else if avg_jitter < 0.05 { + 0.5 + } else { + 1.0 + } +} + +fn score_overall_timing(total_start: f64, total_end: f64) -> f64 { + let total_sec = (total_end - total_start) / 1000.0; + + if total_sec < 0.8 { + 0.0 + } else if total_sec < 1.5 { + 0.3 + } else if total_sec > 60.0 { + 0.5 + } else { + 1.0 + } +} + +pub fn analyze_challenge(data: &ChallengeSubmission) -> AnalysisResult { + let timing = score_timing_variance(&data.segments); + let curvature = score_path_curvature(&data.segments); + let speed = score_speed_variance(&data.segments); + let jitter = score_approach_jitter(&data.segments, &data.circles); + let overall = score_overall_timing(data.total_start_time, data.total_end_time); + + let score = timing * 0.25 + curvature * 0.25 + speed * 0.20 + jitter * 0.20 + overall * 0.10; + + AnalysisResult { + is_human: score >= HUMAN_THRESHOLD, + score, + } +} + +// -- proof generation -- + +pub fn generate_proof( + challenge: &ChallengeSubmission, + keypair: &identity::Keypair, + peer_id: &str, +) -> Result { + let result = analyze_challenge(challenge); + if !result.is_human { + return Err("behavioral analysis did not pass human threshold".to_string()); + } + + // hash the raw challenge data to create a fingerprint + let challenge_bytes = + serde_json::to_vec(challenge).map_err(|e| format!("failed to serialize challenge: {}", e))?; + let mut hasher = Sha256::new(); + hasher.update(&challenge_bytes); + let metrics_hash = hex::encode(hasher.finalize()); + + let timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64; + + // sign (metrics_hash || peer_id || timestamp) to bind the proof to this keypair + let sign_payload = format!("{}||{}||{}", metrics_hash, peer_id, timestamp); + let signature = keypair + .sign(sign_payload.as_bytes()) + .map_err(|e| format!("failed to sign proof: {}", e))?; + + Ok(VerificationProof { + metrics_hash, + signature: hex::encode(signature), + timestamp, + score: result.score, + }) +} + +// -- profile announcement signing -- + +// build the canonical payload that gets signed for an announcement +fn announcement_sign_payload( + peer_id: &str, + display_name: &str, + bio: &str, + public_key: &str, + timestamp: u64, + metrics_hash: &str, +) -> Vec { + format!( + "dusk-announce||{}||{}||{}||{}||{}||{}", + peer_id, display_name, bio, public_key, timestamp, metrics_hash + ) + .into_bytes() +} + +pub fn sign_announcement(keypair: &identity::Keypair, announcement: &ProfileAnnouncement) -> String { + let metrics_hash = announcement + .verification_proof + .as_ref() + .map(|p| p.metrics_hash.as_str()) + .unwrap_or(""); + + let payload = announcement_sign_payload( + &announcement.peer_id, + &announcement.display_name, + &announcement.bio, + &announcement.public_key, + announcement.timestamp, + metrics_hash, + ); + + match keypair.sign(&payload) { + Ok(sig) => hex::encode(sig), + Err(e) => { + log::error!("failed to sign announcement: {}", e); + String::new() + } + } +} + +pub fn verify_announcement(public_key_hex: &str, announcement: &ProfileAnnouncement) -> bool { + let pk_bytes = match hex::decode(public_key_hex) { + Ok(b) => b, + Err(_) => return false, + }; + + let public_key = match identity::PublicKey::try_decode_protobuf(&pk_bytes) { + Ok(pk) => pk, + Err(_) => return false, + }; + + let sig_bytes = match hex::decode(&announcement.signature) { + Ok(b) => b, + Err(_) => return false, + }; + + let metrics_hash = announcement + .verification_proof + .as_ref() + .map(|p| p.metrics_hash.as_str()) + .unwrap_or(""); + + let payload = announcement_sign_payload( + &announcement.peer_id, + &announcement.display_name, + &announcement.bio, + &announcement.public_key, + announcement.timestamp, + metrics_hash, + ); + + public_key.verify(&payload, &sig_bytes) +} + +// -- profile revocation signing -- + +fn revocation_sign_payload(peer_id: &str, public_key: &str, timestamp: u64) -> Vec { + format!("dusk-revoke||{}||{}||{}", peer_id, public_key, timestamp).into_bytes() +} + +pub fn sign_revocation(keypair: &identity::Keypair, revocation: &ProfileRevocation) -> String { + let payload = revocation_sign_payload( + &revocation.peer_id, + &revocation.public_key, + revocation.timestamp, + ); + + match keypair.sign(&payload) { + Ok(sig) => hex::encode(sig), + Err(e) => { + log::error!("failed to sign revocation: {}", e); + String::new() + } + } +} + +pub fn verify_revocation(public_key_hex: &str, revocation: &ProfileRevocation) -> bool { + let pk_bytes = match hex::decode(public_key_hex) { + Ok(b) => b, + Err(_) => return false, + }; + + let public_key = match identity::PublicKey::try_decode_protobuf(&pk_bytes) { + Ok(pk) => pk, + Err(_) => return false, + }; + + let sig_bytes = match hex::decode(&revocation.signature) { + Ok(b) => b, + Err(_) => return false, + }; + + let payload = revocation_sign_payload( + &revocation.peer_id, + &revocation.public_key, + revocation.timestamp, + ); + + public_key.verify(&payload, &sig_bytes) +} diff --git a/src/App.tsx b/src/App.tsx index f5d931d..5f0c003 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,13 @@ -import { Component, onMount, onCleanup, createSignal, Show } from "solid-js"; +import { + Component, + onMount, + onCleanup, + createSignal, + createEffect, + on, + Show, + For, +} from "solid-js"; import AppLayout from "./components/layout/AppLayout"; import OverlayMenu from "./components/navigation/OverlayMenu"; import MobileNav from "./components/navigation/MobileNav"; @@ -6,7 +15,10 @@ import Modal from "./components/common/Modal"; import Button from "./components/common/Button"; import SettingsModal from "./components/settings/SettingsModal"; import SignUpScreen from "./components/auth/SignUpScreen"; +import SplashScreen from "./components/auth/SplashScreen"; import UserDirectoryModal from "./components/directory/UserDirectoryModal"; +import ProfileCard from "./components/common/ProfileCard"; +import ProfileModal from "./components/common/ProfileModal"; import { overlayMenuOpen, @@ -28,6 +40,9 @@ import { setChannels, setActiveChannel, activeChannelId, + setCategories, + addCategory, + categories, } from "./stores/channels"; import { addMessage, @@ -46,6 +61,8 @@ import { setPeerCount, setNodeStatus, setIsConnected, + setRelayConnected, + relayConnected, } from "./stores/connection"; import { setDMConversations, @@ -53,6 +70,12 @@ import { addDMMessage, setActiveDM, updateDMLastMessage, + handleIncomingDM, + addDMTypingPeer, + clearDMTypingPeers, + clearDMMessages, + setDMMessages, + updateDMPeerDisplayName, } from "./stores/dms"; import { setKnownPeers, @@ -61,9 +84,21 @@ import { removePeer, clearDirectory, } from "./stores/directory"; +import { + handleVoiceParticipantJoined, + handleVoiceParticipantLeft, + handleVoiceMediaStateChanged, + handleVoiceSdpReceived, + handleVoiceIceCandidateReceived, +} from "./stores/voice"; import * as tauri from "./lib/tauri"; -import type { DuskEvent } from "./lib/types"; +import type { + DuskEvent, + ChallengeExport, + ChannelMeta, + DirectMessage, +} from "./lib/types"; import { resetSettings } from "./stores/settings"; const App: Component = () => { @@ -73,11 +108,101 @@ const App: Component = () => { const [tauriAvailable, setTauriAvailable] = createSignal(false); const [needsSignUp, setNeedsSignUp] = createSignal(false); const [appReady, setAppReady] = createSignal(false); + const [showSplash, setShowSplash] = createSignal(true); const [newCommunityName, setNewCommunityName] = createSignal(""); const [newCommunityDesc, setNewCommunityDesc] = createSignal(""); const [joinInviteCode, setJoinInviteCode] = createSignal(""); const [newChannelName, setNewChannelName] = createSignal(""); const [newChannelTopic, setNewChannelTopic] = createSignal(""); + const [newChannelKind, setNewChannelKind] = createSignal<"Text" | "Voice">( + "Text", + ); + const [newChannelCategoryId, setNewChannelCategoryId] = createSignal< + string | null + >(null); + const [newCategoryName, setNewCategoryName] = createSignal(""); + + // react to community switches by loading channels, members, and selecting first channel + createEffect( + on(activeCommunityId, async (communityId, prev) => { + if (communityId === prev) return; + if (!communityId) { + setChannels([]); + setCategories([]); + setActiveChannel(null); + clearMessages(); + setMembers([]); + return; + } + + if (tauriAvailable()) { + try { + const [chs, cats] = await Promise.all([ + tauri.getChannels(communityId), + tauri.getCategories(communityId), + ]); + setChannels(chs); + setCategories(cats); + + if (chs.length > 0) { + setActiveChannel(chs[0].id); + } else { + setActiveChannel(null); + clearMessages(); + } + + const mems = await tauri.getMembers(communityId); + setMembers(mems); + } catch (e) { + console.error("failed to load community data:", e); + } + } + }), + ); + + // react to channel switches by loading messages for the new channel + createEffect( + on(activeChannelId, async (channelId, prev) => { + if (channelId === prev) return; + if (!channelId) { + clearMessages(); + return; + } + + if (tauriAvailable()) { + try { + clearMessages(); + const msgs = await tauri.getMessages(channelId); + setMessages(msgs); + } catch (e) { + console.error("failed to load messages:", e); + } + } + }), + ); + + // react to dm switches by loading messages for the selected peer + createEffect( + on(activeDMPeerId, async (peerId, prev) => { + if (peerId === prev) return; + clearDMTypingPeers(); + + if (!peerId) { + clearDMMessages(); + return; + } + + if (tauriAvailable()) { + try { + clearDMMessages(); + const msgs = await tauri.getDMMessages(peerId); + setDMMessages(msgs); + } catch (e) { + console.error("failed to load dm messages:", e); + } + } + }), + ); onMount(async () => { cleanupResize = initResponsive(); @@ -142,6 +267,14 @@ const App: Component = () => { // directory not populated yet, that's fine } + // load existing dm conversations from disk + try { + const convos = await tauri.getDMConversations(); + setDMConversations(convos); + } catch { + // no dm history yet, that's fine + } + const communities = await tauri.getCommunities(); setCommunities(communities); @@ -157,19 +290,10 @@ const App: Component = () => { // from the backend will set the accurate state once peers are found. setNodeStatus("running"); + // the createEffect on activeCommunityId handles loading channels, + // messages, and members reactively when this is set if (communities.length > 0) { setActiveCommunity(communities[0].id); - const channels = await tauri.getChannels(communities[0].id); - setChannels(channels); - - if (channels.length > 0) { - setActiveChannel(channels[0].id); - const messages = await tauri.getMessages(channels[0].id); - setMessages(messages); - } - - const members = await tauri.getMembers(communities[0].id); - setMembers(members); } } catch (e) { console.error("initialization error:", e); @@ -219,11 +343,43 @@ const App: Component = () => { event.payload.display_name, event.payload.bio, ); + // keep dm conversation names in sync + updateDMPeerDisplayName( + event.payload.peer_id, + event.payload.display_name, + ); break; case "profile_revoked": // peer revoked their identity, remove them from our local directory removePeer(event.payload.peer_id); break; + case "relay_status": + setRelayConnected(event.payload.connected); + break; + case "dm_received": + handleIncomingDM(event.payload); + break; + case "dm_typing": + // only show typing if the sender is the active dm peer + if (event.payload.peer_id === activeDMPeerId()) { + addDMTypingPeer(event.payload.peer_id); + } + break; + case "voice_participant_joined": + handleVoiceParticipantJoined(event.payload); + break; + case "voice_participant_left": + handleVoiceParticipantLeft(event.payload); + break; + case "voice_media_state_changed": + handleVoiceMediaStateChanged(event.payload); + break; + case "voice_sdp_received": + handleVoiceSdpReceived(event.payload); + break; + case "voice_ice_candidate_received": + handleVoiceIceCandidateReceived(event.payload); + break; } } @@ -269,23 +425,38 @@ const App: Component = () => { tauri.sendTypingIndicator(channelId).catch(() => {}); } - function handleSendDM(content: string) { + async function handleSendDM(content: string) { const peerId = activeDMPeerId(); if (!peerId) return; - const id = identity(); - const msg = { - id: `dm_${Date.now()}`, - channel_id: `dm_${peerId}`, - author_id: id?.peer_id ?? "local", - author_name: id?.display_name ?? "you", - content, - timestamp: Date.now(), - edited: false, - }; + if (tauriAvailable()) { + try { + const msg = await tauri.sendDM(peerId, content); + addDMMessage(msg); + updateDMLastMessage(peerId, content, msg.timestamp); + } catch (e) { + console.error("failed to send dm:", e); + } + } else { + // demo mode fallback + const id = identity(); + const msg: DirectMessage = { + id: `dm_${Date.now()}`, + from_peer: id?.peer_id ?? "local", + to_peer: peerId, + from_display_name: id?.display_name ?? "you", + content, + timestamp: Date.now(), + }; + addDMMessage(msg); + updateDMLastMessage(peerId, content, msg.timestamp); + } + } - addDMMessage(msg); - updateDMLastMessage(peerId, content, msg.timestamp); + function handleDMTyping() { + const peerId = activeDMPeerId(); + if (!peerId || !tauriAvailable()) return; + tauri.sendDMTyping(peerId).catch(() => {}); } function handleOverlayNavigate(action: string) { @@ -318,17 +489,8 @@ const App: Component = () => { try { const community = await tauri.createCommunity(name, desc); addCommunity(community); + // the createEffect on activeCommunityId handles loading channels, messages, members setActiveCommunity(community.id); - - const channels = await tauri.getChannels(community.id); - setChannels(channels); - if (channels.length > 0) { - setActiveChannel(channels[0].id); - clearMessages(); - } - - const members = await tauri.getMembers(community.id); - setMembers(members); } catch (e) { console.error("failed to create community:", e); } @@ -350,6 +512,8 @@ const App: Component = () => { name: "general", topic: "general discussion", kind: "Text", + position: 0, + category_id: null, }, ]); setActiveChannel(chId); @@ -379,17 +543,8 @@ const App: Component = () => { try { const community = await tauri.joinCommunity(inviteCode); addCommunity(community); + // the createEffect on activeCommunityId handles loading channels, messages, members setActiveCommunity(community.id); - - const channels = await tauri.getChannels(community.id); - setChannels(channels); - if (channels.length > 0) { - setActiveChannel(channels[0].id); - clearMessages(); - } - - const members = await tauri.getMembers(community.id); - setMembers(members); } catch (e) { console.error("failed to join community:", e); } @@ -412,6 +567,8 @@ const App: Component = () => { name: "general", topic: "general discussion", kind: "Text", + position: 0, + category_id: null, }, ]); setActiveChannel(chId); @@ -435,35 +592,78 @@ const App: Component = () => { async function handleCreateChannel() { const name = newChannelName().trim(); const topic = newChannelTopic().trim(); + const kind = newChannelKind(); + const categoryId = newChannelCategoryId(); const communityId = activeCommunityId(); if (!name || !communityId) return; if (tauriAvailable()) { try { - const channel = await tauri.createChannel(communityId, name, topic); + const channel = await tauri.createChannel( + communityId, + name, + topic, + kind.toLowerCase(), + categoryId, + ); setChannels((prev) => [...prev, channel]); - setActiveChannel(channel.id); - clearMessages(); + // only auto-select text channels after creation + if (channel.kind === "Text") { + setActiveChannel(channel.id); + } } catch (e) { console.error("failed to create channel:", e); } } else { // demo mode const chId = `ch_${name.toLowerCase().replace(/\s+/g, "_")}_${Date.now()}`; - const channel = { + const channel: ChannelMeta = { id: chId, community_id: communityId, name, topic: topic || `${name} discussion`, - kind: "Text" as const, + kind, + position: 0, + category_id: categoryId, }; setChannels((prev) => [...prev, channel]); - setActiveChannel(chId); - clearMessages(); + if (kind === "Text") { + setActiveChannel(chId); + clearMessages(); + } } setNewChannelName(""); setNewChannelTopic(""); + setNewChannelKind("Text"); + setNewChannelCategoryId(null); + closeModal(); + } + + async function handleCreateCategory() { + const name = newCategoryName().trim(); + const communityId = activeCommunityId(); + if (!name || !communityId) return; + + if (tauriAvailable()) { + try { + const category = await tauri.createCategory(communityId, name); + addCategory(category); + } catch (e) { + console.error("failed to create category:", e); + } + } else { + // demo mode + const catId = `cat_${name.toLowerCase().replace(/\s+/g, "_")}_${Date.now()}`; + addCategory({ + id: catId, + community_id: communityId, + name, + position: 0, + }); + } + + setNewCategoryName(""); closeModal(); } @@ -487,10 +687,18 @@ const App: Component = () => { closeModal(); } - async function handleSignUpComplete(displayName: string, bio: string) { + async function handleSignUpComplete( + displayName: string, + bio: string, + challengeData?: ChallengeExport, + ) { if (tauriAvailable()) { try { - const created = await tauri.createIdentity(displayName, bio); + const created = await tauri.createIdentity( + displayName, + bio, + challengeData, + ); setCurrentIdentity(created); updateSettings({ display_name: displayName }); @@ -532,13 +740,16 @@ const App: Component = () => { setCommunities([]); setActiveCommunity(null); setChannels([]); + setCategories([]); setActiveChannel(null); clearMessages(); setMembers([]); setDMConversations([]); setActiveDM(null); + clearDMTypingPeers(); setPeerCount(0); setIsConnected(false); + setRelayConnected(true); setNodeStatus("stopped"); localStorage.removeItem("dusk_user_settings"); @@ -553,6 +764,14 @@ const App: Component = () => { return (

+ + setShowSplash(false)} + identity={identity()} + relayConnected={relayConnected()} + /> + + @@ -563,8 +782,12 @@ const App: Component = () => { onSendMessage={handleSendMessage} onTyping={handleTyping} onSendDM={handleSendDM} + onDMTyping={handleDMTyping} /> + + + { title="create channel" >
+ {/* channel type selector */} +
+ +
+ + +
+
+
+ + {/* category selector */} + 0}> +
+ + +
+
+
+ +
+
+ + setNewCategoryName(e.currentTarget.value)} + /> +
+ +
+
+ + + + + + + + diff --git a/src/components/auth/HumanVerification.tsx b/src/components/auth/HumanVerification.tsx new file mode 100644 index 0000000..f1759f4 --- /dev/null +++ b/src/components/auth/HumanVerification.tsx @@ -0,0 +1,539 @@ +import type { Component } from "solid-js"; +import { createSignal, Show, For, onCleanup } from "solid-js"; +import { Shield, Check } from "lucide-solid"; +import Button from "../common/Button"; +import type { ChallengeExport } from "../../lib/types"; + +interface HumanVerificationProps { + onVerified: (data: ChallengeExport) => void; +} + +// -- data structures for mouse tracking and analysis -- + +interface TargetCircle { + id: number; + x: number; + y: number; +} + +interface MouseSample { + x: number; + y: number; + t: number; +} + +interface SegmentData { + fromTarget: number; + toTarget: number; + samples: MouseSample[]; + clickTime: number; + startTime: number; +} + +interface ChallengeData { + segments: SegmentData[]; + totalStartTime: number; + totalEndTime: number; +} + +type Phase = "ready" | "active" | "analyzing" | "passed" | "failed"; + +// -- constants -- + +const CONTAINER_WIDTH = 600; +const CONTAINER_HEIGHT = 400; +const CIRCLE_RADIUS = 24; +const MIN_DISTANCE = 120; +const PADDING = 48; +const TARGET_COUNT = 5; +const HUMAN_THRESHOLD = 0.35; + +// -- circle positioning -- + +function generateCirclePositions( + width: number, + height: number, +): TargetCircle[] { + const circles: TargetCircle[] = []; + const maxAttempts = 200; + + for (let id = 1; id <= TARGET_COUNT; id++) { + let placed = false; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + const x = PADDING + Math.random() * (width - 2 * PADDING); + const y = PADDING + Math.random() * (height - 2 * PADDING); + + const tooClose = circles.some((c) => { + const dx = c.x - x; + const dy = c.y - y; + return Math.sqrt(dx * dx + dy * dy) < MIN_DISTANCE; + }); + + if (!tooClose) { + circles.push({ id, x, y }); + placed = true; + break; + } + } + + // fallback grid placement if rejection sampling exhausts attempts + if (!placed) { + const cols = 3; + const row = Math.floor((id - 1) / cols); + const col = (id - 1) % cols; + circles.push({ + id, + x: PADDING + col * ((width - 2 * PADDING) / (cols - 1)), + y: PADDING + row * ((height - 2 * PADDING) / 1), + }); + } + } + + return circles; +} + +// -- analysis functions -- +// each returns a score from 0.0 (bot-like) to 1.0 (human-like) + +function scoreTimingVariance(segments: SegmentData[]): number { + if (segments.length < 2) return 0; + + const intervals = segments.map((s) => s.clickTime - s.startTime); + const mean = intervals.reduce((a, b) => a + b, 0) / intervals.length; + if (mean === 0) return 0; + + const variance = + intervals.reduce((sum, v) => sum + (v - mean) ** 2, 0) / intervals.length; + const cv = Math.sqrt(variance) / mean; + + // humans have natural variance in click timing + // bots tend to be metronomic or instantaneous + if (cv < 0.03) return 0; + if (cv < 0.08) return 0.3; + if (cv < 0.12) return 0.6; + return 1.0; +} + +function scorePathCurvature(segments: SegmentData[]): number { + const ratios: number[] = []; + + for (const seg of segments) { + if (seg.samples.length < 3) continue; + + const first = seg.samples[0]; + const last = seg.samples[seg.samples.length - 1]; + const straightDist = Math.sqrt( + (last.x - first.x) ** 2 + (last.y - first.y) ** 2, + ); + + // skip very short movements where curvature is meaningless + if (straightDist < 10) continue; + + let pathLength = 0; + for (let i = 1; i < seg.samples.length; i++) { + const dx = seg.samples[i].x - seg.samples[i - 1].x; + const dy = seg.samples[i].y - seg.samples[i - 1].y; + pathLength += Math.sqrt(dx * dx + dy * dy); + } + + ratios.push(pathLength / straightDist); + } + + if (ratios.length === 0) return 0; + + const avgRatio = ratios.reduce((a, b) => a + b, 0) / ratios.length; + + // humans never move in perfectly straight lines + // motor control imprecision guarantees some curvature + if (avgRatio < 1.02) return 0; + if (avgRatio < 1.06) return 0.3; + if (avgRatio < 1.1) return 0.6; + if (avgRatio > 4.0) return 0.5; + return 1.0; +} + +function scoreSpeedVariance(segments: SegmentData[]): number { + const allSpeedCVs: number[] = []; + + for (const seg of segments) { + if (seg.samples.length < 5) continue; + + const speeds: number[] = []; + for (let i = 1; i < seg.samples.length; i++) { + const dx = seg.samples[i].x - seg.samples[i - 1].x; + const dy = seg.samples[i].y - seg.samples[i - 1].y; + const dt = seg.samples[i].t - seg.samples[i - 1].t; + if (dt > 0) { + speeds.push(Math.sqrt(dx * dx + dy * dy) / dt); + } + } + + if (speeds.length < 3) continue; + + const mean = speeds.reduce((a, b) => a + b, 0) / speeds.length; + if (mean === 0) continue; + + const variance = + speeds.reduce((sum, v) => sum + (v - mean) ** 2, 0) / speeds.length; + const cv = Math.sqrt(variance) / mean; + allSpeedCVs.push(cv); + } + + if (allSpeedCVs.length === 0) return 0; + + const avgCV = allSpeedCVs.reduce((a, b) => a + b, 0) / allSpeedCVs.length; + + // humans accelerate and decelerate naturally along paths + // bots maintain constant velocity + if (avgCV < 0.1) return 0; + if (avgCV < 0.25) return 0.4; + if (avgCV < 0.4) return 0.7; + return 1.0; +} + +function scoreApproachJitter( + segments: SegmentData[], + circles: TargetCircle[], +): number { + const jitterScores: number[] = []; + + for (let i = 0; i < segments.length; i++) { + const seg = segments[i]; + const target = circles[i]; + if (seg.samples.length < 5) continue; + + // isolate the last stretch of movement approaching the target + const approachSamples = seg.samples.filter((s) => { + const dx = s.x - target.x; + const dy = s.y - target.y; + return Math.sqrt(dx * dx + dy * dy) < 60; + }); + + if (approachSamples.length < 4) continue; + + // count direction changes via cross product sign flips + let directionChanges = 0; + for (let j = 2; j < approachSamples.length; j++) { + const dx1 = approachSamples[j - 1].x - approachSamples[j - 2].x; + const dy1 = approachSamples[j - 1].y - approachSamples[j - 2].y; + const dx2 = approachSamples[j].x - approachSamples[j - 1].x; + const dy2 = approachSamples[j].y - approachSamples[j - 1].y; + + const cross = dx1 * dy2 - dy1 * dx2; + if (j > 2) { + const prevDx1 = approachSamples[j - 2].x - approachSamples[j - 3].x; + const prevDy1 = approachSamples[j - 2].y - approachSamples[j - 3].y; + const prevCross = prevDx1 * dy1 - prevDy1 * dx1; + if (cross * prevCross < 0) directionChanges++; + } + } + + const jitterRatio = + directionChanges / Math.max(approachSamples.length - 2, 1); + jitterScores.push(jitterRatio); + } + + // not enough data to judge, give a neutral score + if (jitterScores.length === 0) return 0.5; + + const avgJitter = + jitterScores.reduce((a, b) => a + b, 0) / jitterScores.length; + + // humans have micro-corrections from motor noise (fitts's law) + // bots converge smoothly with zero directional jitter + if (avgJitter < 0.01) return 0.2; + if (avgJitter < 0.05) return 0.5; + return 1.0; +} + +function scoreOverallTiming(data: ChallengeData): number { + const totalMs = data.totalEndTime - data.totalStartTime; + const totalSec = totalMs / 1000; + + if (totalSec < 0.8) return 0; + if (totalSec < 1.5) return 0.3; + if (totalSec > 60) return 0.5; + return 1.0; +} + +function analyzeChallenge( + data: ChallengeData, + circles: TargetCircle[], +): { isHuman: boolean; score: number } { + const timing = scoreTimingVariance(data.segments); + const curvature = scorePathCurvature(data.segments); + const speed = scoreSpeedVariance(data.segments); + const jitter = scoreApproachJitter(data.segments, circles); + const overall = scoreOverallTiming(data); + + const score = + timing * 0.25 + + curvature * 0.25 + + speed * 0.2 + + jitter * 0.2 + + overall * 0.1; + + return { + isHuman: score >= HUMAN_THRESHOLD, + score, + }; +} + +// -- component -- + +const HumanVerification: Component = (props) => { + let containerRef: HTMLDivElement | undefined; + + const [phase, setPhase] = createSignal("ready"); + const [circles, setCircles] = createSignal( + generateCirclePositions(CONTAINER_WIDTH, CONTAINER_HEIGHT), + ); + const [currentTarget, setCurrentTarget] = createSignal(1); + const [completedCount, setCompletedCount] = createSignal(0); + const [wrongClickId, setWrongClickId] = createSignal(null); + const [failureMessage, setFailureMessage] = createSignal(""); + + // mutable tracking state, no reactivity needed + let challengeData: ChallengeData = { + segments: [], + totalStartTime: 0, + totalEndTime: 0, + }; + let currentSegmentSamples: MouseSample[] = []; + let currentSegmentStartTime = 0; + let wrongClickTimeout: ReturnType | undefined; + + onCleanup(() => { + if (wrongClickTimeout) clearTimeout(wrongClickTimeout); + }); + + function handleStart() { + const now = performance.now(); + challengeData = { + segments: [], + totalStartTime: now, + totalEndTime: 0, + }; + currentSegmentSamples = []; + currentSegmentStartTime = now; + setPhase("active"); + } + + function handleMouseMove(e: MouseEvent) { + if (phase() !== "active") return; + + const rect = containerRef!.getBoundingClientRect(); + currentSegmentSamples.push({ + x: e.clientX - rect.left, + y: e.clientY - rect.top, + t: performance.now(), + }); + } + + function handleCircleClick(circleId: number, e: MouseEvent) { + // prevent click events during non-active phases + if (phase() !== "active") return; + e.stopPropagation(); + + if (circleId !== currentTarget()) { + // wrong target feedback + setWrongClickId(circleId); + if (wrongClickTimeout) clearTimeout(wrongClickTimeout); + wrongClickTimeout = setTimeout(() => setWrongClickId(null), 400); + return; + } + + // correct target hit + const now = performance.now(); + const rect = containerRef!.getBoundingClientRect(); + + challengeData.segments.push({ + fromTarget: circleId - 1, + toTarget: circleId, + samples: [...currentSegmentSamples], + clickTime: now, + startTime: currentSegmentStartTime, + }); + + // reset for next segment + currentSegmentSamples = [ + { x: e.clientX - rect.left, y: e.clientY - rect.top, t: now }, + ]; + currentSegmentStartTime = now; + + const nextCount = completedCount() + 1; + setCompletedCount(nextCount); + + if (nextCount >= TARGET_COUNT) { + // all targets hit, begin analysis + challengeData.totalEndTime = now; + setPhase("analyzing"); + + setTimeout(() => { + const result = analyzeChallenge(challengeData, circles()); + if (result.isHuman) { + setPhase("passed"); + // package raw challenge data for the backend to re-validate + const exportData: ChallengeExport = { + segments: challengeData.segments.map((s) => ({ + fromTarget: s.fromTarget, + toTarget: s.toTarget, + samples: s.samples.map((m) => ({ x: m.x, y: m.y, t: m.t })), + clickTime: s.clickTime, + startTime: s.startTime, + })), + circles: circles().map((c) => ({ id: c.id, x: c.x, y: c.y })), + totalStartTime: challengeData.totalStartTime, + totalEndTime: challengeData.totalEndTime, + }; + setTimeout(() => props.onVerified(exportData), 600); + } else { + setFailureMessage( + "verification failed. please try again.", + ); + setPhase("failed"); + } + }, 1500); + } else { + setCurrentTarget(circleId + 1); + } + } + + function handleRetry() { + setCircles(generateCirclePositions(CONTAINER_WIDTH, CONTAINER_HEIGHT)); + setCurrentTarget(1); + setCompletedCount(0); + setWrongClickId(null); + setFailureMessage(""); + challengeData = { + segments: [], + totalStartTime: 0, + totalEndTime: 0, + }; + currentSegmentSamples = []; + currentSegmentStartTime = 0; + setPhase("ready"); + } + + function circleClasses(circleId: number): string { + const base = + "absolute flex items-center justify-center rounded-full w-12 h-12 text-[16px] font-bold cursor-pointer transition-colors duration-200 select-none"; + + if (wrongClickId() === circleId) { + return `${base} border-2 border-error text-white bg-orange-muted animate-target-shake`; + } + + if (circleId < currentTarget()) { + // completed + return `${base} border-2 border-white/10 text-white/15 animate-target-complete pointer-events-none`; + } + + if (circleId === currentTarget()) { + // active target + return `${base} border-2 border-orange text-white bg-orange-muted animate-target-pulse`; + } + + // pending + return `${base} border-2 border-white/20 text-white/30`; + } + + return ( +
+
+
+ +

+ human verfication +

+
+

complete the action below to verify your humanity

+
+ + {/* challenge area */} +
+ {/* ready state overlay */} + +
+

+ click the circles in order from 1 to 5. +

+ +
+
+ + {/* target circles, visible during ready (dimmed behind overlay) and active */} + + + {(circle, index) => ( +
handleCircleClick(circle.id, e)} + > + {circle.id} +
+ )} +
+
+ + {/* analyzing overlay */} + +
+

verifying...

+
+
+ + {/* passed overlay */} + +
+
+ +
+

verified

+
+
+
+ + {/* progress indicator */} + +

+ {completedCount()} / {TARGET_COUNT} +

+
+ + {/* failure state */} + +
+

{failureMessage()}

+ +
+
+
+ ); +}; + +export default HumanVerification; diff --git a/src/components/auth/SignUpScreen.tsx b/src/components/auth/SignUpScreen.tsx index 6464e0e..c51fc09 100644 --- a/src/components/auth/SignUpScreen.tsx +++ b/src/components/auth/SignUpScreen.tsx @@ -1,28 +1,41 @@ -import { Component, createSignal, Show } from "solid-js"; -import { Key, User, ArrowRight, Shield } from "lucide-solid"; +import { Component, createSignal, Show, Switch, Match } from "solid-js"; +import { ArrowRight } from "lucide-solid"; import Button from "../common/Button"; import Avatar from "../common/Avatar"; +import HumanVerification from "./HumanVerification"; +import type { ChallengeExport } from "../../lib/types"; interface SignUpScreenProps { - onComplete: (displayName: string, bio: string) => void; + onComplete: ( + displayName: string, + bio: string, + challengeData: ChallengeExport, + ) => void; } const SignUpScreen: Component = (props) => { const [displayName, setDisplayName] = createSignal(""); const [bio, setBio] = createSignal(""); - const [step, setStep] = createSignal<"welcome" | "profile">("welcome"); + const [step, setStep] = createSignal<"welcome" | "verification" | "profile">( + "welcome", + ); const [isCreating, setIsCreating] = createSignal(false); + const [challengeData, setChallengeData] = + createSignal(null); function handleBegin() { - setStep("profile"); + setStep("verification"); } async function handleCreate() { const name = displayName().trim(); if (!name) return; + const challenge = challengeData(); + if (!challenge) return; + setIsCreating(true); - props.onComplete(name, bio().trim()); + props.onComplete(name, bio().trim(), challenge); } function handleKeyDown(e: KeyboardEvent) { @@ -30,9 +43,10 @@ const SignUpScreen: Component = (props) => { e.preventDefault(); if (step() === "welcome") { handleBegin(); - } else if (displayName().trim()) { + } else if (step() === "profile" && displayName().trim()) { handleCreate(); } + // verification step is mouse-only, no keyboard shortcuts } } @@ -41,68 +55,19 @@ const SignUpScreen: Component = (props) => { class="h-screen w-screen bg-black flex items-center justify-center overflow-hidden" onKeyDown={handleKeyDown} > - + + {/* welcome screen */}

- dusk + welcome to dusk chat

- peer-to-peer communication. no servers, no surveillance, no - compromise. + truly private peer-to-peer messaging for the masses.

-
-
-
- -
-
-

- keypair identity -

-

- your identity is a cryptographic keypair generated on your - device. no email, no phone number, no corporate account. -

-
-
- -
-
- -
-
-

- your data, your hardware -

-

- everything is stored locally and synced directly between - peers. no central server ever touches your messages. -

-
-
- -
-
- -
-
-

- portable identity -

-

- take your identity anywhere. your keypair is yours forever - and works across any device running dusk. -

-
-
-
-
- } - > - {/* profile creation screen */} -
-

- create your identity -

-

- choose a display name for the network. you can change this later. -

+ - {/* live preview */} -
- -
-

- {displayName() || "your name"} -

- -

{bio()}

-
-

- peer id will be generated -

-
-
+ + { + setChallengeData(data); + setStep("profile"); + }} + /> + -
-
- - setDisplayName(e.currentTarget.value)} - maxLength={32} - autofocus + + {/* profile creation screen */} +
+

+ create your identity +

+

+ choose a display name for the network. you can change this later. +

+ + {/* live preview */} +
+ -

- {displayName().length}/32 -

+
+

+ {displayName() || "your name"} +

+ +

{bio()}

+
+

+ peer id will be generated +

+
-
- -