diff --git a/src/call.mp3 b/src/call.mp3 new file mode 100644 index 00000000..7eed0041 Binary files /dev/null and b/src/call.mp3 differ diff --git a/src/js/app.js b/src/js/app.js index 1750d9ff..4dcad68d 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -36,8 +36,6 @@ function checkGunPeerCount() { setInterval(checkGunPeerCount, 2000); var notificationSound = new Audio('./notification.mp3'); -var callSound = new Audio('./ring.mp3'); -callSound.loop = true; var chat = gun.get('converse/' + location.hash.slice(1)); var chats = {}; var autolinker = new Autolinker({ stripPrefix: false, stripTrailingSlash: false}); diff --git a/src/js/iris.js b/src/js/iris.js index 2cca5d2b..a5dd532b 100644 --- a/src/js/iris.js +++ b/src/js/iris.js @@ -2999,7 +2999,7 @@ } var sheet = document.createElement('style'); sheet.id = elementId; - sheet.innerHTML = '\n .iris-identicon * {\n box-sizing: border-box;\n }\n\n .iris-identicon {\n vertical-align: middle;\n border-radius: 50%;\n text-align: center;\n display: inline-block;\n position: relative;\n max-width: 100%;\n }\n\n .iris-distance {\n z-index: 2;\n position: absolute;\n left:0%;\n top:2px;\n width: 100%;\n text-align: right;\n color: #fff;\n text-shadow: 0 0 1px #000;\n font-size: 75%;\n line-height: 75%;\n font-weight: bold;\n }\n\n .iris-pie {\n border-radius: 50%;\n position: absolute;\n top: 0;\n left: 0;\n box-shadow: 0px 0px 0px 0px #82FF84;\n padding-bottom: 100%;\n max-width: 100%;\n -webkit-transition: all 0.2s ease-in-out;\n -moz-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n }\n\n .iris-card {\n padding: 10px;\n background-color: #f7f7f7;\n color: #777;\n border: 1px solid #ddd;\n display: flex;\n flex-direction: row;\n overflow: hidden;\n }\n\n .iris-card a {\n -webkit-transition: color 150ms;\n transition: color 150ms;\n text-decoration: none;\n color: #337ab7;\n }\n\n .iris-card a:hover, .iris-card a:active {\n text-decoration: underline;\n color: #23527c;\n }\n\n .iris-pos {\n color: #3c763d;\n }\n\n .iris-neg {\n color: #a94442;\n }\n\n .iris-identicon img {\n position: absolute;\n top: 0;\n left: 0;\n max-width: 100%;\n border-radius: 50%;\n border-color: transparent;\n border-style: solid;\n }\n\n .iris-chat-open-button {\n background-color: #1e1e1e;\n color: #fff;\n padding: 15px;\n cursor: pointer;\n user-select: none;\n }\n\n .iris-chat-open-button svg {\n width: 1em;\n }\n\n .iris-chat-open-button, .iris-chat-box {\n position: fixed;\n bottom: 0.5rem;\n right: 0.5rem;\n border-radius: 8px;\n font-family: system-ui;\n font-size: 15px;\n }\n\n .iris-chat-box {\n background-color: #fff;\n max-height: 25rem;\n box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.2);\n height: calc(100% - 44px);\n display: flex;\n flex-direction: column;\n width: 320px;\n color: rgb(38, 38, 38);\n }\n\n .iris-chat-box.minimized {\n height: auto;\n }\n\n .iris-chat-box.minimized .iris-chat-header {\n border-radius: 8px;\n cursor: pointer;\n }\n\n .iris-chat-box.minimized .iris-chat-messages, .iris-chat-box.minimized .iris-typing-indicator, .iris-chat-box.minimized .iris-chat-input-wrapper, .iris-chat-box.minimized .iris-chat-minimize, .iris-chat-box.minimized .iris-chat-close {\n display: none;\n }\n\n .iris-chat-header {\n background-color: #1e1e1e;\n height: 44px;\n color: #fff;\n border-radius: 8px 8px 0 0;\n text-align: center;\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n flex: none;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n .iris-chat-header-text {\n flex: 1;\n }\n\n .iris-online-indicator {\n color: #bfbfbf;\n margin-right: 5px;\n font-size: 12px;\n user-select: none;\n flex: none;\n }\n\n .iris-online-indicator.yes {\n color: #80bf5f;\n }\n\n .iris-typing-indicator {\n display: none;\n background-color: rgba(255, 255, 255, 0.5);\n font-size: 12px;\n padding: 2px;\n color: #777;\n }\n\n .iris-typing-indicator.yes {\n display: block;\n }\n\n .iris-chat-messages {\n flex: 1;\n padding: 15px;\n overflow-y: scroll;\n }\n\n .iris-chat-input-wrapper {\n flex: none;\n padding: 15px;\n background-color: #efefef;\n display: flex;\n flex-direction: row;\n border-radius: 0 0 8px 8px;\n }\n\n .iris-chat-input-wrapper textarea {\n padding: 15px 8px;\n border-radius: 4px;\n border: 1px solid rgba(0,0,0,0);\n width: auto;\n font-size: 15px;\n resize: none;\n flex: 1;\n }\n\n .iris-chat-input-wrapper textarea:focus {\n outline: none;\n border: 1px solid #6dd0ed;\n }\n\n .iris-chat-input-wrapper button svg {\n display: inline-block;\n font-size: inherit;\n height: 1em;\n width: 1em;\n overflow: visible;\n vertical-align: -0.125em;\n }\n\n .iris-chat-input-wrapper button, .iris-chat-input-wrapper button:hover, .iris-chat-input-wrapper button:active, .iris-chat-input-wrapper button:focus {\n flex: none;\n color: #999;\n background-color: transparent;\n font-size: 30px;\n padding: 5px;\n border: 1px solid rgba(0,0,0,0);\n border-radius: 4px;\n margin-left: 5px;\n }\n\n .iris-chat-input-wrapper button:active, .iris-chat-input-wrapper button:focus {\n outline: none;\n border: 1px solid #6dd0ed;\n }\n\n .iris-chat-message {\n display: flex;\n flex-direction: column;\n margin-bottom: 2px;\n overflow-wrap: break-word;\n }\n\n .iris-msg-content {\n background-color: #efefef;\n padding: 6px 10px;\n border-radius: 8px;\n box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n flex: none;\n max-width: 75%;\n }\n\n .emoji {\n font-size: 1.3em;\n line-height: 1em;\n }\n\n .iris-chat-message .emoji-only {\n font-size: 3em;\n text-align: center;\n }\n\n .seen {\n color: rgba(0, 0, 0, 0.45);\n user-select: none;\n }\n\n .seen.yes {\n color: #4fc3f7;\n }\n\n .seen svg {\n width: 18px;\n }\n\n .iris-delivered-checkmark {\n display: none;\n }\n\n .delivered .iris-delivered-checkmark {\n display: initial;\n }\n\n .iris-chat-minimize, .iris-chat-close {\n user-select: none;\n cursor: pointer;\n width: 45px;\n line-height: 44px;\n }\n\n .iris-chat-message.their {\n align-items: flex-start;\n }\n\n .iris-chat-message.their + .iris-chat-message.our .iris-msg-content, .day-separator + .iris-chat-message.our .iris-msg-content {\n margin-top: 15px;\n border-radius: 8px 0px 8px 8px;\n }\n\n .iris-chat-message.their:first-of-type .iris-msg-content {\n border-radius: 0px 8px 8px 8px;\n }\n\n .iris-chat-message.our:first-of-type .iris-msg-content {\n border-radius: 8px 0px 8px 8px;\n }\n\n .iris-chat-message.our + .iris-chat-message.their .iris-msg-content, .day-separator + .iris-chat-message.their .iris-msg-content {\n margin-top: 15px;\n border-radius: 0px 8px 8px 8px;\n }\n\n .iris-chat-message.our {\n align-items: flex-end;\n }\n\n .iris-chat-message.our .iris-msg-content {\n background-color: #c5ecf7;\n }\n\n .iris-chat-message .time {\n text-align: right;\n font-size: 12px;\n color: rgba(0, 0, 0, 0.45);\n }\n\n .day-separator {\n display: inline-block;\n border-radius: 8px;\n background-color: rgba(227, 249, 255, 0.91);\n padding: 6px 10px;\n margin-top: 15px;\n margin-left: auto;\n margin-right: auto;\n text-transform: uppercase;\n font-size: 13px;\n color: rgba(74, 74, 74, 0.88);\n box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n user-select: none;\n }\n\n .day-separator:first-of-type {\n margin-top: 0;\n }\n '; + sheet.innerHTML = '\n .iris-identicon * {\n box-sizing: border-box;\n }\n\n .iris-identicon {\n vertical-align: middle;\n border-radius: 50%;\n text-align: center;\n display: inline-block;\n position: relative;\n max-width: 100%;\n }\n\n .iris-distance {\n z-index: 2;\n position: absolute;\n left:0%;\n top:2px;\n width: 100%;\n text-align: right;\n color: #fff;\n text-shadow: 0 0 1px #000;\n font-size: 75%;\n line-height: 75%;\n font-weight: bold;\n }\n\n .iris-pie {\n border-radius: 50%;\n position: absolute;\n top: 0;\n left: 0;\n box-shadow: 0px 0px 0px 0px #82FF84;\n padding-bottom: 100%;\n max-width: 100%;\n -webkit-transition: all 0.2s ease-in-out;\n -moz-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n }\n\n .iris-card {\n padding: 10px;\n background-color: #f7f7f7;\n color: #777;\n border: 1px solid #ddd;\n display: flex;\n flex-direction: row;\n overflow: hidden;\n }\n\n .iris-card a {\n -webkit-transition: color 150ms;\n transition: color 150ms;\n text-decoration: none;\n color: #337ab7;\n }\n\n .iris-card a:hover, .iris-card a:active {\n text-decoration: underline;\n color: #23527c;\n }\n\n .iris-pos {\n color: #3c763d;\n }\n\n .iris-neg {\n color: #a94442;\n }\n\n .iris-identicon img {\n position: absolute;\n top: 0;\n left: 0;\n max-width: 100%;\n border-radius: 50%;\n border-color: transparent;\n border-style: solid;\n }\n\n .iris-chat-open-button {\n background-color: #1e1e1e;\n color: #fff;\n padding: 15px;\n cursor: pointer;\n user-select: none;\n }\n\n .iris-chat-open-button svg {\n width: 1em;\n }\n\n .iris-chat-open-button, .iris-chat-box {\n position: fixed;\n bottom: 0.5rem;\n right: 0.5rem;\n border-radius: 8px;\n font-family: system-ui;\n font-size: 15px;\n }\n\n .iris-chat-box {\n background-color: #fff;\n max-height: 25rem;\n box-shadow: 2px 2px 20px rgba(0, 0, 0, 0.2);\n height: calc(100% - 44px);\n display: flex;\n flex-direction: column;\n width: 320px;\n color: rgb(38, 38, 38);\n }\n\n .iris-chat-box.minimized {\n height: auto;\n }\n\n .iris-chat-box.minimized .iris-chat-header {\n border-radius: 8px;\n cursor: pointer;\n }\n\n .iris-chat-box.minimized .iris-chat-messages, .iris-chat-box.minimized .iris-typing-indicator, .iris-chat-box.minimized .iris-chat-input-wrapper, .iris-chat-box.minimized .iris-chat-minimize, .iris-chat-box.minimized .iris-chat-close {\n display: none;\n }\n\n .iris-chat-header {\n background-color: #1e1e1e;\n height: 44px;\n color: #fff;\n border-radius: 8px 8px 0 0;\n text-align: center;\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n flex: none;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n .iris-chat-header-text {\n flex: 1;\n }\n\n .iris-online-indicator {\n color: #bfbfbf;\n margin-right: 5px;\n font-size: 12px;\n user-select: none;\n flex: none;\n }\n\n .iris-online-indicator.yes {\n color: #80bf5f;\n }\n\n .iris-typing-indicator {\n display: none;\n background-color: rgba(255, 255, 255, 0.5);\n font-size: 12px;\n padding: 2px;\n color: #777;\n }\n\n .iris-typing-indicator.yes {\n display: block;\n }\n\n .iris-chat-messages {\n flex: 1;\n padding: 15px;\n overflow-y: scroll;\n }\n\n .iris-chat-input-wrapper {\n flex: none;\n padding: 15px;\n background-color: #efefef;\n display: flex;\n flex-direction: row;\n border-radius: 0 0 8px 8px;\n }\n\n .iris-chat-input-wrapper textarea {\n padding: 15px 8px;\n border-radius: 4px;\n border: 1px solid rgba(0,0,0,0);\n width: auto;\n font-size: 15px;\n resize: none;\n flex: 1;\n }\n\n .iris-chat-input-wrapper textarea:focus {\n outline: none;\n border: 1px solid #6dd0ed;\n }\n\n .iris-chat-input-wrapper button svg {\n display: inline-block;\n font-size: inherit;\n height: 1em;\n width: 1em;\n overflow: visible;\n vertical-align: -0.125em;\n }\n\n .iris-chat-input-wrapper button, .iris-chat-input-wrapper button:hover, .iris-chat-input-wrapper button:active, .iris-chat-input-wrapper button:focus {\n flex: none;\n color: #999;\n background-color: transparent;\n font-size: 30px;\n padding: 5px;\n border: 1px solid rgba(0,0,0,0);\n border-radius: 4px;\n margin-left: 5px;\n }\n\n .iris-chat-input-wrapper button:active, .iris-chat-input-wrapper button:focus {\n outline: none;\n border: 1px solid #6dd0ed;\n }\n\n .iris-chat-message {\n display: flex;\n flex-direction: column;\n margin-bottom: 2px;\n overflow-wrap: break-word;\n }\n\n .iris-msg-content {\n background-color: #efefef;\n padding: 6px 10px;\n border-radius: 8px;\n box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n flex: none;\n max-width: 75%;\n }\n\n .emoji {\n font-size: 1.3em;\n line-height: 1em;\n }\n\n .iris-chat-message .emoji-only {\n font-size: 3em;\n text-align: center;\n }\n\n .iris-seen {\n color: rgba(0, 0, 0, 0.45);\n user-select: none;\n }\n\n .iris-seen.yes {\n color: #4fc3f7;\n }\n\n .iris-seen svg {\n width: 18px;\n }\n\n .iris-delivered-checkmark {\n display: none;\n }\n\n .delivered .iris-delivered-checkmark {\n display: initial;\n }\n\n .iris-chat-minimize, .iris-chat-close {\n user-select: none;\n cursor: pointer;\n width: 45px;\n line-height: 44px;\n }\n\n .iris-chat-message.their {\n align-items: flex-start;\n }\n\n .iris-chat-message.their + .iris-chat-message.our .iris-msg-content, .day-separator + .iris-chat-message.our .iris-msg-content {\n margin-top: 15px;\n border-radius: 8px 0px 8px 8px;\n }\n\n .iris-chat-message.their:first-of-type .iris-msg-content {\n border-radius: 0px 8px 8px 8px;\n }\n\n .iris-chat-message.our:first-of-type .iris-msg-content {\n border-radius: 8px 0px 8px 8px;\n }\n\n .iris-chat-message.our + .iris-chat-message.their .iris-msg-content, .day-separator + .iris-chat-message.their .iris-msg-content {\n margin-top: 15px;\n border-radius: 0px 8px 8px 8px;\n }\n\n .iris-chat-message.our {\n align-items: flex-end;\n }\n\n .iris-chat-message.our .iris-msg-content {\n background-color: #c5ecf7;\n }\n\n .iris-chat-message .time {\n text-align: right;\n font-size: 12px;\n color: rgba(0, 0, 0, 0.45);\n }\n\n .day-separator {\n display: inline-block;\n border-radius: 8px;\n background-color: rgba(227, 249, 255, 0.91);\n padding: 6px 10px;\n margin-top: 15px;\n margin-left: auto;\n margin-right: auto;\n text-transform: uppercase;\n font-size: 13px;\n color: rgba(74, 74, 74, 0.88);\n box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n user-select: none;\n }\n\n .day-separator:first-of-type {\n margin-top: 0;\n }\n '; document.head.prepend(sheet); }, getUrlParameter: function getUrlParameter(sParam, sParams) { @@ -7117,16 +7117,35 @@ var _Number$parseInt = unwrapExports(_parseInt$2); /** - * Private communication channel between two participants (gun public keys). (You can specify more than two participants, but it causes unscalable data replication - better group channel implementation to be done.) Can be used independently of other Iris stuff. + * Private communication channel between two participants ([Gun](https://github.com/amark/gun) public keys). Can be used independently of other Iris stuff. * - * You can use **1)** channel.send() and channel.getMessages() for timestamp-indexed chat-style messaging or **2)** channel.put(key, value) and the corresponding channel.on(key, callback) methods to write key-value pairs where values are encrypted. + * --- * - * Channel ids and data values are obfuscated, but it is possible to guess - * who are communicating with each other by looking at Gun timestamps and subscriptions. + * #### Key-value API + * `channel.put(key, value)` and `channel.on(key, callback)`. * - * @param {Object} options {key, gun, chatLink, participants} **key**: your keypair, **gun**: gun instance, **chatLink**: (optional) chat link instead of participants list, **participants**: (optional) string or string array of participant public keys + * Note that each participant has their own versions of each key-value — they don't overwrite each other. `channel.on()` callback returns them all by default and has a parameter that indicates whose value you got. + * + * While values are encrypted, encryption of keys is not implemented yet. + * + * #### Message API + * `channel.send()` and `channel.getMessages()` for timestamp-indexed chat-style messaging. + * + * Message data is encrypted, but timestamps are public so that peers can return your messages in a sequential order. + * + * --- + * + * You can open a channel with yourself for a private key-value space or a "note to self" type chat with yourself. + * + * You can specify more than one participant key (your own key is included by default), but it's not guaranteed to work and causes unscalable data replication - better group channel implementation to be done. + * + * **Note!** As of April 2020 Gun.SEA hashing function [is broken on Safari](https://github.com/amark/gun/issues/892). Channels don't work on Safari unless you patch sea.js by adding [this line](https://github.com/irislib/iris-messenger/blob/1e012581793485e6b8b5ed3c2ad0629716709366/src/js/sea.js#L270). + * + * **Privacy disclaimer:** Channel ids, data values and messages are encrypted, but message timestamps are unencrypted so that peers can return them to you in a sequential order. By looking at the unencrypted timestamps (or Gun subscriptions), it is possible to guess who are communicating with each other. This could be improved by indexing messages by *day* only, so making the guess would be more difficult, while you could still return them in a semi-sequential order. + * + * @param {Object} options {key, gun, chatLink, participants} **key**: your keypair, **gun**: gun instance, **chatLink**: (optional) chat link instead of participants list, **participants**: (optional) string or string array of participant public keys (your own key is included by default) * @example - * // Copy & paste this to console at https://iris.to or other page that has gun and iris-lib + * // Copy & paste this to console at https://iris.to or other page that has gun, sea and iris-lib * // Due to an unsolved bug, someoneElse's messages only start showing up after a reload * * var gun1 = new Gun('https://gun-us.herokuapp.com/gun'); @@ -7140,6 +7159,9 @@ * localStorage.setItem('someoneElsesKey', JSON.stringify(someoneElse)); * } * + * iris.Channel.initUser(gun1, myKey); // saves myKey.epub to gun.user().get('epub') + * iris.Channel.initUser(gun2, someoneElse); + * * var ourChannel = new iris.Channel({key: myKey, gun: gun1, participants: someoneElse.pub}); * var theirChannel = new iris.Channel({key: someoneElse, gun: gun2, participants: myKey.pub}); * @@ -7158,6 +7180,7 @@ * // you can play with these in the console: * ourChannel.send('message from myKey'); * theirChannel.send('message from someoneElse'); + * * ourChannel.put('mood', 'blessed'); * theirChannel.put('mood', 'happy'); * @@ -7480,7 +7503,7 @@ /** * Save a key-value pair, encrypt value. Each participant in the Channel writes to their own version of the key-value pair — they don't overwrite the same one. * @param {string} key - * @param {string} value + * @param value * @param {string} salt (optional) custom salt for encrypting the value */ @@ -7729,7 +7752,7 @@ } this.getTheirMsgsLastSeenTime(function (time) { - var unseen = messages.querySelectorAll('.seen:not(.yes)'); + var unseen = messages.querySelectorAll('.iris-seen:not(.yes)'); unseen.forEach(function (indicator) { var msgEl = indicator.parentElement.parentElement.parentElement; if (msgEl.getAttribute('data-time') <= time) { @@ -7737,7 +7760,7 @@ if (msgClass.indexOf('delivered') === -1) { msgEl.setAttribute('class', msgClass + ' delivered'); } - indicator.setAttribute('class', 'seen yes'); + indicator.setAttribute('class', 'iris-seen yes'); } }); }); @@ -7748,7 +7771,7 @@ var time = util.createElement('div', 'time', msgContent); time.innerText = util.formatTime(new Date(msg.time)); if (info.selfAuthored) { - var cls = _this11.theirMsgsLastSeenTime >= msg.time ? 'seen yes' : 'seen'; + var cls = _this11.theirMsgsLastSeenTime >= msg.time ? 'iris-seen yes' : 'iris-seen'; var seenIndicator = util.createElement('span', cls, time); seenIndicator.innerHTML = ' '; } @@ -8211,6 +8234,8 @@ // TODO: flush onto IPFS /** + * **Experimental.** Unlike Channel, this is probably not the most useful class yet. + * * The essence of Iris: A database of Contacts and SignedMessages within your web of trust. * * NOTE: these docs reflect the latest commit at https://github.com/irislib/iris-lib @@ -9556,7 +9581,7 @@ return SocialNetwork; }(); - var version$1 = "0.0.142"; + var version$1 = "0.0.143"; /*eslint no-useless-escape: "off", camelcase: "off" */ diff --git a/src/js/videocall.js b/src/js/videocall.js index 0c5914a1..59113488 100644 --- a/src/js/videocall.js +++ b/src/js/videocall.js @@ -1,8 +1,12 @@ +var ringSound = new Audio('./ring.mp3'); +ringSound.loop = true; +var callSound = new Audio('./call.mp3'); var activeCall; var callTimeout; +var callSoundTimeout; var callingInterval; var userMediaStream; -var localVideo = $('