diff --git a/src/components/Main/MainView/MessageElement/MessageTools.vue b/src/components/Main/MainView/MessageElement/MessageTools.vue
index b0a595e16..7db50641a 100644
--- a/src/components/Main/MainView/MessageElement/MessageTools.vue
+++ b/src/components/Main/MainView/MessageElement/MessageTools.vue
@@ -61,6 +61,14 @@
:class="$style.icon"
@click="toggleStampPicker"
/>
+
import { computed, ref } from 'vue'
-import type { StampId, MessageId } from '/@/types/entity-ids'
+import type { StampId, MessageId, ClipFolderId } from '/@/types/entity-ids'
import { useStampPickerInvoker } from '/@/store/ui/stampPicker'
import { useResponsiveStore } from '/@/store/ui/responsive'
import apis from '/@/lib/apis'
@@ -95,6 +103,7 @@ import AStamp from '/@/components/UI/AStamp.vue'
import MessageContextMenu from './MessageContextMenu.vue'
import useToggle from '/@/composables/utils/useToggle'
import { useStampHistory } from '/@/store/domain/stampHistory'
+import { useCreateClip } from '/@/composables/clips/createClip'
const props = withDefaults(
defineProps<{
@@ -169,6 +178,24 @@ const onDotsClick = (e: MouseEvent) => {
})
}
+const DEFAULT_CLIP_FOLDER_ID = '201fcb38-3dbe-4a53-8c0c-37b47bed9985' // FIXME: あとで直す
+const clippingFolderIds = ref(new Set())
+const isClipped = computed(() =>
+ clippingFolderIds.value.has(DEFAULT_CLIP_FOLDER_ID)
+)
+
+apis.getMessageClips(props.messageId).then(res => {
+ clippingFolderIds.value = new Set(res.data.map(c => c.folderId))
+})
+const clipIconName = computed(() => {
+ return isClipped.value ? 'bookmark-check' : 'bookmark'
+})
+
+const { toggleClip } = useCreateClip(props.messageId, clippingFolderIds)
+const openClipCreateModal = () => {
+ toggleClip(DEFAULT_CLIP_FOLDER_ID)
+}
+
const { isMobile } = useResponsiveStore()
const { value: showQuickReaction, toggle: toggleQuickReaction } = useToggle(
@@ -231,6 +258,9 @@ const { value: showQuickReaction, toggle: toggleQuickReaction } = useToggle(
&:hover {
@include background-secondary;
}
+ &[data-clipped] {
+ @include color-accent-primary;
+ }
}
.stampListItem {
diff --git a/src/components/Modal/ClipCreateModal/ClipCreateModal.vue b/src/components/Modal/ClipCreateModal/ClipCreateModal.vue
index 025f529c2..90926378b 100644
--- a/src/components/Modal/ClipCreateModal/ClipCreateModal.vue
+++ b/src/components/Modal/ClipCreateModal/ClipCreateModal.vue
@@ -4,71 +4,31 @@
-
+
+
+
+
-
-
diff --git a/src/components/Modal/ClipCreateModal/ClipFolderNew.vue b/src/components/Modal/ClipCreateModal/ClipFolderNew.vue
new file mode 100644
index 000000000..c5921dcbb
--- /dev/null
+++ b/src/components/Modal/ClipCreateModal/ClipFolderNew.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
diff --git a/src/composables/clips/createClip.ts b/src/composables/clips/createClip.ts
new file mode 100644
index 000000000..afa73a1af
--- /dev/null
+++ b/src/composables/clips/createClip.ts
@@ -0,0 +1,44 @@
+import type { Ref } from 'vue'
+import apis from '/@/lib/apis'
+import type { MessageId, ClipFolderId } from '/@/types/entity-ids'
+import { useToastStore } from '/@/store/ui/toast'
+import type { AxiosError } from 'axios'
+
+export const useCreateClip = (
+ messageId: MessageId,
+ isSelected: Ref>
+) => {
+ const { addSuccessToast, addErrorToast } = useToastStore()
+
+ const createClip = async (clipFolderId: ClipFolderId) => {
+ try {
+ await apis.clipMessage(clipFolderId, {
+ messageId: messageId
+ })
+ isSelected.value.add(clipFolderId)
+ addSuccessToast('クリップフォルダに追加しました')
+ } catch (e) {
+ if ((e as AxiosError).response?.status === 409) {
+ isSelected.value.add(clipFolderId)
+ addErrorToast('すでに追加されています')
+ return
+ } else {
+ addErrorToast('追加に失敗しました')
+ }
+ throw e
+ }
+ }
+ const deleteClip = async (clipFolderId: ClipFolderId) => {
+ await apis.unclipMessage(clipFolderId, messageId)
+ isSelected.value.delete(clipFolderId)
+ addSuccessToast('クリップフォルダから削除しました')
+ }
+ const toggleClip = async (clipFolderId: ClipFolderId) => {
+ if (isSelected.value.has(clipFolderId)) {
+ await deleteClip(clipFolderId)
+ } else {
+ await createClip(clipFolderId)
+ }
+ }
+ return { toggleClip }
+}