Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

設定画面のブラウザタブにあるキャッシュ項目の改修 #4184

Open
wants to merge 56 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
9d55813
templateとscriptを編集し、キャッシュ削除ボタンを"削除する"1つに統一
reiroop Dec 2, 2023
7b8b5ac
見た目をデザインの通りに変更
reiroop Dec 2, 2023
27c9778
CacheManager.vueのキャッシュ項目をKBのみに変更
reiroop Dec 24, 2023
d6a2567
CacheClearモーダルの中に入れるロジックを仮作成(動作未確認)
reiroop Dec 24, 2023
5af2ebb
CacheClearModalのプロトタイプができた
reiroop Dec 24, 2023
fd53bb8
モーダルのボタンの見た目を調整
reiroop Jan 1, 2024
db4e645
Merge remote-tracking branch 'origin/master' into fix/setting_browser…
reiroop Jan 1, 2024
d2d0dd7
formCheckboxを利用しない形に変更
reiroop Jan 2, 2024
9e4624e
checkboxのロジックが完成
reiroop Jan 3, 2024
c7e07fe
見た目を調整
reiroop Jan 3, 2024
bf1648c
デバッグ用のselectedCachesを下に移動
reiroop Jan 3, 2024
449a588
見た目を調整
reiroop Jan 3, 2024
2a9da5a
モーダルのsubtitleがアイコンがないときにtitleの位置からずれていた問題を修正
reiroop Jan 4, 2024
8d68d23
モーダルのbodyの余白を調整
reiroop Jan 4, 2024
8a81fc5
FormCheckboxInnerを使ってcheckboxをいい感じに
reiroop Jan 4, 2024
5f6b6e6
checkbox非選択時にグレーアウトするように変更
reiroop Jan 4, 2024
d6acd10
何も選択されていない時に「削除する」がdisabledになるように
reiroop Jan 4, 2024
2b91a39
checkboxのフォーカス時にenterキーで選択状態を変えられるように
reiroop Jan 4, 2024
79a83df
clearCacheを整理
reiroop Jan 4, 2024
845962b
修正忘れを修正
reiroop Jan 5, 2024
f8968db
checkboxをコンポーネントに分割
reiroop Jan 5, 2024
7aef582
「削除する」でモーダルが閉じるよう変更
reiroop Jan 5, 2024
a8dcb45
スマホでlabelのレイアウトが崩れていたのを修正
reiroop Jan 5, 2024
b43355f
FormCheckboxWithLabelSlotを削除し、FormCheckboxを書き換え
reiroop Jan 6, 2024
df07042
aria-checkedの削除
reiroop Jan 10, 2024
85cb661
FormCheckboxを利用していたコンポーネントの修正(未完)
reiroop Jan 10, 2024
d846bb8
type CacheNameに関する変更
reiroop Jan 10, 2024
e491a06
promisesの修正
reiroop Jan 13, 2024
525fdc9
不要なreturnを削除
reiroop Feb 24, 2024
c519812
cacheNameToIsSelectedに変更
reiroop Feb 24, 2024
368c1bf
コメントの追加
reiroop Feb 29, 2024
a1c9699
navigator.storage.estimate()の使用をやめ、cache.matchAll()を使用
reiroop Feb 29, 2024
86b00cf
updateCacheSizeを作成、データ使用量が0になる
reiroop Feb 29, 2024
d46f9c2
キャッシュサイズの表示が常に0になっているバグがある
reiroop Mar 7, 2024
f46306b
updateCacheSize周りのバグ確認
reiroop Mar 12, 2024
df31d5a
CacheName, CacheNamesの定義を変更
reiroop Mar 12, 2024
71435f5
console.logを追加
reiroop Mar 16, 2024
e95c2ad
console.logを変更
reiroop Mar 16, 2024
3648baa
console.logを変更
reiroop Mar 16, 2024
0bc44b5
awaitがなかったのを修正
reiroop Mar 16, 2024
3005fb6
prettifyFileSize()を引数が0のときに対応するよう修正
reiroop Mar 16, 2024
5ee18df
デバッグ用の処理を削除
reiroop Mar 16, 2024
02896fe
cssの調整
reiroop Mar 16, 2024
687acf5
TODOコメントの削除
reiroop Mar 16, 2024
4c4967b
ModalFrame.vueのpadding変更を削除
reiroop Mar 16, 2024
7e33717
TODOコメントの削除
reiroop Mar 16, 2024
771998c
'traQ_S-precache'を'traQ_S’に変更
reiroop Mar 16, 2024
327da96
ModalFrame.vueの.bodyの左右のpaddingを16pxに変更
reiroop Mar 16, 2024
1328af0
キャッシュ名を変えてみる
reiroop Mar 16, 2024
87c7ed1
キャッシュサイズの計算の対象を削除処理の対象と揃えた
reiroop Mar 16, 2024
c96ff33
await忘れを修正
reiroop Mar 16, 2024
9a5a2cf
TODOの処理
reiroop Mar 16, 2024
6195e5c
ModalFrameのbodyの左右のpaddingを24pxに戻した
reiroop Mar 16, 2024
110ac8e
Merge branch 'master' into fix/setting_browser_cache
reiroop Apr 5, 2024
e435688
ミスの修正
reiroop Apr 5, 2024
504382d
form-checkbox関連の修正
reiroop Apr 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/Modal/Common/ModalFrame.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { useModalStore } from '/@/store/ui/modal'
withDefaults(
defineProps<{
iconMdi?: boolean
iconName: string
iconName?: string
title: string
subtitle?: string
returnButton?: boolean
Expand Down
19 changes: 14 additions & 5 deletions src/components/Modal/Common/ModalHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
<modal-return-button v-if="returnButton" :class="$style.returnButton" />
<div :class="$style.content">
<h1 :class="$style.title">
<a-icon :class="$style.icon" :name="iconName" :mdi="iconMdi" />{{
title
}}
<a-icon
v-if="iconName"
:class="$style.icon"
:name="iconName"
:mdi="iconMdi"
/>
{{ title }}
</h1>
<h2 :class="$style.subtitle"><slot name="subtitle" /></h2>
<h2 :class="$style.subtitle" :data-has-icon="$boolAttr(!iconName)">
<slot name="subtitle" />
</h2>
</div>
</div>
</template>
Expand All @@ -19,7 +25,7 @@ import ModalReturnButton from './ModalReturnButton.vue'
withDefaults(
defineProps<{
iconMdi?: boolean
iconName: string
iconName?: string
title: string
subtitle?: string
returnButton?: boolean
Expand Down Expand Up @@ -69,6 +75,9 @@ withDefaults(
weight: 500;
size: 0.875rem;
}
&[data-has-icon] {
padding-left: 0;
}
}
.icon {
margin-right: 16px;
Expand Down
5 changes: 3 additions & 2 deletions src/components/Modal/GroupCreateModal/GroupCreateModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
<form-checkbox
v-model="addMember"
:class="[$style.item, $style.memberCheckbox]"
label="自分自身をメンバーに追加する"
/>
>
自分自身をメンバーに追加する
</form-checkbox>
<div :class="$style.createButtonWrapper">
<form-button label="作成" @click="create" />
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Modal/ModalContainer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import GroupCreateModal from './GroupCreateModal/GroupCreateModal.vue'
import GroupMemberEditModal from './GroupMemberEditModal/GroupMemberEditModal.vue'
import GroupAdminAddModal from './GroupAdminAddModal/GroupAdminAddModal.vue'
import GroupMemberAddModal from './GroupMemberAddModal/GroupMemberAddModal.vue'
import SettingsCacheClearModal from './SettingsCacheClearModal/SettingsCacheClearModal.vue'

const { shouldShowModal, currentState } = useModalStore()

Expand Down Expand Up @@ -96,6 +97,8 @@ const component = computed(() => {
return GroupAdminAddModal
case 'group-member-add':
return GroupMemberAddModal
case 'settings-cache-clear':
return SettingsCacheClearModal
}
// eslint-disable-next-line no-console
console.error('Unexpected modal type:', currentState.value)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<template>
<modal-frame
title="キャッシュの削除"
subtitle="キャッシュを削除する項目を選んで下さい。"
>
<div :class="$style.content">
<div :class="$style.checkboxContainer">
<form-checkbox
v-for="name in cacheCategories"
:key="name"
v-model="cacheCategoryToIsSelected[name]"
:class="$style.checkbox"
>
<div :class="$style.label">
{{ cacheLabel(name) }}
<span>{{ cacheSize[name] }}</span>
</div>
</form-checkbox>
</div>
<div :class="$style.buttonContainer">
<form-button label="キャンセル" type="tertiary" @click="clearModal" />
<form-button
label="削除する"
type="secondary"
:disabled="!anyCacheSelected"
is-danger
@click="clearCache"
/>
</div>
</div>
</modal-frame>
</template>

<script lang="ts" setup>
import { onMounted, ref, computed } from 'vue'
import { useToastStore } from '/@/store/ui/toast'
import { wait } from '/@/lib/basic/timer'
import ModalFrame from '../Common/ModalFrame.vue'
import FormButton from '/@/components/UI/FormButton.vue'
import { useModalStore } from '/@/store/ui/modal'
import FormCheckbox from '/@/components/UI/FormCheckbox.vue'
import { prettifyFileSize } from '/@/lib/basic/file'

declare global {
interface StorageEstimate {
usageDetails: Record<CacheCategory, number>
}
}

const confirmClear = () => window.confirm('本当に削除しますか?')

/* CacheStorageのnameはsw.jsを参照 */
const clearCacheStorage = (cacheCategory: string) =>
window.caches.delete(cacheCategory)

const { addSuccessToast } = useToastStore()
const showToast = (extraMessage?: string) => {
addSuccessToast(
`削除に成功しました${extraMessage ? `: ${extraMessage}` : ''}`
)
}

const cacheCategories = [
'traQ_S-precache',
'files-cache',
'thumbnail-cache'
] as const
type CacheCategory = (typeof cacheCategories)[number]

const cacheCategoryToIsSelected = ref(
Object.fromEntries(cacheCategories.map(name => [name, false]))
)
const anyCacheSelected = computed(() => {
return Object.values(cacheCategoryToIsSelected).includes(true)
})

const cacheSize = ref(
Object.fromEntries(cacheCategories.map(name => [name, '']))
)

const cacheNames = async (category: CacheCategory) => {
if (!(category === 'traQ_S-precache')) {
return [category]
}
const allNames = await window.caches.keys()
return allNames.filter(name => name.startsWith(category))
}

const updateCacheSize = async () => {
await Promise.all(
cacheCategories.map(async category => {
cacheSize.value[category] = prettifyFileSize(
await calculateCacheSizeSum(await cacheNames(category))
)
})
)
}
onMounted(updateCacheSize)

const calculateCacheSizeSum = async (cacheNames: string[]) => {
let size = 0
await Promise.all(
cacheNames.map(async cacheName => {
size += await calculateEachCacheSize(cacheName)
})
)
return size
}

const calculateEachCacheSize = async (cacheName: string) => {
const cache = await window.caches.open(cacheName)
const keys = await cache.keys()
let size = 0
await Promise.all(
keys.map(async key => {
const response = await cache.match(key)
if (!response) return
const blob = await response.blob()
size += blob.size
mehm8128 marked this conversation as resolved.
Show resolved Hide resolved
})
)
return size
}

const cacheLabel = (cacheCategory: CacheCategory) => {
switch (cacheCategory) {
case 'traQ_S-precache':
return 'traQ本体'
case 'files-cache':
return 'ファイルの本体一覧'
case 'thumbnail-cache':
return 'ファイルのサムネイル一覧'
default:
throw new Error(
`Unknown cache name: ${cacheCategory satisfies CacheCategory}`
)
}
}

const { clearModal } = useModalStore()

const isClearingCache = ref(false)

const clearMainCachePromises = async () => {
const names = await cacheNames('traQ_S-precache')
return names.map(name => {
clearCacheStorage(name)
})
}

const clearCache = async () => {
if (isClearingCache.value || !confirmClear()) return
isClearingCache.value = true
const promises = []
if (cacheCategoryToIsSelected.value['traQ_S-precache']) {
promises.push(clearMainCachePromises())
}
if (cacheCategoryToIsSelected.value['files-cache']) {
promises.push(clearCacheStorage('files-cache'))
}
if (cacheCategoryToIsSelected.value['thumbnail-cache']) {
promises.push(clearCacheStorage('thumbnail-cache'))
}
await Promise.all(promises.flat())
if (!cacheCategoryToIsSelected.value['traQ_S-precache']) {
isClearingCache.value = false
clearModal()
showToast()
return
}
const registration = await navigator.serviceWorker?.getRegistration()
if (!registration) {
isClearingCache.value = false
clearModal()
showToast()
return
}
registration.unregister()
isClearingCache.value = false
showToast('1秒後にリロードします')
await wait(1000)
clearModal()
window.location.reload()
}
</script>

<style lang="scss" module>
.content {
display: flex;
flex-direction: column;
gap: 32px;
}
.checkboxContainer {
display: flex;
flex-direction: column;
gap: 8px;
}
.checkbox {
@include color-ui-secondary;
&:has(:checked) {
@include color-ui-primary;
}
display: flex;
justify-content: space-between;
gap: 4px;
padding: 8px;
align-items: center;
cursor: pointer;
border: solid 2px transparent;
border-radius: 4px;
&:focus-within {
border-color: $theme-accent-focus-default;
}
}
.label {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 8px 16px;
}
.buttonContainer {
display: flex;
justify-content: flex-end;
gap: 16px;
}
</style>