feat: custom table page size setting

This commit is contained in:
pa
2025-12-18 00:28:02 +09:00
committed by Natsumi
parent a3b71007d7
commit 277275f5ef
15 changed files with 132 additions and 86 deletions

View File

@@ -17,7 +17,7 @@
<el-pagination <el-pagination
size="small" size="small"
:current-page="internalCurrentPage" :current-page="internalCurrentPage"
:page-size="internalPageSize" :page-size="effectivePageSize"
:total="filteredData.length" :total="filteredData.length"
v-bind="mergedPaginationProps" v-bind="mergedPaginationProps"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@@ -104,10 +104,14 @@
const mergedPaginationProps = computed(() => ({ const mergedPaginationProps = computed(() => ({
layout: 'sizes, prev, pager, next, total', layout: 'sizes, prev, pager, next, total',
pageSizes: [10, 15, 20, 25, 50, 100], ...paginationProps.value,
...paginationProps.value pageSizes: paginationProps.value?.pageSizes ?? appearanceSettingsStore.tablePageSizes
})); }));
const effectivePageSize = computed(() => {
return props.pageSizeLinked ? appearanceSettingsStore.tablePageSize : internalPageSize.value;
});
const applyFilter = function (row, filter) { const applyFilter = function (row, filter) {
if (Array.isArray(filter.prop)) { if (Array.isArray(filter.prop)) {
return filter.prop.some((propItem) => applyFilter(row, { prop: propItem, value: filter.value })); return filter.prop.some((propItem) => applyFilter(row, { prop: propItem, value: filter.value }));
@@ -175,8 +179,8 @@
return filteredData.value; return filteredData.value;
} }
const start = (internalCurrentPage.value - 1) * internalPageSize.value; const start = (internalCurrentPage.value - 1) * effectivePageSize.value;
const end = start + internalPageSize.value; const end = start + effectivePageSize.value;
return filteredData.value.slice(start, end); return filteredData.value.slice(start, end);
}); });
@@ -202,6 +206,7 @@
const handleSizeChange = (size) => { const handleSizeChange = (size) => {
if (props.pageSizeLinked) { if (props.pageSizeLinked) {
appearanceSettingsStore.setTablePageSize(size); appearanceSettingsStore.setTablePageSize(size);
return;
} }
internalPageSize.value = size; internalPageSize.value = size;
}; };
@@ -234,6 +239,7 @@
return { return {
internalCurrentPage, internalCurrentPage,
internalPageSize, internalPageSize,
effectivePageSize,
showPagination, showPagination,
mergedTableProps, mergedTableProps,
mergedPaginationProps, mergedPaginationProps,

View File

@@ -31,8 +31,8 @@
:disabled=" :disabled="
Boolean( Boolean(
isGroupMembersLoading || isGroupMembersLoading ||
memberSearch.length || memberSearch.length ||
!hasGroupPermission(groupMemberModeration.groupRef, 'group-bans-manage') !hasGroupPermission(groupMemberModeration.groupRef, 'group-bans-manage')
) )
"> ">
<el-button size="small" @click.stop> <el-button size="small" @click.stop>
@@ -60,8 +60,8 @@
:disabled=" :disabled="
Boolean( Boolean(
isGroupMembersLoading || isGroupMembersLoading ||
memberSearch.length || memberSearch.length ||
!hasGroupPermission(groupMemberModeration.groupRef, 'group-bans-manage') !hasGroupPermission(groupMemberModeration.groupRef, 'group-bans-manage')
) )
"> ">
<el-button size="small" @click.stop> <el-button size="small" @click.stop>
@@ -398,10 +398,7 @@
:disabled=" :disabled="
Boolean( Boolean(
progressCurrent || progressCurrent ||
!hasGroupPermission( !hasGroupPermission(groupMemberModeration.groupRef, 'group-invites-manage')
groupMemberModeration.groupRef,
'group-invites-manage'
)
) )
" "
@click="groupMembersDeleteSentInvite" @click="groupMembersDeleteSentInvite"
@@ -483,10 +480,7 @@
:disabled=" :disabled="
Boolean( Boolean(
progressCurrent || progressCurrent ||
!hasGroupPermission( !hasGroupPermission(groupMemberModeration.groupRef, 'group-invites-manage')
groupMemberModeration.groupRef,
'group-invites-manage'
)
) )
" "
@click="groupMembersAcceptInviteRequest" @click="groupMembersAcceptInviteRequest"
@@ -496,10 +490,7 @@
:disabled=" :disabled="
Boolean( Boolean(
progressCurrent || progressCurrent ||
!hasGroupPermission( !hasGroupPermission(groupMemberModeration.groupRef, 'group-invites-manage')
groupMemberModeration.groupRef,
'group-invites-manage'
)
) )
" "
@click="groupMembersRejectInviteRequest" @click="groupMembersRejectInviteRequest"
@@ -509,10 +500,7 @@
:disabled=" :disabled="
Boolean( Boolean(
progressCurrent || progressCurrent ||
!hasGroupPermission( !hasGroupPermission(groupMemberModeration.groupRef, 'group-invites-manage')
groupMemberModeration.groupRef,
'group-invites-manage'
)
) )
" "
@click="groupMembersBlockJoinRequest" @click="groupMembersBlockJoinRequest"
@@ -594,10 +582,7 @@
:disabled=" :disabled="
Boolean( Boolean(
progressCurrent || progressCurrent ||
!hasGroupPermission( !hasGroupPermission(groupMemberModeration.groupRef, 'group-invites-manage')
groupMemberModeration.groupRef,
'group-invites-manage'
)
) )
" "
@click="groupMembersDeleteBlockedRequest" @click="groupMembersDeleteBlockedRequest"
@@ -800,8 +785,8 @@
:disabled=" :disabled="
Boolean( Boolean(
!selectedRoles.length || !selectedRoles.length ||
progressCurrent || progressCurrent ||
!hasGroupPermission(groupMemberModeration.groupRef, 'group-roles-assign') !hasGroupPermission(groupMemberModeration.groupRef, 'group-roles-assign')
) )
" "
@click="groupMembersAddRoles" @click="groupMembersAddRoles"
@@ -811,8 +796,8 @@
:disabled=" :disabled="
Boolean( Boolean(
!selectedRoles.length || !selectedRoles.length ||
progressCurrent || progressCurrent ||
!hasGroupPermission(groupMemberModeration.groupRef, 'group-roles-assign') !hasGroupPermission(groupMemberModeration.groupRef, 'group-roles-assign')
) )
" "
@click="groupMembersRemoveRoles" @click="groupMembersRemoveRoles"
@@ -947,8 +932,7 @@
tableProps: { stripe: true, size: 'small' }, tableProps: { stripe: true, size: 'small' },
pageSize: 15, pageSize: 15,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });
const groupJoinRequestsModerationTable = reactive({ const groupJoinRequestsModerationTable = reactive({
@@ -956,8 +940,7 @@
tableProps: { stripe: true, size: 'small' }, tableProps: { stripe: true, size: 'small' },
pageSize: 15, pageSize: 15,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });
const groupBlockedModerationTable = reactive({ const groupBlockedModerationTable = reactive({
@@ -966,8 +949,7 @@
pageSize: 15, pageSize: 15,
paginationProps: { paginationProps: {
small: true, small: true,
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });
const groupLogsModerationTable = reactive({ const groupLogsModerationTable = reactive({
@@ -976,8 +958,7 @@
tableProps: { stripe: true, size: 'small' }, tableProps: { stripe: true, size: 'small' },
pageSize: 15, pageSize: 15,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });
const groupBansModerationTable = reactive({ const groupBansModerationTable = reactive({
@@ -986,8 +967,7 @@
tableProps: { stripe: true, size: 'small' }, tableProps: { stripe: true, size: 'small' },
pageSize: 15, pageSize: 15,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });
const groupMemberModerationTable = reactive({ const groupMemberModerationTable = reactive({
@@ -995,8 +975,7 @@
tableProps: { stripe: true, size: 'small' }, tableProps: { stripe: true, size: 'small' },
pageSize: 15, pageSize: 15,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });

View File

@@ -94,7 +94,7 @@
defaultSort: { prop: 'created_at', order: 'descending' } defaultSort: { prop: 'created_at', order: 'descending' }
}, },
pageSize: 10, pageSize: 10,
paginationProps: { layout: 'sizes,prev,pager,next,total', pageSizes: [10, 25, 50, 100] } paginationProps: { layout: 'sizes,prev,pager,next,total' }
}); });
const props = defineProps({ const props = defineProps({

View File

@@ -118,8 +118,7 @@
}, },
pageSize: 10, pageSize: 10,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 25, 50, 100]
} }
}); });
const fullscreen = ref(false); const fullscreen = ref(false);

View File

@@ -110,8 +110,7 @@
}, },
pageSize: 10, pageSize: 10,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 25, 50, 100]
} }
}); });
const loading = ref(false); const loading = ref(false);

