diff --git a/src/assets/config.json b/src/assets/config.json index 389e901..a816ef7 100644 --- a/src/assets/config.json +++ b/src/assets/config.json @@ -39,5 +39,6 @@ "siteId": "25" } } - ] + ], + "experimental_voice_mode": true } \ No newline at end of file diff --git a/src/assets/css/chat.scss b/src/assets/css/chat.scss index 7494c34..ba92df1 100644 --- a/src/assets/css/chat.scss +++ b/src/assets/css/chat.scss @@ -896,6 +896,26 @@ body { } } +.with-right-label { + display: flex; + flex-wrap: nowrap; + flex-direction: row; + text-align: start; + & > * { + flex: 1 1 auto; + } + & > *:last-child { + flex: 0 0 auto; + } + .option-title { + color: #000; + font-size: 16 * $chat-text-size; + } + .option-text { + font-size: 13 * $chat-text-size; + } +} + .header-button-left { position: absolute; top: 0px; @@ -1111,6 +1131,21 @@ body { border: 1px solid #808080 !important; position: relative; } + + .options { + display: flex; + width: 100%; + justify-content: flex-end; + color: black; + font-size: 14 * $chat-text-size; + font-weight: bold; + margin-left: 10px; + [dir="rtl"] & { + margin-left: initial; + margin-right: 10px; + } + text-transform: none !important; + } } .room-link .v-input__slot::before { @@ -1236,6 +1271,27 @@ body { flex: 1 0 auto; padding: 20px; } + .typing-users { + flex: 1 0 52px; + min-height: 52px; + padding: 20px; + overflow-x: auto; + overflow-y: hidden; + max-width: 100%; + display: flex; + .typing-user { + width: 32px !important; + height: 32px !important; + margin-left: -8px !important; + } + .list-enter-active, .list-leave-active { + transition: all 1s; + } + .list-enter, .list-leave-to /* .list-leave-active below version 2.1.8 */ { + opacity: 0; + transform: translateY(24px); + } + } .load-later { flex: 1 0 auto; padding: 20px; diff --git a/src/assets/icons/audio_import.vue b/src/assets/icons/audio_import.vue new file mode 100644 index 0000000..d43e655 --- /dev/null +++ b/src/assets/icons/audio_import.vue @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/src/assets/icons/audio_import_play.vue b/src/assets/icons/audio_import_play.vue new file mode 100644 index 0000000..b940826 --- /dev/null +++ b/src/assets/icons/audio_import_play.vue @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/src/assets/translations/en.json b/src/assets/translations/en.json index fa3116e..77f4bc4 100644 --- a/src/assets/translations/en.json +++ b/src/assets/translations/en.json @@ -127,7 +127,8 @@ "status_avatar_total": "Uploading avatar: {count} of {total}", "status_avatar": "Uploading avatar: {count}", "room_name_limit_error_msg": "Maximum 50 characters allowed", - "colon_not_allowed": "Colon is not allowed" + "colon_not_allowed": "Colon is not allowed", + "options": "Options" }, "device_list": { "title": "DEVICES", @@ -243,8 +244,9 @@ "export_room": "Export chat", "user_admin": "Administrator", "user_moderator": "Moderator", - "ui_options": "UI Options", - "audio_layout": "Use audio layout" + "experimental_features": "Experimental Features", + "voice_mode": "Voice mode", + "voice_mode_info": "Switches the chat interface to a 'listen and record' mode" }, "room_info_sheet": { "this_room": "This room", diff --git a/src/components/AudioLayout.vue b/src/components/AudioLayout.vue index ff47abd..d3b9920 100644 --- a/src/components/AudioLayout.vue +++ b/src/components/AudioLayout.vue @@ -1,8 +1,21 @@ diff --git a/src/plugins/utils.js b/src/plugins/utils.js index 740c2a4..95ea715 100644 --- a/src/plugins/utils.js +++ b/src/plugins/utils.js @@ -3,6 +3,8 @@ import * as ContentHelpers from "matrix-js-sdk/lib/content-helpers"; import dataUriToBuffer from "data-uri-to-buffer"; import ImageResize from "image-resize"; +export const ROOM_TYPE_VOICE_MODE = "im.keanu.room_type_voice"; + const sizeOf = require("image-size"); var dayjs = require('dayjs'); @@ -424,6 +426,36 @@ class Util { }); } + /** + * Return 'true' if we should use voice mode for the given room. + * + * The default value is given by the room itself. If the "type" of the + * room is set to 'im.keanu.room_type_voice' then we default to voice mode, + * else not. The user can then override this default by flipping the "voice mode" + * swicth on room settings (it will be persisted as a user specific tag on the room) + */ + useVoiceMode(roomOrNull) { + if (roomOrNull) { + const room = roomOrNull; + + // Have we changed our local view mode of this room? + const tags = room.tags; + if (tags && tags["ui_options"]) { + return tags["ui_options"]["voice_mode"] === 1; + } + + // Was the room created with a voice mode type? + const createEvent = room.currentState.getStateEvents( + "m.room.create", + "" + ); + if (createEvent) { + return createEvent.getContent().type === ROOM_TYPE_VOICE_MODE; + } + } + return false; + } + /** Generate a random user name */ randomUser(prefix) { var pfx = prefix ? prefix.replace(/[^0-9a-zA-Z\-_]/gi, '') : null;