Skip to content

Commit daafa23

Browse files
authored
Merge pull request #4949 from traPtitech/feat/stamp-recommendation
feat(stamp): スタンプのレコメンド機能を追加
2 parents 9cd6c75 + ba7c6f3 commit daafa23

File tree

12 files changed

+138
-20
lines changed

12 files changed

+138
-20
lines changed

package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"@mdi/js": "^7.4.47",
3232
"@sapphi-red/web-noise-suppressor": "^0.3.5",
3333
"@shiguredo/virtual-background": "^2023.2.0",
34-
"@traptitech/traq": "^3.25.1-5",
34+
"@traptitech/traq": "^3.26.1-1",
3535
"@traptitech/traq-markdown-it": "^7.0.2",
3636
"autosize": "^6.0.1",
3737
"browser-image-compression": "^2.0.2",

src/components/Main/MainView/MessageElement/MessageTools.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<transition v-if="!isMinimum" name="quick-reaction">
99
<div v-if="showQuickReaction || !isMobile" :class="$style.quickReaction">
1010
<AStamp
11-
v-for="stamp in recentStamps"
11+
v-for="stamp in topStamps"
1212
:key="stamp"
1313
:stamp-id="stamp"
1414
:size="28"
@@ -96,7 +96,7 @@ import useToggle from '/@/composables/utils/useToggle'
9696
import { isDefined } from '/@/lib/basic/array'
9797
import { useStampUpdater } from '/@/lib/updater/stamp'
9898
import { useMeStore } from '/@/store/domain/me'
99-
import { useStampHistory } from '/@/store/domain/stampHistory'
99+
import { useTopStampIds } from '/@/store/domain/stampRecommendations'
100100
import { useMessagesStore } from '/@/store/entities/messages'
101101
import { useStampsStore } from '/@/store/entities/stamps'
102102
import { useMessageEditingStateStore } from '/@/store/ui/messageEditingStateStore'
@@ -120,7 +120,7 @@ const props = withDefaults(
120120
121121
const isActive = defineModel<boolean>('isActive', { default: false })
122122
123-
const { recentStampIds } = useStampHistory()
123+
const { topStampIds } = useTopStampIds()
124124
const { addStampOptimistically } = useStampUpdater()
125125
const { initialRecentStamps } = useStampsStore()
126126
@@ -139,10 +139,10 @@ const pushInitialRecentStampsIfNeeded = (
139139
}
140140
}
141141
142-
const recentStamps = computed(() => {
143-
const recents = recentStampIds.value.slice(0, 3)
144-
pushInitialRecentStampsIfNeeded(initialRecentStamps.value, recents)
145-
return recents
142+
const topStamps = computed(() => {
143+
const tops = topStampIds.value.slice(0, 3)
144+
pushInitialRecentStampsIfNeeded(initialRecentStamps.value, tops)
145+
return tops
146146
})
147147
const addStamp = async (stampId: StampId) =>
148148
addStampOptimistically(props.messageId, stampId)

src/components/Main/MainView/MessageInput/composables/suggestion/overrides/stampSuggestion.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type MaybeRefOrGetter, computed, toValue } from 'vue'
22

33
import { useStampHistory } from '/@/store/domain/stampHistory'
4+
import { useStampRecommendations } from '/@/store/domain/stampRecommendations'
45

56
import type {
67
Candidate,
@@ -19,6 +20,7 @@ const stampSuggestionOverride = <
1920
input: Params
2021
) => {
2122
const { upsertLocalStampHistory } = useStampHistory()
23+
const { recordStampUsage } = useStampRecommendations()
2224

2325
const isStampSuggestion = computed(() =>
2426
toValue(input.confirmedPart).text.startsWith(':')
@@ -35,6 +37,7 @@ const stampSuggestionOverride = <
3537

3638
const onSelect = (word: WordWithId) => {
3739
upsertLocalStampHistory(word.id, new Date())
40+
recordStampUsage(word.id)
3841
input.onSelect({ ...word, text: `${word.text}:` })
3942
}
4043

src/components/Main/StampPicker/StampPicker.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { onMounted, ref } from 'vue'
5353
import ClickOutside from '/@/components/UI/ClickOutside'
5454
import FilterInput from '/@/components/UI/FilterInput.vue'
5555
import { useStampHistory } from '/@/store/domain/stampHistory'
56+
import { useStampRecommendations } from '/@/store/domain/stampRecommendations'
5657
import { useResponsiveStore } from '/@/store/ui/responsive'
5758
import { useStampPicker } from '/@/store/ui/stampPicker'
5859
import type { StampId } from '/@/types/entity-ids'
@@ -75,6 +76,7 @@ const {
7576
closeStampPicker
7677
} = useStampPicker()
7778
const { upsertLocalStampHistory } = useStampHistory()
79+
const { recordStampUsage } = useStampRecommendations()
7880
const { isMobile } = useResponsiveStore()
7981
8082
const animationKeys = ref(new Map<StampId, number>())
@@ -99,6 +101,7 @@ const filterInputRef = ref<InstanceType<typeof FilterInput> | null>(null)
99101
100102
const onInputStamp = (id: StampId) => {
101103
upsertLocalStampHistory(id, new Date())
104+
recordStampUsage(id)
102105
selectHandler.value({
103106
id,
104107
sizeEffect: selectedSizeEffect.value,

src/components/Main/StampPicker/composables/useStampList.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Ref } from 'vue'
22
import { computed } from 'vue'
33

44
import { useStampCategory } from '/@/store/domain/stampCategory'
5-
import { useStampHistory } from '/@/store/domain/stampHistory'
5+
import { useTopStampIds } from '/@/store/domain/stampRecommendations'
66
import { useStampPalettesStore } from '/@/store/entities/stampPalettes'
77
import { useStampsStore } from '/@/store/entities/stamps'
88
import type { StampId } from '/@/types/entity-ids'
@@ -12,13 +12,13 @@ import type { StampSet } from './useStampSetSelector'
1212

1313
const useStampList = (currentStampSet: Ref<StampSet>) => {
1414
const { traQStampCategory, unicodeStampCategories } = useStampCategory()
15-
const { recentStampIds } = useStampHistory()
15+
const { topStampIds } = useTopStampIds()
1616
const { stampsMap } = useStampsStore()
1717
const { stampPalettesMap } = useStampPalettesStore()
1818

1919
const stampIds = computed((): readonly StampId[] => {
2020
if (currentStampSet.value.type === 'history') {
21-
return recentStampIds.value
21+
return topStampIds.value
2222
}
2323
if (currentStampSet.value.type === 'palette') {
2424
const id = currentStampSet.value.id

src/components/Settings/StampPaletteTab/StampPaletteEditorAddableStampList.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ import { computed, onUnmounted, ref, watch } from 'vue'
4646
import useStampFilter from '/@/components/Main/StampPicker/composables/useStampFilter'
4747
import FilterInput from '/@/components/UI/FilterInput.vue'
4848
import { useStampHistory } from '/@/store/domain/stampHistory'
49+
import {
50+
useStampRecommendations,
51+
useTopStampIds
52+
} from '/@/store/domain/stampRecommendations'
4953
import { useStampsStore } from '/@/store/entities/stamps'
5054
import type { StampId } from '/@/types/entity-ids'
5155
@@ -58,25 +62,27 @@ const currentStampIds = defineModel<StampId[]>('current-stamp-ids', {
5862
})
5963
6064
const { stampsMap, stampsMapFetched } = useStampsStore()
61-
const { recentStampIds, fetchStampHistory } = useStampHistory()
65+
const { fetchStampHistory } = useStampHistory()
66+
const { fetchStampRecommendations } = useStampRecommendations()
67+
const { topStampIds } = useTopStampIds()
6268
const { filterState } = useStampFilter()
6369
6470
const displayCount = ref(ITEMS_PER_LOAD)
6571
6672
fetchStampHistory()
67-
73+
fetchStampRecommendations()
6874
const allAddableStamps = computed(() => {
6975
if (!stampsMapFetched.value) {
7076
return []
7177
}
7278
return (
7379
filterState.query === ''
7480
? [
75-
...recentStampIds.value
81+
...topStampIds.value
7682
.map(id => stampsMap.value.get(id))
7783
.filter(stamp => stamp !== undefined),
7884
...filterState.filteredItems
79-
.filter(stamp => !recentStampIds.value.includes(stamp.id))
85+
.filter(stamp => !topStampIds.value.includes(stamp.id))
8086
.sort((a, b) => a.name.localeCompare(b.name))
8187
]
8288
: filterState.filteredItems

src/components/ShareTarget/ShareTargetMessageInput.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import useMessageInputState from '/@/composables/messageInputState/useMessageInp
4444
import useMessageInputStateAttachment from '/@/composables/messageInputState/useMessageInputStateAttachment'
4545
import { randomString } from '/@/lib/basic/randomString'
4646
import { useStampHistory } from '/@/store/domain/stampHistory'
47+
import { useStampRecommendations } from '/@/store/domain/stampRecommendations'
4748
import { useStampPalettesStore } from '/@/store/entities/stampPalettes'
4849
import { useStampsStore } from '/@/store/entities/stamps'
4950
import { useToastStore } from '/@/store/ui/toast'
@@ -52,6 +53,7 @@ import useAttachments from '../Main/MainView/MessageInput/composables/useAttachm
5253
import useTextStampPickerInvoker from '../Main/MainView/composables/useTextStampPickerInvoker'
5354
5455
const { fetchStampHistory } = useStampHistory()
56+
const { fetchStampRecommendations } = useStampRecommendations()
5557
const { fetchStamps } = useStampsStore()
5658
const { fetchStampPalettes } = useStampPalettesStore()
5759
const { state } = useMessageInputState('share-target')
@@ -81,6 +83,7 @@ const { toggleStampPicker } = useTextStampPickerInvoker(
8183
fetchStamps()
8284
fetchStampPalettes()
8385
fetchStampHistory()
86+
fetchStampRecommendations()
8487
8588
const id = randomString()
8689
</script>

src/lib/updater/stamp.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import apis from '/@/lib/apis'
22
import { useStampHistory } from '/@/store/domain/stampHistory'
3+
import { useStampRecommendations } from '/@/store/domain/stampRecommendations'
34
import { useMessagesStore } from '/@/store/entities/messages'
45
import { useToastStore } from '/@/store/ui/toast'
56
import type { MessageId, StampId } from '/@/types/entity-ids'
67

78
export const useStampUpdater = () => {
89
const { addErrorToast } = useToastStore()
910
const { upsertLocalStampHistory } = useStampHistory()
11+
const { recordStampUsage } = useStampRecommendations()
1012
const { addStampLocally, removeStampLocally } = useMessagesStore()
1113

1214
const addStampOptimistically = async (
@@ -15,6 +17,7 @@ export const useStampUpdater = () => {
1517
) => {
1618
const cancel = addStampLocally(messageId, stampId)
1719
upsertLocalStampHistory(stampId, new Date())
20+
recordStampUsage(stampId)
1821
try {
1922
await apis.addMessageStamp(messageId, stampId)
2023
} catch {

src/store/app/featureFlagSettings.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ export const featureFlagDescriptions = {
4343
'お気に入りチャンネル一覧を、お気に入りに登録されたチャンネルのみの木構造で表示します。',
4444
defaultValue: false,
4545
endAt: new Date('2025-12-31T23:59')
46+
},
47+
stamp_recommendation: {
48+
title: 'スタンプのレコメンド機能',
49+
description:
50+
'スタンプのレコメンド機能を有効にします。スタンプ履歴が用いられている部分をレコメンドで置き換えます。',
51+
defaultValue: false,
52+
endAt: new Date('2026-01-31T23:59')
4653
}
4754
} as const satisfies Record<string, FeatureFlagDescription>
4855

0 commit comments

Comments
 (0)