feat, refac: MessagePlate

This commit is contained in:
2023-03-09 02:20:14 +09:00
parent 9ed3b0a921
commit e7e9ba2201
+260
View File
@@ -0,0 +1,260 @@
<template>
<div
:id="`msg_${msg.id}`"
:class="['msg_plate', `msg_plate_${msg.msgType}`, `msg_plate_${nationType}`]"
data-id="${id}"
>
<div class="msg_icon">
<img v-if="src.icon" class="generalIcon" width="64" height="64" :src="encodeURI(src.icon)" />
<img v-else class="generalIcon" width="64" height="64" :src="encodeURI(defaultIcon)" />
</div>
<div class="msg_body">
<div class="msg_header">
<template v-if="deletable">
<button
type="button"
class="btn btn btn-outline-warning btn-sm btn-delete-msg"
style="float: right"
@click="tryDelete"
>
</button>
</template>
<template v-if="msg.msgType == 'private'">
<template v-if="src.name == generalName">
<span :class="`msg_target msg_${srcColorType}`" :style="{ backgroundColor: src.color }"></span
><span class="msg_from_to"></span
><span :class="`msg_target msg_${destColorType}`" :style="{ backgroundColor: dest.color }"
>{{ dest.name }}:{{ dest.nation }}</span
>
</template>
<template v-else>
<span :class="`msg_target msg_${srcColorType}`" :style="{ backgroundColor: src.color }"
>{{ src.name }}:{{ src.nation }}</span
><span class="msg_from_to"></span
><span :class="`msg_target msg_${destColorType}`" :style="{ backgroundColor: dest.color }"></span>
</template>
</template>
<template v-else-if="msg.msgType == 'national' && src.nation_id === dest.nation_id">
<span :class="`msg_target msg_${srcColorType}`" :style="{ backgroundColor: src.color }">{{ src.name }}</span>
</template>
<template v-else-if="msg.msgType == 'national' || msg.msgType == 'diplomacy'">
<template v-if="src.nation_id == nationID">
<span :class="`msg_target msg_${srcColorType}`" :style="{ backgroundColor: src.color }">{{ src.name }}</span
><span class="msg_from_to"></span
><span :class="`msg_target msg_${destColorType}`" :style="{ backgroundColor: dest.color }">{{
dest.nation
}}</span>
</template>
<template v-else>
<span :class="`msg_target msg_${srcColorType}`" :style="{ backgroundColor: src.color }"
>{{ src.name }}:{{ src.nation }}</span
><span class="msg_from_to"></span>
</template>
</template>
<template v-else>
<span :class="`msg_target msg_${srcColorType}`" :style="{ backgroundColor: src.color }"
>{{ src.name }}:{{ src.nation }}</span
>
</template>
<span class="msg_time">&lt;{{ msg.time }}&gt;</span>
</div>
<!-- eslint-disable-next-line vue/no-v-html vue/max-attributes-per-line -->
<div :class="['msg_content', isValidMsg ? 'msg_valid' : 'msg_invalid']" v-html="isValidMsg ? linkifyStr(msg.text) : '삭제된 메시지입니다'"
></div>
<div v-if="msg.option.action" class="msg_prompt">
<button
type="button"
class="prompt_yes btn_prompt"
:disabled="allowButton ? true : undefined"
@click="tryAccept"
>
수락
</button>
<button
type="button"
class="prompt_no btn_prompt"
:disabled="allowButton ? true : undefined"
@click="tryDecline"
>
거절
</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { MsgItem, MsgTarget } from "@/defs/API/Message";
import { parseTime } from "@/util/parseTime";
import { differenceInMilliseconds, addMinutes } from "date-fns/esm";
import { computed, ref, toRef, watch, type ComputedRef, type Ref } from "vue";
import linkifyStr from "linkifyjs/string";
import { SammoAPI } from "@/SammoAPI";
import { isError, isString } from "lodash";
import { isBrightColor } from "@/util/isBrightColor";
const props = defineProps<{
modelValue: MsgItem;
generalID: number;
generalName: string;
nationID: number;
permissionLevel: number;
deleted?: boolean;
}>();
const emit = defineEmits<{
(event: "request-refresh"): void;
}>();
const src: Ref<MsgTarget> = ref(props.modelValue.src);
const dest: Ref<MsgTarget> = ref(props.modelValue.src);
const srcColorType = computed(() => isBrightColor(src.value.color)) ? "bright" : "dark";
const destColorType = computed(() => isBrightColor(dest.value.color)) ? "bright" : "dark";
const msg = toRef(props, "modelValue");
const defaultIcon = `${window.pathConfig.sharedIcon}/default.jpg`;
const isValidMsg = ref(true);
const deletable = ref(false);
watch(
() => props.deleted,
() => {
isValidMsg.value = testValidMsg(msg.value);
deletable.value = testDeletable(msg.value);
}
);
watch(
msg,
(msg) => {
isValidMsg.value = testValidMsg(msg);
deletable.value = testDeletable(msg);
src.value = msg.src;
dest.value = msg.dest ?? {
id: 0,
name: "",
nation: "재야",
nation_id: 0,
color: "#000000",
icon: defaultIcon,
};
},
{ immediate: true }
);
const deletableTimer: Ref<number | undefined> = ref();
const allowButton = computed(() => {
if (msg.value.msgType != "diplomacy") {
return true;
}
if (props.permissionLevel >= 4) {
return true;
}
return false;
});
function testDeletable(msg: MsgItem): boolean {
if (deletableTimer.value) {
clearTimeout(deletableTimer.value);
}
if (props.deleted) return false;
if (msg.option.action) return false;
if (msg.src.id != props.generalID) return false;
if (msg.option.invalid) return false;
if (!msg.option.deletable) return false;
const now = new Date();
const last5min = addMinutes(parseTime(msg.time), 5);
const timeDiff = differenceInMilliseconds(last5min, now);
if (timeDiff <= 0) return false;
deletableTimer.value = window.setTimeout(() => {
deletable.value = testDeletable(msg);
}, timeDiff);
return true;
}
const nationType: ComputedRef<"local" | "src" | "dest"> = computed(() => {
if (msg.value.src.nation_id === msg.value.dest?.nation_id) {
return "local";
}
if (msg.value.src.nation_id === props.nationID) {
return "src";
}
return "dest";
});
function testValidMsg(msg: MsgItem): boolean {
if (props.deleted) {
return false;
}
if (msg.option.invalid) {
return false;
}
return true;
}
async function tryDelete() {
if (!confirm("삭제하시겠습니까?")) {
return false;
}
try {
await SammoAPI.Message.DeleteMessage({ msgID: msg.value.id });
} catch (e) {
if (isString(e)) {
alert(e);
}
if (isError(e)) {
alert(e.message);
}
console.error(e);
}
emit("request-refresh");
}
async function tryAccept() {
if (!confirm("수락하시겠습니까?")) {
return false;
}
try {
await SammoAPI.Message.DecideMessageResponse({ msgID: msg.value.id, response: true });
} catch (e) {
if (isString(e)) {
alert(e);
}
if (isError(e)) {
alert(e.message);
}
console.error(e);
}
emit("request-refresh");
}
async function tryDecline() {
if (!confirm("거절하시겠습니까?")) {
return false;
}
try {
await SammoAPI.Message.DecideMessageResponse({ msgID: msg.value.id, response: false });
} catch (e) {
if (isString(e)) {
alert(e);
}
if (isError(e)) {
alert(e.message);
}
console.error(e);
}
emit("request-refresh");
}
</script>