Skip to content

Conversation

@marugorou
Copy link

@marugorou marugorou commented Aug 11, 2025

概要

日をまたいだ際に日時の表示を更新する処理を追加しました。

なぜこの PR を入れたいのか

close #4606

動作確認の手順

日付が変わるのを待ち、日時の表示が変わることを確認する。(タイムゾーンをいじると楽かもしれないです。)

UI 変更部分のスクリーンショット

before

after

PR を出す前の確認事項

  • (機能の追加なら)追加することの合意がチームで取れている
    • 取れていない場合はチェックを外して PR にすれば OK
  • 動作確認ができている
  • 自分で一度コードを眺めて自分的に問題はなさそう

見てほしいところ・聞きたいことなど

MessageHeaderごとに更新の処理が走るので、少し非効率な気がします。

@github-actions
Copy link

@marugorou marugorou requested a review from a team as a code owner September 2, 2025 10:20
@codecov
Copy link

codecov bot commented Sep 2, 2025

Codecov Report

❌ Patch coverage is 0% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 13.49%. Comparing base (db66cd0) to head (523d9e8).

Files with missing lines Patch % Lines
src/composables/useDateRepresetation.ts 0.00% 28 Missing ⚠️
...nts/Main/MainView/MessageElement/MessageHeader.vue 0.00% 21 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4750      +/-   ##
==========================================
- Coverage   13.54%   13.49%   -0.05%     
==========================================
  Files         704      705       +1     
  Lines       31691    31800     +109     
  Branches      676      676              
