perf: Add category / tag chip color (#1539)

This commit is contained in:
Rémi Marseault 2024-02-29 13:09:29 +01:00 committed by GitHub
parent 36b682f426
commit 05b3e357c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 48 additions and 9 deletions

9
package-lock.json generated
View file

@ -8,6 +8,7 @@
"name": "vuetorrent",
"version": "2.7.1",
"dependencies": {
"@ctrl/tinycolor": "^4.0.3",
"@faker-js/faker": "^8.4.1",
"@fontsource/roboto": "^5.0.8",
"@fontsource/roboto-mono": "^5.0.16",
@ -123,6 +124,14 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true
},
"node_modules/@ctrl/tinycolor": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.0.3.tgz",
"integrity": "sha512-e9nEVehVJwkymQpkGhdSNzLT2Lr9UTTby+JePq4Z2SxBbOQjY7pLgSouAaXvfaGQVSAaY0U4eJdwfSDmCbItcw==",
"engines": {
"node": ">=14"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",

View file

@ -15,6 +15,7 @@
"coverage": "vitest run --coverage"
},
"dependencies": {
"@ctrl/tinycolor": "^4.0.3",
"@faker-js/faker": "^8.4.1",
"@fontsource/roboto": "^5.0.8",
"@fontsource/roboto-mono": "^5.0.16",

View file

@ -1,9 +1,10 @@
<script setup lang="ts">
import { getColorFromName } from '@/helpers'
import { useVueTorrentStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { computed } from 'vue'
const props = defineProps<{ torrent: Torrent; title: string; value: string; color: string }>()
const props = defineProps<{ torrent: Torrent; title: string; value: string; color: string; enableHashColor: boolean }>()
const vueTorrentStore = useVueTorrentStore()
@ -27,7 +28,7 @@ const emptyValue = computed(() => values.value.length < 1)
<v-chip v-if="!values || emptyValue" :color="color.replace('$1', torrent[value])" variant="flat">
{{ $t(`torrent.properties.empty_${value}`) }}
</v-chip>
<v-chip v-else v-for="val in values" :color="color.replace('$1', torrent.state)" variant="flat">
<v-chip v-else v-for="val in values" :color="enableHashColor ? getColorFromName(val) : color.replace('$1', torrent.state)" variant="flat">
{{ val }}
</v-chip>
</div>

View file

@ -1,9 +1,10 @@
<script setup lang="ts">
import { getColorFromName } from '@/helpers'
import { useVueTorrentStore } from '@/stores'
import { Torrent } from '@/types/vuetorrent'
import { computed } from 'vue'
const props = defineProps<{ torrent: Torrent; title: string; value: string; color: string }>()
const props = defineProps<{ torrent: Torrent; title: string; value: string; color: string; enableHashColor: boolean }>()
const vueTorrentStore = useVueTorrentStore()
@ -24,7 +25,7 @@ const emptyValue = computed(() => values.value.length < 1)
<v-chip v-if="!values || emptyValue" :color="color.replace('$1', torrent[value])" variant="flat">
{{ $t(`torrent.properties.empty_${value}`) }}
</v-chip>
<v-chip v-else v-for="val in values" :color="color.replace('$1', torrent.state)" variant="flat">
<v-chip v-else v-for="val in values" :color="enableHashColor ? getColorFromName(val) : color.replace('$1', torrent.state)" variant="flat">
{{ val }}
</v-chip>
</div>

View file

@ -4,7 +4,7 @@ import { DashboardPropertyType } from './DashboardPropertyType'
type pptData = { active: boolean; order: number }
type pptMetadata =
| { type: DashboardPropertyType.AMOUNT; props: { title: string; value: string; total: string } }
| { type: DashboardPropertyType.CHIP; props: { title: string; value: string; color: string } }
| { type: DashboardPropertyType.CHIP; props: { title: string; value: string; color: string; enableHashColor: boolean } }
| { type: DashboardPropertyType.DATA; props: { title: string; value: string } }
| { type: DashboardPropertyType.DATETIME; props: { title: string; value: string } }
| { type: DashboardPropertyType.DURATION; props: { title: string; value: string } }
@ -211,7 +211,7 @@ export const propsMetadata: PropertyMetadata = {
type: DashboardPropertyType.SPEED
},
[DashboardProperty.CATEGORY]: {
props: { title: 'category', value: 'category', color: 'category' },
props: { title: 'category', value: 'category', color: 'category', enableHashColor: true },
type: DashboardPropertyType.CHIP
},
[DashboardProperty.COMPLETED_ON]: {
@ -315,11 +315,11 @@ export const propsMetadata: PropertyMetadata = {
type: DashboardPropertyType.DATA
},
[DashboardProperty.STATE]: {
props: { title: 'state', value: 'stateString', color: 'torrent-$1' },
props: { title: 'state', value: 'stateString', color: 'torrent-$1', enableHashColor: false },
type: DashboardPropertyType.CHIP
},
[DashboardProperty.TAGS]: {
props: { title: 'tags', value: 'tags', color: 'tag' },
props: { title: 'tags', value: 'tags', color: 'tag', enableHashColor: true },
type: DashboardPropertyType.CHIP
},
[DashboardProperty.TIME_ACTIVE]: {
@ -331,7 +331,7 @@ export const propsMetadata: PropertyMetadata = {
type: DashboardPropertyType.DATA
},
[DashboardProperty.TRACKER]: {
props: { title: 'tracker', value: 'tracker_domain', color: 'tracker' },
props: { title: 'tracker', value: 'tracker_domain', color: 'tracker', enableHashColor: false },
type: DashboardPropertyType.CHIP
},
[DashboardProperty.TRACKERS_COUNT]: {

View file

@ -0,0 +1,8 @@
import { expect, test } from 'vitest'
import { getColorFromName } from './colors'
test('helpers/colors/getColorFromName', () => {
expect(getColorFromName('foo')).toBe('#7b2fde')
expect(getColorFromName('bar')).toBe('#97e374')
expect(getColorFromName('baz')).toBe('#447ecf')
})

17
src/helpers/colors.ts Normal file
View file

@ -0,0 +1,17 @@
import { random } from '@ctrl/tinycolor'
function djb2Hash(str: string): number {
let hash = 5381
for (let i = 0; i < str.length; i++) {
hash = (hash * 33) ^ str.charCodeAt(i)
}
return hash >>> 0 // ensure non-negative integer
}
export function getColorFromName(name: string) {
const color = random({
seed: djb2Hash(name)
})
return color.toHexString()
}

View file

@ -1,3 +1,4 @@
import { getColorFromName } from './colors'
import { formatDataValue, formatDataUnit, formatData } from './data'
import { formatEta } from './datetime'
import { toPrecision, formatPercent } from './number'
@ -6,6 +7,7 @@ import { isWindows, isMac, doesCommand } from './system'
import { titleCase, capitalize, extractHostname, getDomainBody, splitByUrl, stringContainsUrl, codeToFlag } from './text'
export {
getColorFromName,
formatDataValue,
formatDataUnit,
formatData,