View File

@@ -119,8 +119,7 @@
}, },
pageSize: 10, pageSize: 10,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 25, 50, 100]
} }
}); });

View File

@@ -557,6 +557,8 @@
"sort_instance_users_by_time": "time", "sort_instance_users_by_time": "time",
"sort_instance_users_by_alphabet": "alphabetical", "sort_instance_users_by_alphabet": "alphabetical",
"table_max_size": "Table Max Size", "table_max_size": "Table Max Size",
"table_page_sizes": "Table Page Sizes",
"table_page_sizes_error": "Page size must be a number between 1 and 1000",
"show_notification_icon_dot": "Show Tray Notification Dot" "show_notification_icon_dot": "Show Tray Notification Dot"
}, },
"timedate": { "timedate": {

View File

@@ -36,8 +36,7 @@ export const useFeedStore = defineStore('Feed', () => {
pageSize: 20, pageSize: 20,
pageSizeLinked: true, pageSizeLinked: true,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });

View File

@@ -98,8 +98,7 @@ export const useFriendStore = defineStore('Friend', () => {
pageSize: 20, pageSize: 20,
pageSizeLinked: true, pageSizeLinked: true,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });

View File

@@ -75,8 +75,7 @@ export const useGameLogStore = defineStore('GameLog', () => {
pageSize: 20, pageSize: 20,
pageSizeLinked: true, pageSizeLinked: true,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
}, },
vip: false vip: false
}); });