==========================================
- Hits         4293     4292       -1     
- Misses      27386    27496     +110     
  Partials       12       12              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Pugma Pugma requested a review from Copilot October 1, 2025 14:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds automatic date display updates when the day changes for message headers in the application.

  • Introduces a new useDateRepresentation composable that automatically updates date display when crossing midnight
  • Replaces the static computed date property with a reactive date that updates via scheduled timeouts
  • Implements proper cleanup of timers on component unmount to prevent memory leaks

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 28 to 32
<script lang="ts">
import { ref, onMounted, onUnmounted, watchEffect } from 'vue'
import { getDateRepresentation } from '/@/lib/basic/date'
const useDateRepresentation = (updatedAt: string) => {
Copy link

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useDateRepresentation function is defined in a separate script block but should be moved to a composables directory (e.g., /@/composables/useDateRepresentation.ts) for better code organization and reusability across components.

Copilot uses AI. Check for mistakes.
Comment on lines 29 to 49
import { ref, onMounted, onUnmounted, watchEffect } from 'vue'
import { getDateRepresentation } from '/@/lib/basic/date'
const useDateRepresentation = (updatedAt: string) => {
const dateTimeout = ref<ReturnType<typeof setTimeout>>()
const date = ref<string>('')
watchEffect(() => {
date.value = getDateRepresentation(updatedAt)
})
const subscribeDateChange = () => {
const now = new Date()
const tomorrow = new Date()
tomorrow.setDate(now.getDate() + 1)
tomorrow.setHours(0, 0, 0, 0)
dateTimeout.value = setTimeout(() => {
date.value = getDateRepresentation(updatedAt)
subscribeDateChange()
}, tomorrow.getTime() - now.getTime())
}
onMounted(() => subscribeDateChange())
onUnmounted(() => clearTimeout(dateTimeout.value))
Copy link

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each MessageHeader component creates its own timer, which could be inefficient with many messages. Consider using a global timer that broadcasts date changes to all components instead of creating individual timers per component.

Suggested change
import { ref, onMounted, onUnmounted, watchEffect } from 'vue'
import { getDateRepresentation } from '/@/lib/basic/date'
const useDateRepresentation = (updatedAt: string) => {
const dateTimeout = ref<ReturnType<typeof setTimeout>>()
const date = ref<string>('')
watchEffect(() => {
date.value = getDateRepresentation(updatedAt)
})
const subscribeDateChange = () => {
const now = new Date()
const tomorrow = new Date()
tomorrow.setDate(now.getDate() + 1)
tomorrow.setHours(0, 0, 0, 0)
dateTimeout.value = setTimeout(() => {
date.value = getDateRepresentation(updatedAt)
subscribeDateChange()
}, tomorrow.getTime() - now.getTime())
}
onMounted(() => subscribeDateChange())
onUnmounted(() => clearTimeout(dateTimeout.value))
import { ref, onMounted, onUnmounted, watchEffect, computed } from 'vue'
import { getDateRepresentation } from '/@/lib/basic/date'
// Global midnight tick composable
const midnightTick = ref(new Date())
let midnightTimeout: ReturnType<typeof setTimeout> | null = null
function scheduleNextMidnightTick() {
const now = new Date()
const tomorrow = new Date()
tomorrow.setDate(now.getDate() + 1)
tomorrow.setHours(0, 0, 0, 0)
const msUntilMidnight = tomorrow.getTime() - now.getTime()
midnightTimeout = setTimeout(() => {
midnightTick.value = new Date()
scheduleNextMidnightTick()
}, msUntilMidnight)
}
if (typeof window !== 'undefined' && !midnightTimeout) {
scheduleNextMidnightTick()
}
const useMidnightTick = () => midnightTick
const useDateRepresentation = (updatedAt: string) => {
const tick = useMidnightTick()
const date = ref<string>(getDateRepresentation(updatedAt))
watchEffect(() => {
// Recompute date when tick or updatedAt changes
date.value = getDateRepresentation(updatedAt)
})

Copilot uses AI. Check for mistakes.
}, tomorrow.getTime() - now.getTime())
}
onMounted(() => subscribeDateChange())
onUnmounted(() => clearTimeout(dateTimeout.value))
Copy link

Copilot AI Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout cleanup doesn't check if dateTimeout.value is defined. If the component unmounts before subscribeDateChange is called, this could attempt to clear an undefined timeout.

Suggested change
onUnmounted(() => clearTimeout(dateTimeout.value))
onUnmounted(() => {
if (dateTimeout.value !== undefined) {
clearTimeout(dateTimeout.value)
}
})

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@Pugma Pugma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらコメントをつけました!
ご確認をお願いします 🙏

import { ref, onMounted, onUnmounted, watchEffect } from 'vue'
import { getDateRepresentation } from '/@/lib/basic/date'
const useDateRepresentation = (updatedAt: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここは copilot のコメントのとおりだと思います
/src/composables 以下にこのような再利用可能な関数をおいているところがあるので、そちらに移してしまいましょう

また、 (画面で見えない部分を含む) 読み込んでいる範囲すべての投稿が現在時刻を参照するようになってしまうので、それも処理が重くなる原因として copilot からコメントがついてます
これは、先の部分で触れたのと同じように composable 以下に移して、それを各投稿のコンポーネントから参照するようにすることでまとめて解決できると思います

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(横槍ごめんなさい :sorry:) composables にまとめたところで setTimeout のインスタンスが大量に生成されるのは回避できない気がします
(パフォーマンスに問題があるようなら effect scope とかを使うとよさそうです)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

composables にまとめたうえで、この部分から各投稿の時間表示を更新するイベントを発火できればいいのかなって思っていたんだけど、それが effect scope になるのかな

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ~ Copilot がそういう変更を提示してくれているんですね、よく読んでいませんでしたすみません :pray-nya:
でもなんか間違ってる気がするので、やはり effect scope あたりを使って実装するのが無難そうです (他にシンプルな実装の仕方があるならそれでもよさそうですけれど)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`<script lang="ts">
import { useDateRepresentation } from '/@/composables/useDateRepresentation'

export default {
setup() {
const date = useDateRepresentation(updatedAt)
return { date }
}
}
</script>`

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


ありがとうございます。わかりました。copilotの言うとおりに、composablesにuseDateRepresentation.tsとしてまとめました。これを参照する方法を調べたのですが、MessageHeader.vueの元の部分のところを
上のように変えるというので良いのでしょうか?

また、copilotが最後に指摘している
onUnmounted(() => clearTimeout(dateTimeout.value))
という文言がuseDateRepresentationに見当たらず、どうすればよいか分かりません。

お手数をおかけしまして申し訳ありません。よろしくお願いします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

日付が変わっても表記が「今日」から「昨日」に変わらない

5 participants