From 551117950e76a129ffeab0779d9648d8d6a9c360 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Wed, 21 Feb 2024 08:54:13 -0600 Subject: [PATCH 1/3] Sync Signed-off-by: Armored Dragon --- applications/armored-chat/README.md | 27 ++ applications/armored-chat/armored_chat.js | 199 ++++++++++++++ .../armored-chat/compact-messages.css | 22 ++ .../armored-chat/compact-messages.scss | 29 +++ applications/armored-chat/encrpytion.js | 22 ++ applications/armored-chat/img/icon.png | Bin 0 -> 400 bytes applications/armored-chat/img/ui/send.svg | 42 +++ .../armored-chat/img/ui/send_black.png | Bin 0 -> 1950 bytes .../armored-chat/img/ui/send_white.png | Bin 0 -> 1956 bytes .../armored-chat/img/ui/settings_black.png | Bin 0 -> 1561 bytes .../armored-chat/img/ui/settings_white.png | Bin 0 -> 1568 bytes .../armored-chat/img/ui/social_black.png | Bin 0 -> 3485 bytes .../armored-chat/img/ui/social_white.png | Bin 0 -> 3491 bytes applications/armored-chat/img/ui/user.svg | 42 +++ .../armored-chat/img/ui/user_black.png | Bin 0 -> 2463 bytes .../armored-chat/img/ui/user_white.png | Bin 0 -> 2446 bytes .../armored-chat/img/ui/world_black.png | Bin 0 -> 4066 bytes .../armored-chat/img/ui/world_white.png | Bin 0 -> 3960 bytes applications/armored-chat/index.css | 190 ++++++++++++++ applications/armored-chat/index.html | 245 ++++++++++++++++++ applications/armored-chat/index.scss | 222 ++++++++++++++++ 21 files changed, 1040 insertions(+) create mode 100644 applications/armored-chat/README.md create mode 100644 applications/armored-chat/armored_chat.js create mode 100644 applications/armored-chat/compact-messages.css create mode 100644 applications/armored-chat/compact-messages.scss create mode 100644 applications/armored-chat/encrpytion.js create mode 100644 applications/armored-chat/img/icon.png create mode 100644 applications/armored-chat/img/ui/send.svg create mode 100644 applications/armored-chat/img/ui/send_black.png create mode 100644 applications/armored-chat/img/ui/send_white.png create mode 100644 applications/armored-chat/img/ui/settings_black.png create mode 100644 applications/armored-chat/img/ui/settings_white.png create mode 100644 applications/armored-chat/img/ui/social_black.png create mode 100644 applications/armored-chat/img/ui/social_white.png create mode 100644 applications/armored-chat/img/ui/user.svg create mode 100644 applications/armored-chat/img/ui/user_black.png create mode 100644 applications/armored-chat/img/ui/user_white.png create mode 100644 applications/armored-chat/img/ui/world_black.png create mode 100644 applications/armored-chat/img/ui/world_white.png create mode 100644 applications/armored-chat/index.css create mode 100644 applications/armored-chat/index.html create mode 100644 applications/armored-chat/index.scss diff --git a/applications/armored-chat/README.md b/applications/armored-chat/README.md new file mode 100644 index 0000000..cd7d682 --- /dev/null +++ b/applications/armored-chat/README.md @@ -0,0 +1,27 @@ +# Armored Chat + +Armored Chat is a light-weight alternative chat application that extends the existing chat features. + +## Features + +- (wip) Drop-in replacement for Fluffy chat +- (wip) E2EE Direct messages +- (wip) Group chats + +- (?) Message signing + +## Encryption + +TODO: + +- Algorithm +- Key exchange +- When and where +- How + +## Group chats + +TODO: + +- How +- Limitations diff --git a/applications/armored-chat/armored_chat.js b/applications/armored-chat/armored_chat.js new file mode 100644 index 0000000..1ba1307 --- /dev/null +++ b/applications/armored-chat/armored_chat.js @@ -0,0 +1,199 @@ +// +// armored_chat.js +// +// Created by Armored Dragon, 2024. +// Copyright 2024 Overte e.V. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +(function () { + "use strict"; + // TODO: Theme consistency + // TODO: Dark Theme/Light theme + // TODO: Encryption + // TODO: Minimal theme + // TODO: Image embedding + + var app_is_visible = true; + var settings = { + max_history: 250, + // show_typing_indicator: true, + // show_speech_bubble: true, + // compact_chat: false + }; + var app_data = { app_uuid: Uuid.generate(), current_page: "domain" }; + // var encryption = { public: null, private: null }; + + // Global vars + var ac_tablet; + var chat_overlay_window; + + startup(); + + function startup() { + ac_tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + + var app_button = ac_tablet.addButton({ + icon: Script.resolvePath("./img/icon.png"), + text: "A-CHAT", + }); + + // When script ends, remove itself from tablet + Script.scriptEnding.connect(function () { + ac_tablet.removeButton(app_button); + chat_overlay_window.close(); + }); + + chat_overlay_window = new OverlayWebWindow({ + title: "Armored-Chat", + width: 350, + height: 400, + visible: app_is_visible, + source: Script.resolvePath("./index.html"), + }); + // TODO Crashing + // chat_overlay_window = new AppUi({ + // buttonName: "Armored-Chat", + // home: Script.resolvePath("./index.html"), + // graphicsDirectory: Script.resolvePath("./") // The path to your button icons + // }); + + // Main overlay + + // Overlay button toggle + app_button.clicked.connect(toggleMainChatWindow); + chat_overlay_window.closed.connect(toggleMainChatWindow); + + function toggleMainChatWindow() { + app_is_visible = !app_is_visible; + app_button.editProperties({ isActive: app_is_visible }); + chat_overlay_window.visible = app_is_visible; + } + } + + // Initialize default message subscriptions + Messages.subscribe("chat"); + Messages.subscribe("system"); + // Messages.subscribe() // TODO: Get unique avatar identifier + + // Add event listeners + // FIXME: below needs to be changed to work with appui + chat_overlay_window.webEventReceived.connect(onWebEventReceived); + Messages.messageReceived.connect(receivedMessage); + + function receivedMessage(channel, message) { + // Check to see if the message is relating to Chat + channel = channel.toLowerCase(); + + if (channel !== "chat") return; + + // Parse the chat channel for the message + var message = JSON.parse(message); + message.channel = message.channel.toLowerCase(); + + // For now, while we are working on superseding Floof, we will allow compatibility with it. + // If for_app exists, it came from us and we are just sending the message so Floof can read it. + // We don't need to listen to this message. + if (message.for_app) return; + + // Check the channel is valid + if ( + message.channel !== "domain" && + message.channel !== "local" && + message.channel !== "system" + ) + return; + + // If message is local, and if player is too far away from location, don't do anything + if ( + channel.toLowerCase() === "local" && + !Vec3.withinEpsilon(MyAvatar.position, message.position, 20) + ) + return; + + // Update web view of to new message + // FIXME: this needs to be changed to work with appui + chat_overlay_window.emitScriptEvent(JSON.stringify(message)); + + // Display on popup chat area + _overlayMessage({ sender: message.displayName, message: message }); + } + function onWebEventReceived(event) { + var parsed = JSON.parse(event); + + // Not our app? Not our problem! + if (parsed.app !== "ArmoredChat") return; + + if (parsed.action === "change_page") { + app_data.current_page = parsed.message; + return; + } + + if (parsed.action === "change_setting") { + console.log(parsed); + settings[parsed.message.setting] = parsed.message.value; + + console.log(settings[parsed.message.setting]); + + if (parsed.message.setting === "vr_safe_mode") { + chat_overlay_window.close(); + // close window + // change settings + } + } + if (parsed.action === "send_chat_message") + return _sendMessage(parsed.message); + if (parsed.action === "open_url") Window.openUrl(parsed.message.toString()); + + // Send to specific user (DM) + } + + function _sendMessage(message) { + Messages.sendMessage( + "chat", + JSON.stringify({ + position: MyAvatar.position, + message: message, + displayName: MyAvatar.sessionDisplayName, + channel: app_data.current_page, + action: "send_chat_message", + }) + ); + + // FloofyChat Compatibility + Messages.sendMessage( + "Chat", + JSON.stringify({ + position: MyAvatar.position, + message: message, + displayName: MyAvatar.sessionDisplayName, + channel: + app_data.current_page.charAt(0).toUpperCase() + + app_data.current_page.slice(1), + type: "TransmitChatMessage", + for_app: "Floof", + }) + ); + + // Show overlay of the message you sent + _overlayMessage({ sender: MyAvatar.sessionDisplayName, message: message }); + } + + // TODO: Create new overlay system + function _overlayMessage(message) { + // Foofchat compatibility + // This makes it so that our own messages are not rendered. + // For now, Floofchat has priority over notifications as they use a strange system I don't want to touch yet. + if (!message.action) return; + + Messages.sendLocalMessage( + "Floof-Notif", + JSON.stringify({ + sender: message.sender, + text: message.message, + color: { red: 122, green: 122, blue: 122 }, + }) + ); + } +})(); diff --git a/applications/armored-chat/compact-messages.css b/applications/armored-chat/compact-messages.css new file mode 100644 index 0000000..b5f0eef --- /dev/null +++ b/applications/armored-chat/compact-messages.css @@ -0,0 +1,22 @@ +body .page .content.message-list .message { + display: grid; + box-sizing: border-box; + grid-template-columns: 1fr 1fr; + grid-gap: inherit; + padding: 2px; + margin-bottom: 5px; +} +body .page .content.message-list .message .pfp { + display: none !important; +} +body .page .content.message-list .message .name { + color: #dbdbdb; +} +body .page .content.message-list .message .timestamp { + text-align: right; + color: #dbdbdb; +} +body .page .content.message-list .message .body { + grid-column-start: 1; + grid-column-end: 3; +} \ No newline at end of file diff --git a/applications/armored-chat/compact-messages.scss b/applications/armored-chat/compact-messages.scss new file mode 100644 index 0000000..ed40c1e --- /dev/null +++ b/applications/armored-chat/compact-messages.scss @@ -0,0 +1,29 @@ +body { + .page { + .content.message-list { + .message { + display: grid; + box-sizing: border-box; + grid-template-columns: 1fr 1fr; + grid-gap: inherit; + padding: 2px; + margin-bottom: 5px; + + .pfp { + display: none !important; + } + .name { + color: #dbdbdb; + } + .timestamp { + text-align: right; + color: #dbdbdb; + } + .body { + grid-column-start: 1; + grid-column-end: 3; + } + } + } + } +} diff --git a/applications/armored-chat/encrpytion.js b/applications/armored-chat/encrpytion.js new file mode 100644 index 0000000..fa2233f --- /dev/null +++ b/applications/armored-chat/encrpytion.js @@ -0,0 +1,22 @@ +(function () { + // TODO: Sign messages + // TODO: Verify signatures + + let rsa = forge.pki.rsa; + let keypair; + + function newKeyPair() { + // 2048 bits. Not the most super-duper secure length of 4096. + // This value must remain low to ensure lower-power machines can use. + // We will generate new keys automatically every so often and will also allow user to refresh keys. + keypair = rsa.generateKeyPair({ bits: 2048, workers: -1 }); + } + function encrypt(message) { + if (!keypair) return null; + return keypair.publicKey.encrypt("Test message"); + } + function decrypt(message) { + if (!keypair) return null; + return keypair.privateKey.decrypt(encrypted); + } +})(); diff --git a/applications/armored-chat/img/icon.png b/applications/armored-chat/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..410dc40b5933b126b7a996926e9c2a98a6471316 GIT binary patch literal 400 zcmV;B0dM|^P) + + + + + diff --git a/applications/armored-chat/img/ui/send_black.png b/applications/armored-chat/img/ui/send_black.png new file mode 100644 index 0000000000000000000000000000000000000000..bc9ece7a1186440aefa69560047589a94f5a2efe GIT binary patch literal 1950 zcmV;P2VwY$P)F0KBn)fs&lHl0AB;+ zfT<$#FBQ?y1vt?9>n*@!V3>&foY{;jQX?tXvmclPi~v3qk@nxOC)8#w4~!F$=EkQ~krrvlO|let9hfE}J5n6Cq7KrQ>)8s-1YQ%7RR-f%)PR*- zk6$y71Kt&peTK0r+F>m>$y#7MFhNBA3>34}gp}*q1-t_c6_I6uW0#67zle-i)nkFXfhOP*v__-oi zay_cr4Y&iBW#4WTW!5MnFvCT<7p zCxh`#DYRUVs`do#2VMfMHV9G3Lcb{FCTU$WH{tfQdl-cH5qD^j`{ualrvH{fyZ%c<_io$>;aUF*UY7q>q)Gcn{XvUX_p28e2;66n-ID=uGDgq zsOqJ-EzbVHDFz{Yq2F*3S!pnS2P(PkP}LKGhkzG=s|-Q}TQk=xcOEbm_)J7rTTLcU zBuaw@0(W7v&AAR&n?1>5&0J5f&?aCm& zHE0@*U@f?x>}KHOnCq4jr9p#$n~lPxR_JHZ<+lzedOk2G*2_==w9_iFPeo))!1!haXs3a;Lcg)K{JUk{e7z4?M%!cj za}n8=;e1jdKs${u^cyK6-yZG{Wi7Wodx7P&J;vu1x#K?3PSXTjVHD=Dg?@RH+n$}c zk{ACNpDQA}vz=1sY1d9;RT{JbcRRso5!np+m)o8lzyjJH;|ue2#8wLd+G+fnc|=!( z!7bUJ^#oGDBGEb|7TtDfvJLo(w$I?DB2qZPfhsmTJeKn&cQde%w$Io?%Jd}8jhlcA zjlvu@p~_nBCSVb5GMB{AjTd0|s-~q-Xt^7KFL3|c<`IcZIB4H_FmRJmm`-hCSj$Zw zD$EB~#v;?Bs+Zs{U+V{)W)Pz8?Z>p`9wal?tAzq3NDUtxG%7bKGy1dL0EKms;*nox z<*uXc^YW9jyj&_kf@E@7U#r|vz$<0CbW>G(0T1I20Io9%V_IfYtK1c35gRB$3Q{1K z^*T2f1gc*SUfNn}xrr)@XR%9=GAl|irQ84sQZCv_N+UPXpgkD4)+kJ_8o{EM8z4b~ zoVIXADK}7pl>6rEsN@DpkP35cLKJcXBuIt4@T9PE10_g>zN)Bjaua>DR(DT9B$td8 zLT;c0DZ1+cb1gSerX6PcP;MGJ0Z6FAM=W} z+(H(X#e$XGt-ws&w%{tG7!^k$ZMjQvO;6K8H$7E!Bn`RI6_&+9BXWIV*{E1=LoYh@ z$jxQbQ$G3O82|tP literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/send_white.png b/applications/armored-chat/img/ui/send_white.png new file mode 100644 index 0000000000000000000000000000000000000000..2730d2f84c769991885250798ac5e453a5c47d19 GIT binary patch literal 1956 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 LNkvXXu0mjfD_g-8 literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/settings_white.png b/applications/armored-chat/img/ui/settings_white.png new file mode 100644 index 0000000000000000000000000000000000000000..12a35ad58c9149f9c3d07155798130e30fd971fa GIT binary patch literal 1568 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 Bh}!@F literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/social_white.png b/applications/armored-chat/img/ui/social_white.png new file mode 100644 index 0000000000000000000000000000000000000000..7677bd54696ae317fcf03436102f46fa69fc4e4b GIT binary patch literal 3491 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 H literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/user.svg b/applications/armored-chat/img/ui/user.svg new file mode 100644 index 0000000..110e522 --- /dev/null +++ b/applications/armored-chat/img/ui/user.svg @@ -0,0 +1,42 @@ + + + + + + diff --git a/applications/armored-chat/img/ui/user_black.png b/applications/armored-chat/img/ui/user_black.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ca6e04451fb530b1be9694b9838996ce79035b GIT binary patch literal 2463 zcmV;Q31Ie#P)Jw&%O8a z+P-7E_k5n`aNpnO^Ld`I-$@NeKCuou_?{1ey$ zY!Z=wi=(O+0p9_x1S%;u-3|N} zSR^8wQfxO>f)qzpM*~ZNFOaS%)pP@o0C$PVo(%hGh^C?)s76(<0JZ`%$yOMm_P+!? zud35C?khGyiKD7_15aWP_&jL=)~f3KocryQAZ}}_S^@3{<`(S>@E~x9h;$e2NGKy` zDPaf$=EskUb^-zrM^(QD%q!ZDDsETRuN3V>b8BmBVV$e$1=wtz`uYOfMkb$5a`5>ePQM^%pp+OSoAT($$tvB|@>de4XGIW`fPip~5c zG|L~11^uZXH{Q|g6MBYu%?{UCSu&p332Y|66@>-+)HcC+==XU(UbOYZK zk^7Q%8r`05Qq?wK3BE<{aBK#*AZh<`$$hq_s>6WUF)sOD8p8A@YHx9jOXjHRv1$6? zp@^yU6yP+ctpeZ8$dCEJTBq$u;By)Iaa4*B=US)TeqdIA5B^4p+MR_>yFGaQPK_eO z@qPn;AR@14>4=Ez1%Bu>pPZ#H^~hD6XqI-S!}ML?`x(2_!_ug~{y0ljy|?33$b00R z=d{}>B5!5tNrZ^J3H-@nTEXvsD&#GWchUJore4&t&S~cv^{J7!I3IP|ZOPP&TK?j+ z8TO99dd}O9x)Z+az3~F&+b=sYisTZ|)!@;>m zMe`PChtqCqmQK`Rn$zy(OueWgZ*jc&$x~G|mxpiE&*e_@_AGs=CU0^64s7}W%PGi>T*Zmv`rgFx1z88UqV^X!&7aCU(Xfb+fjaHZ2ELl5Bf!`3@ArBA zPK_eOc^v;DbFr#sGC5GyY522h4&slRrbh1Kh)5@}!fDI`6G)UJna@(cVOL6I4sE3h&`FWtZcz&(xRkVR40 z`B<7$oVuS!MI^78;}H~{@i`rTK63@Q1GrgL?*|?ck?s9mq^c9J>GGZUcg1_?0=^mZ zn$#$?K1WsOVxyr^UI8`$JFzgsK41ivdNl_4EO2^)_UDMmvIN&BqVVD=Rb35SQ>YX5 zStTNIZo8>dczq6V1MqawPE@f4xVdO23KvI2x`3;(a*z<%4qPQ7xrPVoQMfn&BGLg| zf=zLYWHT^1@~3cu5CgvJI<}`>BZROQF5Y z2wt4tsOq^`Ncke*lUN36U!(thU>7zuej0c}L~@O0CSgE{Q%zJQHwHKb%f|cwRxz+2 zcmvoeBHo;|;26;240eK?5R@3DH~~|N6ELMX0aJ<-Fr_#FQ;HKXr8ogoWP*naRXrWc z{`?45xAS4F*y%LjSS-bRcV5+{17&%tt$^Da*hna#k@v3%}^b0A`iqpD5Vfp)X7G}>HGwHRRR$LfF{ zXk;|G#ZlE0fiGhx+a`JYQ(El9Lebs8VJw@bhm)``O$7^KkI3D-S~g%Wu~;J_hdmec zD^66@dK*^TlGm-P6I&d<-0QOwTj6&CopEMK(f^?ZtC}8(z31)B=ra~u^yVeti`d_C zO@9TzeToxhyDTT$6Z$%_#ojZ(bJ+3suVmO?T~u`}@QLU%3HUVG?oMm~ZWNJSM>9C8 zII4OBu#9-8rh7O5{4R2CJYT?`9seS{wGfKZFqskXJngz`+&9Hsp4QlRfl8w-1BIBsj(Lr-xFu*9c;Uo#)Nqa zSRx|7Y0#lTK~xF%psFqdJ`a2w3x~vE6mSpG`|Bzqf~uZ}y$C4IY-AO%P((s07Yq(n zy%hUnUlQZ8!@xul+1@i7n~PtV{lGOMGNTlxZ=&bNrPu*Whn$x+(=&3gLmKwrTOt1k zm?k2BjPL5uMpb75zrwdXc?%fbjJ=fm7H1#xL}X=y{tanbTU*=O+uMf$pK+KU2W)P_ z;`bi5kj+YC1#VIL(^0pQ*r8ogoiW4xUH~~|N6ELMX0aJ<- dFr_#F^Is1sZ+{Om&qn|N002ovPDHLkV1gD|psN4? literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/user_white.png b/applications/armored-chat/img/ui/user_white.png new file mode 100644 index 0000000000000000000000000000000000000000..74ec794249eda232338049cc72a67cbd15aee52f GIT binary patch literal 2446 zcmZvbc{J3E0>^)5?E4`5I^BzeD0M9(x@IgX3=PWCOd&Fsu|^byJ4{Gqi*Xx-DKcb> z7|SGtm^&uMGKnl%Mkrx;=ic}Jc;~$L$M<~C`Tp_!p7TBDlj`JPBPOgU3;=+boh{rM z0Dv0+0Qd;<0|4-Zq3;F&fKaIIzGhq{gAL5Pu5_H03f7f2S0b|R?%v4{EIwagoijFvXYj!V|aIW%F%po)p%Ua6_)l~He$Zb|J?u=c!s=$Z(MO<$g=OC zgU8ze2~bn2Z8g^BT7Zc?-b&uUqTQ`gS~Ag?yz9%(sN+_Cc13ZojXUJ*UU6Y;CT>$( zU1aD&EBvNi4B46yYTvQ`c%^1{_(4AD!KEC{46-;+( z_~S0Z*X%t4ZkbP2l06b>JNzwH6xGT7SKC_UoasWcIKQ7(^SsApL3**%G>NzAJ(6Km zocm0>^td^nF(Y74o-1*ZxZf)D>b3rvc%nYeq2&?$n2#c?(@W&mb@L{$PO0sDlyd``N zxQ~%&L%w8Wr7^~9M#=cB#X4V&(?MLtPZxxMVlKsplTTmMW!uM?g5vlN<4XRyuc&uJ z;-p;FP5ojpsyM}h{6+ErMSrjDsSH`-%{3bo;OTH;q+Z^Y?Dt5y+jEG=x8;^gsP+r@ zUaWg~2IT&d%=AN2$U{`p1smg#D&%C>3^GSyqea>N=$12B6<7<D z(?$aWR8zD-SAU!jG$bQQ?u)an%d zF3`j#`yyH+H0nW@Wtm=u8QD~MfWH|cUve(XgQDA_miBI1w0|Idk+zgUCf?UOc2zJ= zl%T#^z1;y`>3RLu5$uS!efqp0V9{;%FX_6ux9DT5-3dR?3gEp2W`YWIHrO*0(P< z69)t9%VNWh*q~Sm$0_fIs>)dYr)5oRRjgI{h%#A|Cp%8bXGi(6ayG5kA*vcppm zqVQ|DOASX@AA)6NtvwcNWVsLG-Bmw;2VZG68Iw&#cR-ExL51{^x@#vIWxT){=n*5Y zBD}eg-bbnLoUS)t`%G6P2`Fe-Pq=Bb!qm%oN8a%?L$kF8!K( zXr+{U+FZ(PVf8_1I*tDgLTCr{y~&f|1`2&So8+J8JJ)J;RqM>hJ!y_|BbPg1GRBld zsfffGd1faN`l6$*sf6CgufTFU4QWWm*TnK)Sf{7D@35JjEe+H$5`UzfV0Dnxm`L$G zTG$P4e7wp|8y+^jm?uU9*! zC250NK&#d0>Ue=+Nqn1+!yZ|yCRJ5_O?X1dwjOov{{G?Y`9Dj0kPJet7Hm-c+Y$B+ zsxxGqNGiIMNY3b$q6TYnW6bji??PJda4c|LbdFr%dR7py26nyOng$j^sie`uXU=U} zrJGZCY9gPl5rTe<78yA55D;^D7fp@S1q(tY$ji=bI+aP8fB4G-(3(ckRp#jQbOxD7 zP~puf`>hV-t`4P?iCF(Z_DNIUWVEc+&;04YQ_`?QBU*4R0U zSqQqnc+;feN|0b<&6Q2zQyW}e_?@D9p##pgKfiyq=y;&gCGy3r< zACvaYScec=)B49RMmCnN`z5v4`@+TP*=@5j@jAVhz4bqT+Ewp-86mr7>k;kPonRAe z)y#kKr`K?0u%2(<|v{ Jn%~j){sl3Zl&$~( literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/world_black.png b/applications/armored-chat/img/ui/world_black.png new file mode 100644 index 0000000000000000000000000000000000000000..c983e5df28df328c581ae424242aa3308d13de35 GIT binary patch literal 4066 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 Uao=#1VE_OC07*qoM6N<$g5Qv^mjD0& literal 0 HcmV?d00001 diff --git a/applications/armored-chat/img/ui/world_white.png b/applications/armored-chat/img/ui/world_white.png new file mode 100644 index 0000000000000000000000000000000000000000..1f152b47b2ceb6144197886a1ed20a14fafff56b GIT binary patch literal 3960 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 SF%fA10000 + + + + + + + + + + + + +
+
+ + + +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+ + +
+ + + + + + + + diff --git a/applications/armored-chat/index.scss b/applications/armored-chat/index.scss new file mode 100644 index 0000000..5b98ae4 --- /dev/null +++ b/applications/armored-chat/index.scss @@ -0,0 +1,222 @@ +body { + background-color: black; + color: white; + margin: 0; + + height: 100vh; + width: 100vw; + + font-family: Verdana, Geneva, Tahoma, sans-serif; + display: flex; + flex-direction: column; + + .header { + width: 100%; + height: 40px; + display: flex; + flex-direction: row; + + button { + width: 60px; + height: 100%; + border-radius: 0; + border: 0; + margin: 0; + padding: 0; + box-sizing: border-box; + transition: width ease-in-out 0.2s; + } + button.active { + background-color: #6667ab; + color: white; + width: 100px; + } + + .left { + margin: 0 auto 0 0; + } + + .right { + margin: 0 0 0 auto; + } + } + + .page { + display: flex; + flex-direction: column; + flex-grow: 1; + overflow-y: auto; + width: 100%; + + .content { + width: 100%; + background-color: #111; + flex-grow: 1; + } + + .content.message-list { + overflow-y: auto; + overflow-x: hidden; + width: 100%; + + .message:nth-child(even) { + background-color: #1a1a1a; + } + .message { + display: grid; + box-sizing: border-box; + grid-template-columns: 80px 5fr; + grid-gap: 0.75rem; + padding: 0.8rem 0.15rem; + width: 100%; + overflow-y: auto; + .pfp { + height: 30px; + + width: auto; + display: flex; + + img { + height: 100%; + width: auto; + margin: auto; + border-radius: 50px; + background-color: black; + } + } + + .name { + font-size: 1.15rem; + color: #dbdbdb; + } + + .body { + width: 100%; + word-wrap: anywhere; + overflow-x: hidden; + + .image-container { + width: 100%; + max-width: 400px; + max-height: 300px; + + img { + width: auto; + height: 100%; + + max-width: 400px; + max-height: 300px; + } + } + } + + .timestamp { + text-align: center; + color: #dbdbdb; + } + } + } + + .content.settings { + .setting { + width: 100%; + display: flex; + padding: 0.5rem 0.25rem; + box-sizing: border-box; + } + .setting-toggle { + input { + margin: auto 0 auto auto; + width: 20px; + height: 20px; + } + } + .setting:nth-child(even) { + background-color: #1a1a1a; + } + } + } + .footer { + width: 100%; + height: 40px; + } + + .footer.text-entry { + display: Flex; + flex-direction: row; + input { + flex-grow: 1; + margin-right: 0; + border: 0; + font-size: 1.3rem; + min-width: 0; + } + + button { + width: 75px; + border: 0; + border-radius: 0; + } + } + + .hidden { + display: none !important; + } +} + +button { + width: 100px; + height: 100%; + background-color: white; + border-radius: 2px; + border: 0; + cursor: pointer; + outline: none; + + span { + width: 100%; + height: 100%; + img { + max-height: 70%; + width: auto; + user-select: none; + -webkit-user-drag: none; + } + } +} +button:focus { + filter: brightness(50%); +} + +input { + outline: none; +} +input:focus { + background-color: lightgray; +} + +@media screen and (max-width: 400px) { + body { + .header { + height: 30px; + + button { + width: 50px; + } + } + + .page { + .content.message-list { + .message { + grid-template-columns: 80px 5fr; + grid-gap: 0.75rem; + padding: 0.8rem 0.15rem; + + .pfp { + height: 30px; + } + } + } + } + } +} From d99ce00b5bf25f2535625649209f9d67d9e75624 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Wed, 21 Feb 2024 14:00:51 -0600 Subject: [PATCH 2/3] External Window Setting + Settings persistance Adds the ability to have the chat window open in a different window. Also allows settings to be saved and loaded. Signed-off-by: Armored Dragon --- applications/armored-chat/armored_chat.js | 143 ++++++++++++++-------- applications/armored-chat/index.html | 89 +++++++++----- 2 files changed, 151 insertions(+), 81 deletions(-) diff --git a/applications/armored-chat/armored_chat.js b/applications/armored-chat/armored_chat.js index 1ba1307..8179fdb 100644 --- a/applications/armored-chat/armored_chat.js +++ b/applications/armored-chat/armored_chat.js @@ -12,29 +12,31 @@ // TODO: Theme consistency // TODO: Dark Theme/Light theme // TODO: Encryption - // TODO: Minimal theme // TODO: Image embedding + // TODO: Find window init event method var app_is_visible = true; var settings = { max_history: 250, // show_typing_indicator: true, // show_speech_bubble: true, - // compact_chat: false + compact_chat: false, + external_window: false, }; var app_data = { app_uuid: Uuid.generate(), current_page: "domain" }; - // var encryption = { public: null, private: null }; + // var encryption = { }; // Global vars var ac_tablet; var chat_overlay_window; + var app_button; startup(); function startup() { ac_tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var app_button = ac_tablet.addButton({ + app_button = ac_tablet.addButton({ icon: Script.resolvePath("./img/icon.png"), text: "A-CHAT", }); @@ -42,75 +44,72 @@ // When script ends, remove itself from tablet Script.scriptEnding.connect(function () { ac_tablet.removeButton(app_button); + console.log("Closing"); chat_overlay_window.close(); }); - chat_overlay_window = new OverlayWebWindow({ - title: "Armored-Chat", - width: 350, - height: 400, - visible: app_is_visible, - source: Script.resolvePath("./index.html"), - }); - // TODO Crashing - // chat_overlay_window = new AppUi({ - // buttonName: "Armored-Chat", - // home: Script.resolvePath("./index.html"), - // graphicsDirectory: Script.resolvePath("./") // The path to your button icons - // }); - - // Main overlay + _openWindow(); // Overlay button toggle app_button.clicked.connect(toggleMainChatWindow); - chat_overlay_window.closed.connect(toggleMainChatWindow); + } + function toggleMainChatWindow() { + app_is_visible = !app_is_visible; + app_button.editProperties({ isActive: app_is_visible }); + chat_overlay_window.visible = app_is_visible; - function toggleMainChatWindow() { - app_is_visible = !app_is_visible; - app_button.editProperties({ isActive: app_is_visible }); - chat_overlay_window.visible = app_is_visible; + // External window was closed; the window does not exist anymore + if (chat_overlay_window.title == "" && app_is_visible) { + _openWindow(); } } + function _openWindow() { + chat_overlay_window = new Desktop.createWindow(Script.resourcesPath() + "qml/hifi/tablet/DynamicWebview.qml", { + title: "Armored-Chat", + size: { x: 550, y: 400 }, + additionalFlags: Desktop.ALWAYS_ON_TOP, + visible: app_is_visible, + presentationMode: Desktop.PresentationMode.VIRTUAL, + }); + chat_overlay_window.closed.connect(toggleMainChatWindow); + chat_overlay_window.sendToQml({ url: Script.resolvePath("./index.html") }); + // FIXME: Loadsettings need to happen after the window is initialized? + Script.setTimeout(_loadSettings, 1000); + chat_overlay_window.webEventReceived.connect(onWebEventReceived); + } // Initialize default message subscriptions Messages.subscribe("chat"); Messages.subscribe("system"); // Messages.subscribe() // TODO: Get unique avatar identifier - - // Add event listeners - // FIXME: below needs to be changed to work with appui - chat_overlay_window.webEventReceived.connect(onWebEventReceived); Messages.messageReceived.connect(receivedMessage); function receivedMessage(channel, message) { - // Check to see if the message is relating to Chat + var message = JSON.parse(message); + + if (message.action == "change_setting") return; + channel = channel.toLowerCase(); if (channel !== "chat") return; - // Parse the chat channel for the message - var message = JSON.parse(message); message.channel = message.channel.toLowerCase(); + console.log(channel); + console.log(JSON.stringify(message)); + // For now, while we are working on superseding Floof, we will allow compatibility with it. // If for_app exists, it came from us and we are just sending the message so Floof can read it. // We don't need to listen to this message. if (message.for_app) return; // Check the channel is valid - if ( - message.channel !== "domain" && - message.channel !== "local" && - message.channel !== "system" - ) - return; + if (message.channel !== "domain" && message.channel !== "local" && message.channel !== "system") return; // If message is local, and if player is too far away from location, don't do anything - if ( - channel.toLowerCase() === "local" && - !Vec3.withinEpsilon(MyAvatar.position, message.position, 20) - ) - return; + if (channel === "local" && !Vec3.withinEpsilon(MyAvatar.position, message.position, 20)) return; + + if (message.type === "TransmitChatMessage") message.action = "send_chat_message"; // Update web view of to new message // FIXME: this needs to be changed to work with appui @@ -120,6 +119,11 @@ _overlayMessage({ sender: message.displayName, message: message }); } function onWebEventReceived(event) { + console.log(event); + // FIXME: Lazy! + // Checks to see if the event is a JSON object + if (!event.includes("{")) return; + var parsed = JSON.parse(event); // Not our app? Not our problem! @@ -131,10 +135,16 @@ } if (parsed.action === "change_setting") { - console.log(parsed); settings[parsed.message.setting] = parsed.message.value; - console.log(settings[parsed.message.setting]); + console.log(JSON.stringify(parsed.message)); + + _saveSettings(); + switch (parsed.message.setting) { + case "external_window": + chat_overlay_window.presentationMode = parsed.message.value ? Desktop.PresentationMode.NATIVE : Desktop.PresentationMode.VIRTUAL; + break; + } if (parsed.message.setting === "vr_safe_mode") { chat_overlay_window.close(); @@ -142,13 +152,11 @@ // change settings } } - if (parsed.action === "send_chat_message") - return _sendMessage(parsed.message); + if (parsed.action === "send_chat_message") return _sendMessage(parsed.message); if (parsed.action === "open_url") Window.openUrl(parsed.message.toString()); // Send to specific user (DM) } - function _sendMessage(message) { Messages.sendMessage( "chat", @@ -168,9 +176,7 @@ position: MyAvatar.position, message: message, displayName: MyAvatar.sessionDisplayName, - channel: - app_data.current_page.charAt(0).toUpperCase() + - app_data.current_page.slice(1), + channel: app_data.current_page.charAt(0).toUpperCase() + app_data.current_page.slice(1), type: "TransmitChatMessage", for_app: "Floof", }) @@ -179,7 +185,6 @@ // Show overlay of the message you sent _overlayMessage({ sender: MyAvatar.sessionDisplayName, message: message }); } - // TODO: Create new overlay system function _overlayMessage(message) { // Foofchat compatibility @@ -196,4 +201,40 @@ }) ); } + function _sendUpdateMessage(message_packet = { setting_name, setting_value }) { + chat_overlay_window.emitScriptEvent( + JSON.stringify({ + setting_name: message_packet.setting_name, + setting_value: message_packet.setting_value, + action: "change_setting", + }) + ); + } + function _loadSettings() { + console.log("Loading config"); + settings = Settings.getValue("ArmoredChat-Config", settings); + console.log("\nSettings follow:"); + console.log(JSON.stringify(settings, " ", 4)); + + // Compact chat + if (settings.compact_chat) { + _sendUpdateMessage({ + setting_name: "compact-chat", + setting_value: true, + }); + } + + // External Window + if (settings.external_window) { + chat_overlay_window.presentationMode = settings.external_window ? Desktop.PresentationMode.NATIVE : Desktop.PresentationMode.VIRTUAL; + _sendUpdateMessage({ + setting_name: "external_window", + setting_value: true, + }); + } + } + function _saveSettings() { + console.log("Saving config"); + Settings.setValue("ArmoredChat-Config", settings); + } })(); diff --git a/applications/armored-chat/index.html b/applications/armored-chat/index.html index ebf5715..724254f 100644 --- a/applications/armored-chat/index.html +++ b/applications/armored-chat/index.html @@ -60,6 +60,10 @@ Compact Mode +
+ External Window + +
@@ -78,6 +82,7 @@ const qsa = (target) => document.querySelectorAll(target); var scroll_distance = 100000; // The scroll distance for the chat window to automatically scroll down with. var compact_mode = false; // Compact messages + var external_window = false; // Add event listeners to all nav-buttons qsa(".header button").forEach((button) => { @@ -114,7 +119,7 @@ JSON.stringify({ app: "ArmoredChat", action: "change_page", - message: button.dataset.target.replace("-chat", "") + message: button.dataset.target.replace("-chat", ""), }) ); } @@ -129,7 +134,7 @@ var clickEvent = { app: "ArmoredChat", message: qs("#message-entry").value, - action: "send_chat_message" + action: "send_chat_message", }; EventBridge.emitWebEvent(JSON.stringify(clickEvent)); @@ -137,37 +142,55 @@ }); // Start listening for new messages - EventBridge.scriptEventReceived.connect(function (message) { + EventBridge.scriptEventReceived.connect((message) => { message = JSON.parse(message); - newMessage(message); + switch (message.action) { + case "send_chat_message": + newMessage(message); + break; + case "change_setting": + newSetting(message); + break; + } }); - // Settings - // qs("#vr-safe-mode-toggle").addEventListener("change", function () { - // var clickEvent = { - // app: "ArmoredChat", - // message: { setting: "vr_safe_mode", value: qs("#vr-safe-mode-toggle").value == "on" ? true : false }, - // action: "change_setting" - // }; - - // EventBridge.emitWebEvent(JSON.stringify(clickEvent)); - // }); - // Settings qs("#compact-message-toggle").addEventListener("change", function () { + _toggleCompactMode(); + _sendSettingUpdate({ + setting_name: "compact_chat", + setting_value: compact_mode, + }); + }); + + function _toggleCompactMode() { compact_mode = !compact_mode; if (compact_mode) { // Add the stylesheet to the head - document.head.insertAdjacentHTML( - "beforeend", - '' - ); + document.head.insertAdjacentHTML("beforeend", ''); } else { // Remove the compact messages stylesheet qs("#compact-messages-ss").remove(); } + } + + qs("#external-window-toggle").addEventListener("change", function () { + external_window = !external_window; + _sendSettingUpdate({ + setting_name: "external_window", + setting_value: external_window, + }); }); + function _sendSettingUpdate(obj = { setting_name, setting_value }) { + var obj_packet = { + app: "ArmoredChat", + message: { setting: obj.setting_name, value: obj.setting_value }, + action: "change_setting", + }; + EventBridge.emitWebEvent(JSON.stringify(obj_packet)); + } + // TODO: Dynamic scrolling: Make it so each message increases the scrollTop value to make sure it continues to work for future messages. // TODO: Limit embeds to 3. function newMessage(message) { @@ -179,27 +202,20 @@ let message_clone = message_template.content.cloneNode(true); // Youtube embeds - let yt_url = message.message.match( - /(https?:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([^& \n<]+)(?:[^ \n<]+)?/g - ); + let yt_url = message.message.match(/(https?:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([^& \n<]+)(?:[^ \n<]+)?/g); if (yt_url) { message.message = message.message.replace( yt_url, `${yt_url}
- ` + ` ); } // Image embeds let image_link = message.message.match(/.+.(png|jpg|jpeg|webp)/g); if (image_link) { - message.message = message.message.replace( - image_link, - `${image_link}
` - ); + message.message = message.message.replace(image_link, `${image_link}
`); } // Linkify links @@ -216,7 +232,7 @@ message_clone.querySelector(".timestamp").innerText = new Date().toLocaleTimeString(undefined, { hour12: false }); message_clone.querySelector(".timestamp").title = new Date().toLocaleDateString(undefined, { month: "long", - day: "numeric" + day: "numeric", }); message_clone.querySelector(".body").innerHTML = message.message; // Append to the message list @@ -231,6 +247,19 @@ function openExternal(url) { EventBridge.emitWebEvent(JSON.stringify({ app: "ArmoredChat", action: "open_url", message: url })); } + + function newSetting(message) { + switch (message.setting_name) { + case "compact-chat": + qs("#compact-message-toggle").checked = true; + _toggleCompactMode(); + break; + case "external_window": + qs("#external-window-toggle").checked = true; + external_window = true; + break; + } + }