View File

@@ -37,8 +37,7 @@ export const useModerationStore = defineStore('Moderation', () => {
pageSize: 20, pageSize: 20,
pageSizeLinked: true, pageSizeLinked: true,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });

View File

@@ -77,8 +77,7 @@ export const useNotificationStore = defineStore('Notification', () => {
pageSize: 20, pageSize: 20,
pageSizeLinked: true, pageSizeLinked: true,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [10, 15, 20, 25, 50, 100]
} }
}); });
const unseenNotifications = ref([]); const unseenNotifications = ref([]);

View File

@@ -107,8 +107,7 @@ export const usePhotonStore = defineStore('Photon', () => {
}, },
pageSize: 10, pageSize: 10,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [5, 10, 15, 25, 50]
} }
}); });
const photonEventTablePrevious = ref({ const photonEventTablePrevious = ref({
@@ -129,8 +128,7 @@ export const usePhotonStore = defineStore('Photon', () => {
}, },
pageSize: 10, pageSize: 10,
paginationProps: { paginationProps: {
layout: 'sizes,prev,pager,next,total', layout: 'sizes,prev,pager,next,total'
pageSizes: [5, 10, 15, 25, 50]
} }
}); });
const chatboxUserBlacklist = ref(new Map()); const chatboxUserBlacklist = ref(new Map());

View File

