mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-25 17:53:48 +02:00
feat: add spacing option to friends locations card and favtories cards (#1477)
This commit is contained in:
@@ -21,10 +21,10 @@
|
|||||||
<el-button :icon="MoreFilled" size="small" circle />
|
<el-button :icon="MoreFilled" size="small" circle />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="favorites-dropdown">
|
<el-dropdown-menu class="favorites-dropdown">
|
||||||
<li class="favorites-dropdown__scale" @click.stop>
|
<li class="favorites-dropdown__control" @click.stop>
|
||||||
<div class="favorites-dropdown__scale-header">
|
<div class="favorites-dropdown__control-header">
|
||||||
<span>Scale</span>
|
<span>Scale</span>
|
||||||
<span class="favorites-dropdown__scale-value">{{ avatarCardScalePercent }}%</span>
|
<span class="favorites-dropdown__control-value">{{ avatarCardScalePercent }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<el-slider
|
<el-slider
|
||||||
v-model="avatarCardScale"
|
v-model="avatarCardScale"
|
||||||
@@ -34,6 +34,21 @@
|
|||||||
:step="avatarCardScaleSlider.step"
|
:step="avatarCardScaleSlider.step"
|
||||||
:show-tooltip="false" />
|
:show-tooltip="false" />
|
||||||
</li>
|
</li>
|
||||||
|
<li class="favorites-dropdown__control" @click.stop>
|
||||||
|
<div class="favorites-dropdown__control-header">
|
||||||
|
<span>Spacing</span>
|
||||||
|
<span class="favorites-dropdown__control-value">
|
||||||
|
{{ avatarCardSpacingPercent }}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-slider
|
||||||
|
v-model="avatarCardSpacing"
|
||||||
|
class="favorites-dropdown__slider"
|
||||||
|
:min="avatarCardSpacingSlider.min"
|
||||||
|
:max="avatarCardSpacingSlider.max"
|
||||||
|
:step="avatarCardSpacingSlider.step"
|
||||||
|
:show-tooltip="false" />
|
||||||
|
</li>
|
||||||
<el-dropdown-item @click="handleAvatarImportClick">
|
<el-dropdown-item @click="handleAvatarImportClick">
|
||||||
{{ t('view.favorite.import') }}
|
{{ t('view.favorite.import') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
@@ -531,17 +546,31 @@
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
cardScale: avatarCardScale,
|
cardScale: avatarCardScale,
|
||||||
|
cardSpacing: avatarCardSpacing,
|
||||||
slider: avatarCardScaleSlider,
|
slider: avatarCardScaleSlider,
|
||||||
|
spacingSlider: avatarCardSpacingSlider,
|
||||||
containerRef: avatarFavoritesContainerRef,
|
containerRef: avatarFavoritesContainerRef,
|
||||||
gridStyle: avatarFavoritesGridStyle
|
gridStyle: avatarFavoritesGridStyle
|
||||||
} = useFavoritesCardScaling({
|
} = useFavoritesCardScaling({
|
||||||
configKey: 'VRCX_FavoritesAvatarCardScale',
|
configKey: 'VRCX_FavoritesAvatarCardScale',
|
||||||
|
spacingConfigKey: 'VRCX_FavoritesAvatarCardSpacing',
|
||||||
min: 0.6,
|
min: 0.6,
|
||||||
max: 1,
|
max: 1,
|
||||||
step: 0.01
|
step: 0.01,
|
||||||
|
spacingMin: 0.5,
|
||||||
|
spacingMax: 1.5,
|
||||||
|
spacingStep: 0.05,
|
||||||
|
basePaddingY: 8,
|
||||||
|
basePaddingX: 10,
|
||||||
|
baseContentGap: 10,
|
||||||
|
baseActionGap: 8,
|
||||||
|
baseActionGroupGap: 6,
|
||||||
|
baseActionMargin: 8,
|
||||||
|
baseCheckboxMargin: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
const avatarCardScalePercent = computed(() => Math.round(avatarCardScale.value * 100));
|
const avatarCardScalePercent = computed(() => Math.round(avatarCardScale.value * 100));
|
||||||
|
const avatarCardSpacingPercent = computed(() => Math.round(avatarCardSpacing.value * 100));
|
||||||
|
|
||||||
const avatarExportDialogVisible = ref(false);
|
const avatarExportDialogVisible = ref(false);
|
||||||
const avatarFavoriteSearch = ref('');
|
const avatarFavoriteSearch = ref('');
|
||||||
@@ -1460,7 +1489,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -1469,7 +1497,8 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
height: 32px;
|
min-height: 32px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-group-menu__item:hover {
|
.favorites-group-menu__item:hover {
|
||||||
@@ -1500,7 +1529,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
@@ -1509,7 +1537,8 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
height: 32px;
|
min-height: 32px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-visibility-menu__item:hover,
|
.group-visibility-menu__item:hover,
|
||||||
@@ -1625,7 +1654,7 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 1px solid var(--el-border-color);
|
border: 1px solid var(--el-border-color);
|
||||||
border-radius: calc(8px * var(--favorites-card-scale, 1));
|
border-radius: calc(8px * var(--favorites-card-scale, 1));
|
||||||
padding: calc(8px * var(--favorites-card-scale, 1)) calc(10px * var(--favorites-card-scale, 1));
|
padding: var(--favorites-card-padding-y, 8px) var(--favorites-card-padding-x, 10px);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--el-bg-color);
|
background: var(--el-bg-color);
|
||||||
transition:
|
transition:
|
||||||
@@ -1650,7 +1679,7 @@
|
|||||||
:deep(.favorites-search-card__content) {
|
:deep(.favorites-search-card__content) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: calc(10px * var(--favorites-card-scale, 1));
|
gap: var(--favorites-card-content-gap, 10px);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
@@ -1720,8 +1749,8 @@
|
|||||||
:deep(.favorites-search-card__actions) {
|
:deep(.favorites-search-card__actions) {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: var(--favorites-card-action-gap, 8px);
|
||||||
margin-left: 8px;
|
margin-left: var(--favorites-card-action-margin, 8px);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -1740,7 +1769,7 @@
|
|||||||
|
|
||||||
:deep(.favorites-search-card__action-group) {
|
:deep(.favorites-search-card__action-group) {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: var(--favorites-card-action-group-gap, 6px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1751,7 +1780,7 @@
|
|||||||
:deep(.favorites-search-card__action--checkbox) {
|
:deep(.favorites-search-card__action--checkbox) {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-right: 10px;
|
margin-right: var(--favorites-card-checkbox-margin, 10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.favorites-search-card__action--checkbox .el-checkbox) {
|
:deep(.favorites-search-card__action--checkbox .el-checkbox) {
|
||||||
@@ -1771,15 +1800,18 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale {
|
.favorites-dropdown__control {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 12px 16px 8px;
|
padding: 12px 16px 8px;
|
||||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale-header {
|
.favorites-dropdown__control:not(:last-child) {
|
||||||
|
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.favorites-dropdown__control-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -1789,7 +1821,7 @@
|
|||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale-value {
|
.favorites-dropdown__control-value {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--el-text-color-secondary);
|
color: var(--el-text-color-secondary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,12 @@
|
|||||||
<el-button :icon="MoreFilled" size="small" circle @click.stop />
|
<el-button :icon="MoreFilled" size="small" circle @click.stop />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="favorites-dropdown">
|
<el-dropdown-menu class="favorites-dropdown">
|
||||||
<li class="favorites-dropdown__scale" @click.stop>
|
<li class="favorites-dropdown__control" @click.stop>
|
||||||
<div class="favorites-dropdown__scale-header">
|
<div class="favorites-dropdown__control-header">
|
||||||
<span>Scale</span>
|
<span>Scale</span>
|
||||||
<span class="favorites-dropdown__scale-value">{{ friendCardScalePercent }}%</span>
|
<span class="favorites-dropdown__control-value">
|
||||||
|
{{ friendCardScalePercent }}%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<el-slider
|
<el-slider
|
||||||
v-model="friendCardScale"
|
v-model="friendCardScale"
|
||||||
@@ -34,6 +36,21 @@
|
|||||||
:step="friendCardScaleSlider.step"
|
:step="friendCardScaleSlider.step"
|
||||||
:show-tooltip="false" />
|
:show-tooltip="false" />
|
||||||
</li>
|
</li>
|
||||||
|
<li class="favorites-dropdown__control" @click.stop>
|
||||||
|
<div class="favorites-dropdown__control-header">
|
||||||
|
<span>Spacing</span>
|
||||||
|
<span class="favorites-dropdown__control-value">
|
||||||
|
{{ friendCardSpacingPercent }}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-slider
|
||||||
|
v-model="friendCardSpacing"
|
||||||
|
class="favorites-dropdown__slider"
|
||||||
|
:min="friendCardSpacingSlider.min"
|
||||||
|
:max="friendCardSpacingSlider.max"
|
||||||
|
:step="friendCardSpacingSlider.step"
|
||||||
|
:show-tooltip="false" />
|
||||||
|
</li>
|
||||||
<el-dropdown-item @click="handleFriendImportClick">
|
<el-dropdown-item @click="handleFriendImportClick">
|
||||||
{{ t('view.favorite.import') }}
|
{{ t('view.favorite.import') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
@@ -295,17 +312,31 @@
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
cardScale: friendCardScale,
|
cardScale: friendCardScale,
|
||||||
|
cardSpacing: friendCardSpacing,
|
||||||
slider: friendCardScaleSlider,
|
slider: friendCardScaleSlider,
|
||||||
|
spacingSlider: friendCardSpacingSlider,
|
||||||
containerRef: friendFavoritesContainerRef,
|
containerRef: friendFavoritesContainerRef,
|
||||||
gridStyle: friendFavoritesGridStyle
|
gridStyle: friendFavoritesGridStyle
|
||||||
} = useFavoritesCardScaling({
|
} = useFavoritesCardScaling({
|
||||||
configKey: 'VRCX_FavoritesFriendCardScale',
|
configKey: 'VRCX_FavoritesFriendCardScale',
|
||||||
|
spacingConfigKey: 'VRCX_FavoritesFriendCardSpacing',
|
||||||
min: 0.6,
|
min: 0.6,
|
||||||
max: 1,
|
max: 1,
|
||||||
step: 0.01
|
step: 0.01,
|
||||||
|
spacingMin: 0.5,
|
||||||
|
spacingMax: 1.5,
|
||||||
|
spacingStep: 0.05,
|
||||||
|
basePaddingY: 8,
|
||||||
|
basePaddingX: 10,
|
||||||
|
baseContentGap: 10,
|
||||||
|
baseActionGap: 8,
|
||||||
|
baseActionGroupGap: 6,
|
||||||
|
baseActionMargin: 8,
|
||||||
|
baseCheckboxMargin: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
const friendCardScalePercent = computed(() => Math.round(friendCardScale.value * 100));
|
const friendCardScalePercent = computed(() => Math.round(friendCardScale.value * 100));
|
||||||
|
const friendCardSpacingPercent = computed(() => Math.round(friendCardSpacing.value * 100));
|
||||||
|
|
||||||
const friendExportDialogVisible = ref(false);
|
const friendExportDialogVisible = ref(false);
|
||||||
const friendFavoriteSearch = ref('');
|
const friendFavoriteSearch = ref('');
|
||||||
@@ -808,7 +839,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -817,7 +847,8 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
height: 32px;
|
min-height: 32px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-group-menu__item:hover {
|
.favorites-group-menu__item:hover {
|
||||||
@@ -848,7 +879,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
@@ -857,7 +887,8 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
height: 32px;
|
min-height: 32px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-visibility-menu__item:hover,
|
.group-visibility-menu__item:hover,
|
||||||
@@ -973,7 +1004,7 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 1px solid var(--el-border-color);
|
border: 1px solid var(--el-border-color);
|
||||||
border-radius: calc(8px * var(--favorites-card-scale, 1));
|
border-radius: calc(8px * var(--favorites-card-scale, 1));
|
||||||
padding: calc(8px * var(--favorites-card-scale, 1)) calc(10px * var(--favorites-card-scale, 1));
|
padding: var(--favorites-card-padding-y, 8px) var(--favorites-card-padding-x, 10px);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--el-bg-color);
|
background: var(--el-bg-color);
|
||||||
transition:
|
transition:
|
||||||
@@ -998,7 +1029,7 @@
|
|||||||
:deep(.favorites-search-card__content) {
|
:deep(.favorites-search-card__content) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: calc(10px * var(--favorites-card-scale, 1));
|
gap: var(--favorites-card-content-gap, 10px);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
@@ -1068,8 +1099,8 @@
|
|||||||
:deep(.favorites-search-card__actions) {
|
:deep(.favorites-search-card__actions) {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: var(--favorites-card-action-gap, 8px);
|
||||||
margin-left: 8px;
|
margin-left: var(--favorites-card-action-margin, 8px);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -1088,7 +1119,7 @@
|
|||||||
|
|
||||||
:deep(.favorites-search-card__action-group) {
|
:deep(.favorites-search-card__action-group) {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: var(--favorites-card-action-group-gap, 6px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,7 +1130,7 @@
|
|||||||
:deep(.favorites-search-card__action--checkbox) {
|
:deep(.favorites-search-card__action--checkbox) {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-right: 10px;
|
margin-right: var(--favorites-card-checkbox-margin, 10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.favorites-search-card__action--checkbox .el-checkbox) {
|
:deep(.favorites-search-card__action--checkbox .el-checkbox) {
|
||||||
@@ -1127,15 +1158,18 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale {
|
.favorites-dropdown__control {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 12px 16px 8px;
|
padding: 12px 16px 8px;
|
||||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale-header {
|
.favorites-dropdown__control:not(:last-child) {
|
||||||
|
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.favorites-dropdown__control-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -1145,7 +1179,7 @@
|
|||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale-value {
|
.favorites-dropdown__control-value {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--el-text-color-secondary);
|
color: var(--el-text-color-secondary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,12 @@
|
|||||||
<el-button :icon="MoreFilled" size="small" circle />
|
<el-button :icon="MoreFilled" size="small" circle />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="favorites-dropdown">
|
<el-dropdown-menu class="favorites-dropdown">
|
||||||
<li class="favorites-dropdown__scale" @click.stop>
|
<li class="favorites-dropdown__control" @click.stop>
|
||||||
<div class="favorites-dropdown__scale-header">
|
<div class="favorites-dropdown__control-header">
|
||||||
<span>Scale</span>
|
<span>Scale</span>
|
||||||
<span class="favorites-dropdown__scale-value">{{ worldCardScalePercent }}%</span>
|
<span class="favorites-dropdown__control-value">
|
||||||
|
{{ worldCardScalePercent }}%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<el-slider
|
<el-slider
|
||||||
v-model="worldCardScale"
|
v-model="worldCardScale"
|
||||||
@@ -34,6 +36,21 @@
|
|||||||
:step="worldCardScaleSlider.step"
|
:step="worldCardScaleSlider.step"
|
||||||
:show-tooltip="false" />
|
:show-tooltip="false" />
|
||||||
</li>
|
</li>
|
||||||
|
<li class="favorites-dropdown__control" @click.stop>
|
||||||
|
<div class="favorites-dropdown__control-header">
|
||||||
|
<span>Spacing</span>
|
||||||
|
<span class="favorites-dropdown__control-value">
|
||||||
|
{{ worldCardSpacingPercent }}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-slider
|
||||||
|
v-model="worldCardSpacing"
|
||||||
|
class="favorites-dropdown__slider"
|
||||||
|
:min="worldCardSpacingSlider.min"
|
||||||
|
:max="worldCardSpacingSlider.max"
|
||||||
|
:step="worldCardSpacingSlider.step"
|
||||||
|
:show-tooltip="false" />
|
||||||
|
</li>
|
||||||
<el-dropdown-item @click="handleWorldImportClick">
|
<el-dropdown-item @click="handleWorldImportClick">
|
||||||
{{ t('view.favorite.import') }}
|
{{ t('view.favorite.import') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
@@ -439,17 +456,31 @@
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
cardScale: worldCardScale,
|
cardScale: worldCardScale,
|
||||||
|
cardSpacing: worldCardSpacing,
|
||||||
slider: worldCardScaleSlider,
|
slider: worldCardScaleSlider,
|
||||||
|
spacingSlider: worldCardSpacingSlider,
|
||||||
containerRef: worldFavoritesContainerRef,
|
containerRef: worldFavoritesContainerRef,
|
||||||
gridStyle: worldFavoritesGridStyle
|
gridStyle: worldFavoritesGridStyle
|
||||||
} = useFavoritesCardScaling({
|
} = useFavoritesCardScaling({
|
||||||
configKey: 'VRCX_FavoritesWorldCardScale',
|
configKey: 'VRCX_FavoritesWorldCardScale',
|
||||||
|
spacingConfigKey: 'VRCX_FavoritesWorldCardSpacing',
|
||||||
min: 0.6,
|
min: 0.6,
|
||||||
max: 1,
|
max: 1,
|
||||||
step: 0.01
|
step: 0.01,
|
||||||
|
spacingMin: 0.5,
|
||||||
|
spacingMax: 1.5,
|
||||||
|
spacingStep: 0.05,
|
||||||
|
basePaddingY: 8,
|
||||||
|
basePaddingX: 10,
|
||||||
|
baseContentGap: 10,
|
||||||
|
baseActionGap: 8,
|
||||||
|
baseActionGroupGap: 6,
|
||||||
|
baseActionMargin: 8,
|
||||||
|
baseCheckboxMargin: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
const worldCardScalePercent = computed(() => Math.round(worldCardScale.value * 100));
|
const worldCardScalePercent = computed(() => Math.round(worldCardScale.value * 100));
|
||||||
|
const worldCardSpacingPercent = computed(() => Math.round(worldCardSpacing.value * 100));
|
||||||
|
|
||||||
const worldGroupVisibilityOptions = ref(['public', 'friends', 'private']);
|
const worldGroupVisibilityOptions = ref(['public', 'friends', 'private']);
|
||||||
const worldSplitterSize = ref(260);
|
const worldSplitterSize = ref(260);
|
||||||
@@ -1324,7 +1355,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@@ -1333,7 +1363,8 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
height: 32px;
|
min-height: 32px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
.favorites-group-menu__item:hover {
|
.favorites-group-menu__item:hover {
|
||||||
background-color: var(--el-menu-hover-bg-color);
|
background-color: var(--el-menu-hover-bg-color);
|
||||||
@@ -1363,7 +1394,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
@@ -1372,7 +1402,8 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
transition: background-color 0.15s ease;
|
transition: background-color 0.15s ease;
|
||||||
height: 32px;
|
min-height: 32px;
|
||||||
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-visibility-menu__item:hover,
|
.group-visibility-menu__item:hover,
|
||||||
@@ -1488,7 +1519,7 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 1px solid var(--el-border-color);
|
border: 1px solid var(--el-border-color);
|
||||||
border-radius: calc(8px * var(--favorites-card-scale, 1));
|
border-radius: calc(8px * var(--favorites-card-scale, 1));
|
||||||
padding: calc(8px * var(--favorites-card-scale, 1)) calc(10px * var(--favorites-card-scale, 1));
|
padding: var(--favorites-card-padding-y, 8px) var(--favorites-card-padding-x, 10px);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--el-bg-color);
|
background: var(--el-bg-color);
|
||||||
transition:
|
transition:
|
||||||
@@ -1513,7 +1544,7 @@
|
|||||||
:deep(.favorites-search-card__content) {
|
:deep(.favorites-search-card__content) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: calc(10px * var(--favorites-card-scale, 1));
|
gap: var(--favorites-card-content-gap, 10px);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
@@ -1583,8 +1614,8 @@
|
|||||||
:deep(.favorites-search-card__actions) {
|
:deep(.favorites-search-card__actions) {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: var(--favorites-card-action-gap, 8px);
|
||||||
margin-left: 8px;
|
margin-left: var(--favorites-card-action-margin, 8px);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -1603,7 +1634,7 @@
|
|||||||
|
|
||||||
:deep(.favorites-search-card__action-group) {
|
:deep(.favorites-search-card__action-group) {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: var(--favorites-card-action-group-gap, 6px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1614,7 +1645,7 @@
|
|||||||
:deep(.favorites-search-card__action--checkbox) {
|
:deep(.favorites-search-card__action--checkbox) {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-right: 10px;
|
margin-right: var(--favorites-card-checkbox-margin, 10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.favorites-search-card__action--checkbox .el-checkbox) {
|
:deep(.favorites-search-card__action--checkbox .el-checkbox) {
|
||||||
@@ -1634,15 +1665,18 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale {
|
.favorites-dropdown__control {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 12px 16px 8px;
|
padding: 12px 16px 8px;
|
||||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale-header {
|
.favorites-dropdown__control:not(:last-child) {
|
||||||
|
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.favorites-dropdown__control-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -1652,7 +1686,7 @@
|
|||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorites-dropdown__scale-value {
|
.favorites-dropdown__control-value {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--el-text-color-secondary);
|
color: var(--el-text-color-secondary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,12 +28,33 @@ export function useFavoritesCardScaling(options = {}) {
|
|||||||
max: options.max ?? 1,
|
max: options.max ?? 1,
|
||||||
step: options.step ?? 0.01
|
step: options.step ?? 0.01
|
||||||
};
|
};
|
||||||
|
const spacingSlider = {
|
||||||
|
min: options.spacingMin ?? 0.5,
|
||||||
|
max: options.spacingMax ?? 1.5,
|
||||||
|
step: options.spacingStep ?? 0.05
|
||||||
|
};
|
||||||
const baseWidth = options.baseWidth ?? 260;
|
const baseWidth = options.baseWidth ?? 260;
|
||||||
const baseGap = options.baseGap ?? 12;
|
const baseGap = options.baseGap ?? 12;
|
||||||
const gapStep = options.gapStep ?? 8;
|
const gapStep = options.gapStep ?? 8;
|
||||||
const configKey = options.configKey ?? '';
|
const configKey = options.configKey ?? '';
|
||||||
|
const spacingConfigKey = options.spacingConfigKey ?? '';
|
||||||
|
const basePaddingY = options.basePaddingY ?? 8;
|
||||||
|
const basePaddingX = options.basePaddingX ?? 10;
|
||||||
|
const baseContentGap = options.baseContentGap ?? 10;
|
||||||
|
const baseActionGap = options.baseActionGap ?? 8;
|
||||||
|
const baseActionGroupGap = options.baseActionGroupGap ?? 6;
|
||||||
|
const baseActionMargin = options.baseActionMargin ?? 8;
|
||||||
|
const baseCheckboxMargin = options.baseCheckboxMargin ?? 10;
|
||||||
|
const minGap = options.minGap ?? 4;
|
||||||
|
const minPadding = options.minPadding ?? 4;
|
||||||
|
const defaultSpacing = clamp(
|
||||||
|
options.defaultSpacing ?? 1,
|
||||||
|
spacingSlider.min,
|
||||||
|
spacingSlider.max
|
||||||
|
);
|
||||||
|
|
||||||
const cardScaleBase = ref(1);
|
const cardScaleBase = ref(1);
|
||||||
|
const cardSpacingBase = ref(defaultSpacing);
|
||||||
const containerRef = ref(null);
|
const containerRef = ref(null);
|
||||||
const containerWidth = ref(0);
|
const containerWidth = ref(0);
|
||||||
|
|
||||||
@@ -69,15 +90,59 @@ export function useFavoritesCardScaling(options = {}) {
|
|||||||
const nextValue = clamp(Number(value) || 1, slider.min, slider.max);
|
const nextValue = clamp(Number(value) || 1, slider.min, slider.max);
|
||||||
cardScaleBase.value = nextValue;
|
cardScaleBase.value = nextValue;
|
||||||
if (configKey) {
|
if (configKey) {
|
||||||
configRepository.setString(configKey, nextValue);
|
configRepository.setString(configKey, String(nextValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const cardSpacing = computed({
|
||||||
|
get: () => cardSpacingBase.value,
|
||||||
|
set: (value) => {
|
||||||
|
const nextValue = clamp(
|
||||||
|
Number(value) || 1,
|
||||||
|
spacingSlider.min,
|
||||||
|
spacingSlider.max
|
||||||
|
);
|
||||||
|
cardSpacingBase.value = nextValue;
|
||||||
|
if (spacingConfigKey) {
|
||||||
|
configRepository.setString(spacingConfigKey, String(nextValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const gridStyle = computed(() => {
|
const gridStyle = computed(() => {
|
||||||
const minWidth = baseWidth * cardScale.value;
|
const minWidth = baseWidth * cardScale.value;
|
||||||
const rawGap = baseGap + (cardScale.value - 1) * gapStep;
|
const spacing = cardSpacing.value;
|
||||||
const gap = Math.max(6, rawGap);
|
const adjustedGapBase = baseGap + (cardScale.value - 1) * gapStep;
|
||||||
|
const gap = Math.max(minGap, adjustedGapBase * spacing);
|
||||||
|
const paddingY = Math.max(
|
||||||
|
minPadding,
|
||||||
|
basePaddingY * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
const paddingX = Math.max(
|
||||||
|
minPadding,
|
||||||
|
basePaddingX * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
const contentGap = Math.max(
|
||||||
|
minPadding,
|
||||||
|
baseContentGap * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
const actionsGap = Math.max(
|
||||||
|
minPadding,
|
||||||
|
baseActionGap * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
const actionsGroupGap = Math.max(
|
||||||
|
minPadding,
|
||||||
|
baseActionGroupGap * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
const actionsMargin = Math.max(
|
||||||
|
0,
|
||||||
|
baseActionMargin * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
const checkboxMargin = Math.max(
|
||||||
|
0,
|
||||||
|
baseCheckboxMargin * cardScale.value * spacing
|
||||||
|
);
|
||||||
|
|
||||||
return (count = 1, options = {}) => {
|
return (count = 1, options = {}) => {
|
||||||
const width = Math.max(containerWidth.value ?? 0, 0);
|
const width = Math.max(containerWidth.value ?? 0, 0);
|
||||||
@@ -100,9 +165,7 @@ export function useFavoritesCardScaling(options = {}) {
|
|||||||
const columns = Math.max(1, Math.min(safeCount, requestedColumns));
|
const columns = Math.max(1, Math.min(safeCount, requestedColumns));
|
||||||
const forceStretch = Boolean(options?.forceStretch);
|
const forceStretch = Boolean(options?.forceStretch);
|
||||||
const disableAutoStretch = Boolean(options?.disableAutoStretch);
|
const disableAutoStretch = Boolean(options?.disableAutoStretch);
|
||||||
const matchMaxColumnWidth = Boolean(
|
const matchMaxColumnWidth = Boolean(options?.matchMaxColumnWidth);
|
||||||
options?.matchMaxColumnWidth
|
|
||||||
);
|
|
||||||
const shouldStretch =
|
const shouldStretch =
|
||||||
!disableAutoStretch &&
|
!disableAutoStretch &&
|
||||||
(forceStretch || itemCount >= maxColumns);
|
(forceStretch || itemCount >= maxColumns);
|
||||||
@@ -133,7 +196,15 @@ export function useFavoritesCardScaling(options = {}) {
|
|||||||
'--favorites-card-gap': `${Math.round(gap)}px`,
|
'--favorites-card-gap': `${Math.round(gap)}px`,
|
||||||
'--favorites-card-target-width': `${Math.round(cardWidth)}px`,
|
'--favorites-card-target-width': `${Math.round(cardWidth)}px`,
|
||||||
'--favorites-grid-columns': `${columns}`,
|
'--favorites-grid-columns': `${columns}`,
|
||||||
'--favorites-card-scale': `${cardScale.value.toFixed(2)}`
|
'--favorites-card-scale': `${cardScale.value.toFixed(2)}`,
|
||||||
|
'--favorites-card-padding-y': `${Math.round(paddingY)}px`,
|
||||||
|
'--favorites-card-padding-x': `${Math.round(paddingX)}px`,
|
||||||
|
'--favorites-card-content-gap': `${Math.round(contentGap)}px`,
|
||||||
|
'--favorites-card-action-gap': `${Math.round(actionsGap)}px`,
|
||||||
|
'--favorites-card-action-group-gap': `${Math.round(actionsGroupGap)}px`,
|
||||||
|
'--favorites-card-action-margin': `${Math.round(actionsMargin)}px`,
|
||||||
|
'--favorites-card-checkbox-margin': `${Math.round(checkboxMargin)}px`,
|
||||||
|
'--favorites-card-spacing-scale': `${cardSpacing.value.toFixed(2)}`
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -184,34 +255,46 @@ export function useFavoritesCardScaling(options = {}) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
if (!configKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (configKey) {
|
||||||
const storedScale = await configRepository.getString(
|
const storedScale = await configRepository.getString(
|
||||||
configKey,
|
configKey,
|
||||||
'1'
|
'1'
|
||||||
);
|
);
|
||||||
const parsedValue = parseFloat(storedScale);
|
const parsedScale = parseFloat(storedScale);
|
||||||
if (!Number.isNaN(parsedValue)) {
|
if (!Number.isNaN(parsedScale)) {
|
||||||
cardScaleBase.value = clamp(
|
cardScaleBase.value = clamp(
|
||||||
parsedValue,
|
parsedScale,
|
||||||
slider.min,
|
slider.min,
|
||||||
slider.max
|
slider.max
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
}
|
||||||
console.error(
|
|
||||||
'Failed to load favorites card scale preference',
|
if (spacingConfigKey) {
|
||||||
error
|
const storedSpacing = await configRepository.getString(
|
||||||
|
spacingConfigKey,
|
||||||
|
String(defaultSpacing)
|
||||||
);
|
);
|
||||||
|
const parsedSpacing = parseFloat(storedSpacing);
|
||||||
|
if (!Number.isNaN(parsedSpacing)) {
|
||||||
|
cardSpacingBase.value = clamp(
|
||||||
|
parsedSpacing,
|
||||||
|
spacingSlider.min,
|
||||||
|
spacingSlider.max
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load favorites card preferences', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cardScale,
|
cardScale,
|
||||||
|
cardSpacing,
|
||||||
slider,
|
slider,
|
||||||
|
spacingSlider,
|
||||||
containerRef,
|
containerRef,
|
||||||
gridStyle
|
gridStyle
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<div class="friend-view__settings-row">
|
<div class="friend-view__settings-row">
|
||||||
<span class="friend-view__settings-label">Scale</span>
|
<span class="friend-view__settings-label">Scale</span>
|
||||||
<div class="friend-view__scale-control">
|
<div class="friend-view__scale-control">
|
||||||
<span class="friend-view__scale-value">{{ cardScalePercentLabel }} </span>
|
<span class="friend-view__scale-value">{{ cardScalePercentLabel }} </span>
|
||||||
<el-slider
|
<el-slider
|
||||||
v-model="cardScale"
|
v-model="cardScale"
|
||||||
class="friend-view__slider"
|
class="friend-view__slider"
|
||||||
@@ -36,6 +36,19 @@
|
|||||||
:show-tooltip="false" />
|
:show-tooltip="false" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="friend-view__settings-row">
|
||||||
|
<span class="friend-view__settings-label">Spacing</span>
|
||||||
|
<div class="friend-view__scale-control">
|
||||||
|
<span class="friend-view__scale-value">{{ cardSpacingPercentLabel }} </span>
|
||||||
|
<el-slider
|
||||||
|
v-model="cardSpacing"
|
||||||
|
class="friend-view__slider"
|
||||||
|
:min="0.5"
|
||||||
|
:max="1.5"
|
||||||
|
:step="0.05"
|
||||||
|
:show-tooltip="false" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -66,7 +79,8 @@
|
|||||||
v-for="friend in group.friends"
|
v-for="friend in group.friends"
|
||||||
:key="friend.id ?? friend.userId ?? friend.displayName"
|
:key="friend.id ?? friend.userId ?? friend.displayName"
|
||||||
:friend="friend"
|
:friend="friend"
|
||||||
:card-scale="cardScale" />
|
:card-scale="cardScale"
|
||||||
|
:card-spacing="cardSpacing" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,6 +110,7 @@
|
|||||||
:key="friend.id ?? friend.userId ?? friend.displayName"
|
:key="friend.id ?? friend.userId ?? friend.displayName"
|
||||||
:friend="friend"
|
:friend="friend"
|
||||||
:card-scale="cardScale"
|
:card-scale="cardScale"
|
||||||
|
:card-spacing="cardSpacing"
|
||||||
:display-instance-info="false" />
|
:display-instance-info="false" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -111,7 +126,8 @@
|
|||||||
v-for="entry in mergedOnlineEntries"
|
v-for="entry in mergedOnlineEntries"
|
||||||
:key="entry.id ?? entry.friend.id ?? entry.friend.displayName"
|
:key="entry.id ?? entry.friend.id ?? entry.friend.displayName"
|
||||||
:friend="entry.friend"
|
:friend="entry.friend"
|
||||||
:card-scale="cardScale" />
|
:card-scale="cardScale"
|
||||||
|
:card-spacing="cardSpacing" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!mergedSameInstanceGroups.length && !mergedOnlineEntries.length" class="friend-view__empty">
|
<div v-if="!mergedSameInstanceGroups.length && !mergedOnlineEntries.length" class="friend-view__empty">
|
||||||
No matching friends
|
No matching friends
|
||||||
@@ -123,7 +139,8 @@
|
|||||||
v-for="entry in visibleFriends"
|
v-for="entry in visibleFriends"
|
||||||
:key="entry.id ?? entry.friend.id ?? entry.friend.displayName"
|
:key="entry.id ?? entry.friend.id ?? entry.friend.displayName"
|
||||||
:friend="entry.friend"
|
:friend="entry.friend"
|
||||||
:card-scale="cardScale" />
|
:card-scale="cardScale"
|
||||||
|
:card-spacing="cardSpacing" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="friend-view__empty">No matching friends</div>
|
<div v-else class="friend-view__empty">No matching friends</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -175,6 +192,7 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
const cardScaleBase = ref(1);
|
const cardScaleBase = ref(1);
|
||||||
|
const cardSpacingBase = ref(1);
|
||||||
|
|
||||||
const cardScale = computed({
|
const cardScale = computed({
|
||||||
get: () => cardScaleBase.value,
|
get: () => cardScaleBase.value,
|
||||||
@@ -184,7 +202,16 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cardSpacing = computed({
|
||||||
|
get: () => cardSpacingBase.value,
|
||||||
|
set: (value) => {
|
||||||
|
cardSpacingBase.value = value;
|
||||||
|
configRepository.setString('VRCX_FriendLocationCardSpacing', value.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const cardScalePercentLabel = computed(() => `${Math.round(cardScale.value * 100)}%`);
|
const cardScalePercentLabel = computed(() => `${Math.round(cardScale.value * 100)}%`);
|
||||||
|
const cardSpacingPercentLabel = computed(() => `${Math.round(cardSpacing.value * 100)}%`);
|
||||||
|
|
||||||
const showSameInstanceBase = ref(false);
|
const showSameInstanceBase = ref(false);
|
||||||
|
|
||||||
@@ -457,8 +484,9 @@
|
|||||||
const baseWidth = 220;
|
const baseWidth = 220;
|
||||||
const baseGap = 14;
|
const baseGap = 14;
|
||||||
const scale = cardScale.value;
|
const scale = cardScale.value;
|
||||||
|
const spacing = cardSpacing.value;
|
||||||
const minWidth = baseWidth * scale;
|
const minWidth = baseWidth * scale;
|
||||||
const gap = baseGap + (scale - 1) * 10;
|
const gap = Math.max(6, (baseGap + (scale - 1) * 10) * spacing);
|
||||||
|
|
||||||
return (count = 1, options = {}) => {
|
return (count = 1, options = {}) => {
|
||||||
const containerWidth = Math.max(gridWidth.value ?? 0, 0);
|
const containerWidth = Math.max(gridWidth.value ?? 0, 0);
|
||||||
@@ -493,7 +521,8 @@
|
|||||||
'--friend-card-min-width': `${Math.round(minWidth)}px`,
|
'--friend-card-min-width': `${Math.round(minWidth)}px`,
|
||||||
'--friend-card-gap': `${Math.round(gap)}px`,
|
'--friend-card-gap': `${Math.round(gap)}px`,
|
||||||
'--friend-card-target-width': `${Math.round(cardWidth)}px`,
|
'--friend-card-target-width': `${Math.round(cardWidth)}px`,
|
||||||
'--friend-grid-columns': `${columns}`
|
'--friend-grid-columns': `${columns}`,
|
||||||
|
'--friend-card-spacing': `${spacing.toFixed(2)}`
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -577,7 +606,7 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(cardScale, () => {
|
watch([cardScale, cardSpacing], () => {
|
||||||
if (!settingsReady.value) {
|
if (!settingsReady.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -620,8 +649,9 @@
|
|||||||
|
|
||||||
async function loadInitialSettings() {
|
async function loadInitialSettings() {
|
||||||
try {
|
try {
|
||||||
const [storedScale, storedShowSameInstance] = await Promise.all([
|
const [storedScale, storedSpacing, storedShowSameInstance] = await Promise.all([
|
||||||
configRepository.getString('VRCX_FriendLocationCardScale', '1'),
|
configRepository.getString('VRCX_FriendLocationCardScale', '1'),
|
||||||
|
configRepository.getString('VRCX_FriendLocationCardSpacing', '1'),
|
||||||
configRepository.getBool('VRCX_FriendLocationShowSameInstance', null)
|
configRepository.getBool('VRCX_FriendLocationShowSameInstance', null)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -630,6 +660,11 @@
|
|||||||
cardScaleBase.value = parsedScale;
|
cardScaleBase.value = parsedScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parsedSpacing = parseFloat(storedSpacing);
|
||||||
|
if (!Number.isNaN(parsedSpacing) && parsedSpacing > 0) {
|
||||||
|
cardSpacingBase.value = parsedSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
if (storedShowSameInstance !== null && storedShowSameInstance !== undefined) {
|
if (storedShowSameInstance !== null && storedShowSameInstance !== undefined) {
|
||||||
showSameInstanceBase.value = Boolean(storedShowSameInstance);
|
showSameInstanceBase.value = Boolean(storedShowSameInstance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<el-card
|
<el-card
|
||||||
class="friend-card"
|
class="friend-card"
|
||||||
shadow="never"
|
shadow="never"
|
||||||
:body-style="{ padding: `${16 * cardScale}px` }"
|
:body-style="{ padding: `${16 * cardScale * cardSpacing}px` }"
|
||||||
:style="cardStyle"
|
:style="cardStyle"
|
||||||
@click="showUserDialog(friend.id)">
|
@click="showUserDialog(friend.id)">
|
||||||
<div class="friend-card__header">
|
<div class="friend-card__header">
|
||||||
@@ -50,6 +50,10 @@
|
|||||||
displayInstanceInfo: {
|
displayInstanceInfo: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
cardSpacing: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -57,6 +61,7 @@
|
|||||||
|
|
||||||
const cardStyle = computed(() => ({
|
const cardStyle = computed(() => ({
|
||||||
'--card-scale': props.cardScale,
|
'--card-scale': props.cardScale,
|
||||||
|
'--card-spacing': props.cardSpacing,
|
||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -85,9 +90,10 @@
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.friend-card {
|
.friend-card {
|
||||||
--card-scale: 1;
|
--card-scale: 1;
|
||||||
|
--card-spacing: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: calc(14px * var(--card-scale));
|
gap: calc(14px * var(--card-scale) * var(--card-spacing));
|
||||||
border-radius: calc(8px * var(--card-scale));
|
border-radius: calc(8px * var(--card-scale));
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid var(--el-border-color);
|
border: 1px solid var(--el-border-color);
|
||||||
@@ -95,7 +101,6 @@
|
|||||||
transition:
|
transition:
|
||||||
box-shadow 0.2s ease,
|
box-shadow 0.2s ease,
|
||||||
transform 0.2s ease;
|
transform 0.2s ease;
|
||||||
width: 100%;
|
|
||||||
max-width: var(--friend-card-target-width, 220px);
|
max-width: var(--friend-card-target-width, 220px);
|
||||||
min-width: var(--friend-card-min-width, 220px);
|
min-width: var(--friend-card-min-width, 220px);
|
||||||
|
|
||||||
@@ -109,7 +114,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: calc(12px * var(--card-scale));
|
gap: calc(12px * var(--card-scale) * var(--card-spacing));
|
||||||
}
|
}
|
||||||
|
|
||||||
.friend-card__avatar-wrapper {
|
.friend-card__avatar-wrapper {
|
||||||
@@ -126,8 +131,8 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(8px * var(--card-scale));
|
top: calc(8px * var(--card-scale));
|
||||||
right: calc(8px * var(--card-scale));
|
right: calc(8px * var(--card-scale));
|
||||||
width: calc(8px * var(--card-scale));
|
inline-size: calc(8px * var(--card-scale));
|
||||||
height: calc(8px * var(--card-scale));
|
block-size: calc(8px * var(--card-scale));
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
border: calc(2px * var(--card-scale)) solid #fff;
|
border: calc(2px * var(--card-scale)) solid #fff;
|
||||||
box-shadow: 0 0 calc(4px * var(--card-scale)) rgba(15, 23, 42, 0.12);
|
box-shadow: 0 0 calc(4px * var(--card-scale)) rgba(15, 23, 42, 0.12);
|
||||||
@@ -160,7 +165,7 @@
|
|||||||
|
|
||||||
.friend-card__body {
|
.friend-card__body {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: calc(12px * var(--card-scale));
|
gap: calc(12px * var(--card-scale) * var(--card-spacing));
|
||||||
}
|
}
|
||||||
|
|
||||||
.friend-card__name {
|
.friend-card__name {
|
||||||
@@ -174,7 +179,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.friend-card__signature {
|
.friend-card__signature {
|
||||||
margin-top: 6px;
|
margin-top: calc(6px * var(--card-spacing));
|
||||||
font-size: calc(13px * var(--card-scale));
|
font-size: calc(13px * var(--card-scale));
|
||||||
color: rgba(31, 41, 55, 0.7);
|
color: rgba(31, 41, 55, 0.7);
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
@@ -187,7 +192,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: calc(40px * var(--card-scale));
|
min-height: calc(40px * var(--card-scale));
|
||||||
padding: calc(6px * var(--card-scale)) calc(10px * var(--card-scale));
|
padding: calc(6px * var(--card-scale)) calc(10px * var(--card-scale));
|
||||||
border-radius: calc(12px * var(--card-scale));
|
border-radius: calc(12px * var(--card-scale));
|
||||||
background: rgba(148, 163, 184, 0.18);
|
background: rgba(148, 163, 184, 0.18);
|
||||||
@@ -213,6 +218,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user