Skip to content

Commit

Permalink
feat: add preview area for message drafts, fixes #142
Browse files Browse the repository at this point in the history
  • Loading branch information
valeriansaliou committed Nov 27, 2024
1 parent 5ef1204 commit 8e74bae
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 15 deletions.
36 changes: 33 additions & 3 deletions src/assemblies/inbox/InboxForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,20 @@ layout-toolbar(
inbox-form-formatting(
v-if="isActionFormatFormattingVisible"
@action="onFormattingAction"
@mode="onFormattingMode"
:disabled="isFormDisabled"
:mode="formattingMode"
class="a-inbox-form__compose-formatting"
)

inbox-form-preview(
v-if="formattingMode === formattingModeOptions.Preview"
:message="message"
class="a-inbox-form__compose-preview"
)

form.a-inbox-form__compose-form(
v-show="formattingMode === formattingModeOptions.Write"
@submit.prevent="onSubmit"
)
form-field(
Expand Down Expand Up @@ -199,6 +208,7 @@ import { Suggestion as FormFieldSuggestSuggestion } from "@/components/form/Form
import {
default as InboxFormFormatting,
FormattingAction,
FormattingMode,
FormattingSyntax,
TAG_TEXT as FORMATTING_TAG_TEXT,
TAG_INDEX as FORMATTING_TAG_INDEX
Expand All @@ -209,6 +219,7 @@ import {
} from "@/components/inbox/InboxFormRecorder.vue";
import InboxFormAttach from "@/components/inbox/InboxFormAttach.vue";
import InboxFormChatstate from "@/components/inbox/InboxFormChatstate.vue";
import InboxFormPreview from "@/components/inbox/InboxFormPreview.vue";
import InboxFormLoader from "@/components/inbox/InboxFormLoader.vue";
// PROJECT: STORES
Expand Down Expand Up @@ -243,6 +254,7 @@ export default {
InboxFormRecorder,
InboxFormAttach,
InboxFormChatstate,
InboxFormPreview,
InboxFormLoader
},
Expand All @@ -261,10 +273,14 @@ export default {
actionIconSize: "18px",
formattingModeOptions: FormattingMode,
// --> STATE <--
message: "",
formattingMode: FormattingMode.Write,
mentionQuery: null as string | null,
isMessageFieldFocused: false,
Expand Down Expand Up @@ -539,6 +555,12 @@ export default {
focusMessageField(): void {
// Focus on input
(this.$refs.message as typeof FormField)?.focusFieldFromParent();
// Force formatting mode to write
// Notice: this is important, as the user might be previewing a message \
// when something requests to focus on the message field. We therefore \
// need to force the mode to write.
this.formattingMode = FormattingMode.Write;
},
clearMessageField(): void {
Expand Down Expand Up @@ -742,6 +764,10 @@ export default {
}
},
onFormattingMode(mode: FormattingMode): void {
this.formattingMode = mode;
},
onRecorderAudio(audio: RecorderAudio) {
// Close recorder
this.isActionRecordRecorderVisible = false;
Expand Down Expand Up @@ -1054,15 +1080,19 @@ $form-compose-send-button-size: (
width: 100%;
}
#{$c}__compose-field textarea,
#{$c}__compose-preview {
min-height: $form-compose-field-height-minimum;
max-height: 220px;
border-radius: ($size-form-field-border-radius + 2px);
}
#{$c}__compose-field {
textarea {
min-height: $form-compose-field-height-minimum;
max-height: 220px;
padding-inline-end: (
$form-compose-send-button-size + $form-compose-send-position-edges +
2px
);
border-radius: ($size-base-button-border-radius + 2px);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/assets/images/icons/character.cursor.ibeam.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/images/icons/text.viewfinder.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/broker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import BrokerClient from "@/broker/client";
import BrokerModuleAccount from "@/broker/modules/account";
import BrokerModuleRoom from "@/broker/modules/room";
import BrokerModulePresence from "@/broker/modules/presence";
import BrokerModuleMessage from "@/broker/modules/message";
import BrokerModuleChannel from "@/broker/modules/channel";
import BrokerModuleProfile from "@/broker/modules/profile";
import BrokerModuleRoster from "@/broker/modules/roster";
Expand All @@ -32,6 +33,7 @@ class Broker {
readonly $roster: BrokerModuleRoster;
readonly $status: BrokerModuleStatus;
readonly $presence: BrokerModulePresence;
readonly $message: BrokerModuleMessage;
readonly $room: BrokerModuleRoom;
readonly $channel: BrokerModuleChannel;
readonly $data: BrokerModuleData;
Expand All @@ -46,6 +48,7 @@ class Broker {
this.$roster = new BrokerModuleRoster(this.client);
this.$status = new BrokerModuleStatus(this.client);
this.$presence = new BrokerModulePresence(this.client);
this.$message = new BrokerModuleMessage(this.client);
this.$room = new BrokerModuleRoom(this.client);
this.$channel = new BrokerModuleChannel(this.client);
this.$data = new BrokerModuleData(this.client);
Expand Down
166 changes: 154 additions & 12 deletions src/components/inbox/InboxFormFormatting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,69 @@

<template lang="pug">
.c-inbox-form-formatting
.c-inbox-form-formatting__group(
v-for="group in groups"
.c-inbox-form-formatting__groups
.c-inbox-form-formatting__group(
v-for="group in groups"
)
base-tooltip(
v-for="action in group"
:tooltip="action.title"
)
base-action(
@click="onActionClick(action.action, action.syntax)"
:icon="action.icon"
:disabled="disabled"
class="c-inbox-form-formatting__action"
context="transparent"
size="12px"
auto-width
auto-height
bordered
)

.c-inbox-form-formatting__modes(
v-if="modeToggle"
)
base-tooltip(
v-for="action in group"
:tooltip="action.title"
:tooltip="modeToggle.title"
align="right"
)
base-action(
@click="onActionClick(action.action, action.syntax)"
:icon="action.icon"
:disabled="disabled"
class="c-inbox-form-formatting__action"
@click="onModeToggleClick"
:icon="modeToggle.icon"
:class=`[
"c-inbox-form-formatting__mode",
"c-inbox-form-formatting__mode--" + mode
]`
icon-class="c-inbox-form-formatting__mode-icon"
context="transparent"
size="12px"
auto-width
auto-height
bordered
)
template(
v-slot:inner
)
span(
:class=`[
"c-inbox-form-formatting__mode-label",
{
"u-medium": (mode === formattingModeOptions.Preview)
}
]`
)
| {{ modeToggle.label }}
</template>

<!-- **********************************************************************
SCRIPT
********************************************************************** -->

<script lang="ts">
// NPM
import { PropType } from "vue";
// ENUMERATIONS
export enum FormattingAction {
// Bold formatting.
Expand All @@ -53,12 +91,25 @@ export enum FormattingAction {
CodeBlock = "code-block"
}
export enum FormattingMode {
// Write mode.
Write = "write",
// Preview mode.
Preview = "preview"
}
// INTERFACES
export interface FormattingSyntax {
code: string;
contiguous?: boolean;
}
interface FormattingModeToggle {
icon: string;
label: string;
title: string;
}
// CONSTANTS
export const TAG_INDEX = "%i";
export const TAG_TEXT = "%t";
Expand All @@ -67,18 +118,25 @@ export default {
name: "InboxFormFormatting",
props: {
mode: {
type: String as PropType<FormattingMode>,
default: FormattingMode.Write
},
disabled: {
type: Boolean,
default: false
}
},
emits: ["action"],
emits: ["action", "mode"],
data() {
return {
// --> DATA <--
formattingModeOptions: FormattingMode,
groups: [
[
{
Expand Down Expand Up @@ -162,11 +220,59 @@ export default {
};
},
computed: {
modeToggle(): FormattingModeToggle | null {
switch (this.mode) {
case FormattingMode.Write: {
return {
icon: "character.cursor.ibeam",
label: "Write",
title: "Go to preview"
};
}
case FormattingMode.Preview: {
return {
icon: "text.viewfinder",
label: "Preview",
title: "Return to editor"
};
}
default: {
return null;
}
}
}
},
methods: {
// --> EVENT LISTENERS <--
onActionClick(action: FormattingAction, syntax: FormattingSyntax): void {
this.$emit("action", action, syntax);
},
onModeToggleClick(): void {
// Find next mode (circle through modes)
let nextMode: FormattingMode;
switch (this.mode) {
case FormattingMode.Write: {
nextMode = FormattingMode.Preview;
break;
}
case FormattingMode.Preview: {
nextMode = FormattingMode.Write;
break;
}
}
// Update mode to next mode
this.$emit("mode", nextMode);
}
}
};
Expand All @@ -183,15 +289,25 @@ $c: ".c-inbox-form-formatting";
$group-spacing-edges: 12px;
#{$c} {
display: flex;
align-items: center;
column-gap: 14px;
&,
#{$c}__groups,
#{$c}__modes {
display: flex;
align-items: center;
}
#{$c}__group,
#{$c}__modes {
column-gap: 5px;
}
#{$c}__group {
border-inline-end: 1px solid rgb(var(--color-border-tertiary));
font-size: ($font-size-baseline - 1px);
margin-inline-end: $group-spacing-edges;
padding-inline-end: $group-spacing-edges;
column-gap: 5px;
display: flex;
align-items: center;
Expand All @@ -214,5 +330,31 @@ $group-spacing-edges: 12px;
}
}
}
#{$c}__modes {
flex: 1;
justify-content: flex-end;
#{$c}__mode {
#{$c}__mode-icon {
margin-inline-end: 5px;
}
#{$c}__mode-label {
font-size: ($font-size-baseline - 2px);
line-height: 12px;
}
&--preview {
#{$c}__mode-icon {
fill: rgb(var(--color-base-blue-dark));
}
#{$c}__mode-label {
color: rgb(var(--color-base-blue-dark));
}
}
}
}
}
</style>
Loading

0 comments on commit 8e74bae

Please sign in to comment.