@@ -15,10 +15,7 @@ import {
import { database } from '../../service/database'; import { database } from '../../service/database';
import { getNameColour } from '../../shared/utils'; import { getNameColour } from '../../shared/utils';
import { useFeedStore } from '../feed'; import { useFeedStore } from '../feed';
import { useFriendStore } from '../friend';
import { useGameLogStore } from '../gameLog'; import { useGameLogStore } from '../gameLog';
import { useModerationStore } from '../moderation';
import { useNotificationStore } from '../notification';
import { useUiStore } from '../ui'; import { useUiStore } from '../ui';
import { useUserStore } from '../user'; import { useUserStore } from '../user';
import { useVrStore } from '../vr'; import { useVrStore } from '../vr';
@@ -31,11 +28,8 @@ export const useAppearanceSettingsStore = defineStore(
'AppearanceSettings', 'AppearanceSettings',
() => { () => {
const friendStore = useFriendStore();
const vrStore = useVrStore(); const vrStore = useVrStore();
const notificationStore = useNotificationStore();
const feedStore = useFeedStore(); const feedStore = useFeedStore();
const moderationStore = useModerationStore();
const gameLogStore = useGameLogStore(); const gameLogStore = useGameLogStore();
const vrcxStore = useVrcxStore(); const vrcxStore = useVrcxStore();
const userStore = useUserStore(); const userStore = useUserStore();
@@ -44,6 +38,9 @@ export const useAppearanceSettingsStore = defineStore(
const { t, availableLocales, locale } = useI18n(); const { t, availableLocales, locale } = useI18n();
const MAX_TABLE_PAGE_SIZE = 1000;
const DEFAULT_TABLE_PAGE_SIZES = [10, 15, 20, 25, 50, 100];
const appLanguage = ref('en'); const appLanguage = ref('en');
const themeMode = ref(''); const themeMode = ref('');
const isDarkMode = ref(false); const isDarkMode = ref(false);
@@ -53,6 +50,7 @@ export const useAppearanceSettingsStore = defineStore(
const sortFavorites = ref(true); const sortFavorites = ref(true);
const instanceUsersSortAlphabetical = ref(false); const instanceUsersSortAlphabetical = ref(false);
const tablePageSize = ref(15); const tablePageSize = ref(15);
const tablePageSizes = ref([...DEFAULT_TABLE_PAGE_SIZES]);
const dtHour12 = ref(false); const dtHour12 = ref(false);
const dtIsoFormat = ref(false); const dtIsoFormat = ref(false);
const sidebarSortMethod1 = ref('Sort Private to Bottom'); const sidebarSortMethod1 = ref('Sort Private to Bottom');
@@ -91,6 +89,11 @@ export const useAppearanceSettingsStore = defineStore(
); );
}); });
const clampInt = (value, min, max) => {
const n = parseInt(value, 10);
return Math.min(max, Math.max(min, n));
};
async function initAppearanceSettings() { async function initAppearanceSettings() {
const [ const [
appLanguageConfig, appLanguageConfig,
@@ -101,6 +104,7 @@ export const useAppearanceSettingsStore = defineStore(
sortFavoritesConfig, sortFavoritesConfig,
instanceUsersSortAlphabeticalConfig, instanceUsersSortAlphabeticalConfig,
tablePageSizeConfig, tablePageSizeConfig,
tablePageSizesConfig,
dtHour12Config, dtHour12Config,
dtIsoFormatConfig, dtIsoFormatConfig,
sidebarSortMethodsConfig, sidebarSortMethodsConfig,
@@ -129,6 +133,10 @@ export const useAppearanceSettingsStore = defineStore(
false false
), ),
configRepository.getInt('VRCX_tablePageSize', 20), configRepository.getInt('VRCX_tablePageSize', 20),
configRepository.getString(
'VRCX_tablePageSizes',
JSON.stringify(DEFAULT_TABLE_PAGE_SIZES)
),
configRepository.getBool('VRCX_dtHour12', false), configRepository.getBool('VRCX_dtHour12', false),
configRepository.getBool('VRCX_dtIsoFormat', false), configRepository.getBool('VRCX_dtIsoFormat', false),
configRepository.getString( configRepository.getString(
@@ -193,6 +201,10 @@ export const useAppearanceSettingsStore = defineStore(
instanceUsersSortAlphabetical.value = instanceUsersSortAlphabetical.value =
instanceUsersSortAlphabeticalConfig; instanceUsersSortAlphabeticalConfig;
tablePageSizes.value = normalizeTablePageSizes(
JSON.parse(tablePageSizesConfig)
);
setTablePageSize(tablePageSizeConfig); setTablePageSize(tablePageSizeConfig);
dtHour12.value = dtHour12Config; dtHour12.value = dtHour12Config;
@@ -462,18 +474,42 @@ export const useAppearanceSettingsStore = defineStore(
instanceUsersSortAlphabetical.value instanceUsersSortAlphabetical.value
); );
} }
/**
* @param {number} size
*/
function setTablePageSize(size) {
feedStore.feedTable.pageSize = size;
gameLogStore.gameLogTable.pageSize = size;
friendStore.friendLogTable.pageSize = size;
moderationStore.playerModerationTable.pageSize = size;
notificationStore.notificationTable.pageSize = size;
tablePageSize.value = size; function setTablePageSize(size) {
configRepository.setInt('VRCX_tablePageSize', size); const processedSize = clampInt(size, 1, MAX_TABLE_PAGE_SIZE);
tablePageSize.value = processedSize;
configRepository.setInt('VRCX_tablePageSize', processedSize);
return processedSize;
}
function normalizeTablePageSizes(input) {
const values = (
Array.isArray(input) ? input : DEFAULT_TABLE_PAGE_SIZES
)
.map((v) => parseInt(v, 10))
.filter((v) => v > 0 && v <= MAX_TABLE_PAGE_SIZE);
const uniqueSorted = Array.from(new Set(values)).sort(
(a, b) => a - b
);
return uniqueSorted.length
? uniqueSorted
: [...DEFAULT_TABLE_PAGE_SIZES];
}
/**
* @param {Array<number|string>} sizes
*/
function setTablePageSizes(sizes) {
tablePageSizes.value = normalizeTablePageSizes(sizes);
configRepository.setString(
'VRCX_tablePageSizes',
JSON.stringify(tablePageSizes.value)
);
if (!tablePageSizes.value.includes(tablePageSize.value)) {
setTablePageSize(tablePageSizes.value[0]);
}
} }
function setDtHour12() { function setDtHour12() {
dtHour12.value = !dtHour12.value; dtHour12.value = !dtHour12.value;
@@ -708,6 +744,7 @@ export const useAppearanceSettingsStore = defineStore(
sortFavorites, sortFavorites,
instanceUsersSortAlphabetical, instanceUsersSortAlphabetical,
tablePageSize, tablePageSize,
tablePageSizes,
dtHour12, dtHour12,
dtIsoFormat, dtIsoFormat,
sidebarSortMethod1, sidebarSortMethod1,
@@ -734,6 +771,7 @@ export const useAppearanceSettingsStore = defineStore(
setSortFavorites, setSortFavorites,
setInstanceUsersSortAlphabetical, setInstanceUsersSortAlphabetical,
setTablePageSize, setTablePageSize,
setTablePageSizes,
setDtHour12, setDtHour12,
setDtIsoFormat, setDtIsoFormat,
setSidebarSortMethod1, setSidebarSortMethod1,

View File

@@ -101,12 +101,26 @@
}}</el-radio> }}</el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
<div class="options-container-item">
<span class="name">{{ t('view.settings.appearance.appearance.table_page_sizes') }}</span>
<el-select
v-model="tablePageSizesModel"
multiple
filterable
allow-create
default-first-option
collapse-tags
:max-collapse-tags="3"
style="width: 300px">
<el-option v-for="size in tablePageSizes" :key="size" :label="String(size)" :value="String(size)" />
</el-select>
</div>
<div class="options-container-item"> <div class="options-container-item">
<el-button size="small" :icon="Notebook" style="margin-right: 10px" @click="promptMaxTableSizeDialog">{{ <el-button size="small" :icon="Notebook" style="margin-right: 10px" @click="promptMaxTableSizeDialog">{{
t('view.settings.appearance.appearance.table_max_size') t('view.settings.appearance.appearance.table_max_size')
}}</el-button> }}</el-button>
</div> </div>
<div class="options-container-item" />
</div> </div>
<div class="options-container"> <div class="options-container">
<span class="header">{{ t('view.settings.appearance.timedate.header') }}</span> <span class="header">{{ t('view.settings.appearance.timedate.header') }}</span>
@@ -365,6 +379,7 @@
<script setup> <script setup>
import { ArrowDown, ArrowRight, Notebook } from '@element-plus/icons-vue'; import { ArrowDown, ArrowRight, Notebook } from '@element-plus/icons-vue';
import { computed, onBeforeUnmount, ref } from 'vue'; import { computed, onBeforeUnmount, ref } from 'vue';
import { ElMessage } from 'element-plus';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@@ -399,7 +414,8 @@
hideUnfriends, hideUnfriends,
randomUserColours, randomUserColours,
trustColor, trustColor,
notificationIconDot notificationIconDot,
tablePageSizes
} = storeToRefs(appearanceSettingsStore); } = storeToRefs(appearanceSettingsStore);
const { saveSortFavoritesOption } = useFavoriteStore(); const { saveSortFavoritesOption } = useFavoriteStore();
@@ -424,7 +440,8 @@
saveThemeMode, saveThemeMode,
changeAppLanguage, changeAppLanguage,
promptMaxTableSizeDialog, promptMaxTableSizeDialog,
setNotificationIconDot setNotificationIconDot,
setTablePageSizes
} = appearanceSettingsStore; } = appearanceSettingsStore;
const zoomLevel = ref(100); const zoomLevel = ref(100);
@@ -439,6 +456,20 @@
initGetZoomLevel(); initGetZoomLevel();
const tablePageSizesModel = computed({
get: () => tablePageSizes.value.map(String),
set: (values) => {
const rawLength = Array.isArray(values) ? values.length : 0;
setTablePageSizes(values);
if (rawLength && rawLength !== tablePageSizes.value.length) {
ElMessage({
message: t('view.settings.appearance.appearance.table_page_sizes_error'),
type: 'error'
});
}
}
});
async function initGetZoomLevel() { async function initGetZoomLevel() {
const handleWheel = (event) => { const handleWheel = (event) => {
if (event.ctrlKey) { if (event.ctrlKey) {