diff options
| author | dakkar <dakkar@thenautilus.net> | 2024-07-19 12:19:00 +0000 |
|---|---|---|
| committer | dakkar <dakkar@thenautilus.net> | 2024-07-19 12:19:00 +0000 |
| commit | 3d5fd4a12df34e7fbed2fe46d5210f37b4bf17d7 (patch) | |
| tree | 4177a8a6459c96fff7c20ee9a07b9442d8b89602 | |
| parent | merge: feat: Filter notifications by edit (!573) (diff) | |
| parent | Fix vertical align of ... (diff) | |
| download | sharkey-3d5fd4a12df34e7fbed2fe46d5210f37b4bf17d7.tar.gz sharkey-3d5fd4a12df34e7fbed2fe46d5210f37b4bf17d7.tar.bz2 sharkey-3d5fd4a12df34e7fbed2fe46d5210f37b4bf17d7.zip | |
merge: Drive searching by alt text and title (!564)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/564
Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <marie@kaifa.ch>
| -rw-r--r-- | locales/en-US.yml | 1 | ||||
| -rw-r--r-- | locales/index.d.ts | 4 | ||||
| -rw-r--r-- | locales/ja-JP.yml | 1 | ||||
| -rw-r--r-- | packages/backend/src/server/api/endpoints/drive/files.ts | 6 | ||||
| -rw-r--r-- | packages/backend/src/server/api/endpoints/drive/folders.ts | 5 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkDrive.vue | 23 |
6 files changed, 38 insertions, 2 deletions
diff --git a/locales/en-US.yml b/locales/en-US.yml index 598f742896..03a5a91e84 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -321,6 +321,7 @@ lightThemes: "Light themes" darkThemes: "Dark themes" syncDeviceDarkMode: "Sync Dark Mode with your device settings" drive: "Drive" +driveSearchbarPlaceholder: "Search drive" fileName: "Filename" selectFile: "Select a file" selectFiles: "Select files" diff --git a/locales/index.d.ts b/locales/index.d.ts index e3434d7dbf..7020bc2159 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1301,6 +1301,10 @@ export interface Locale extends ILocale { */ "drive": string; /** + * 検索ドライブ + */ + "driveSearchbarPlaceholder": string; + /** * ファイル名 */ "fileName": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index c25b421172..8f3bb4f48c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -321,6 +321,7 @@ lightThemes: "明るいテーマ" darkThemes: "暗いテーマ" syncDeviceDarkMode: "デバイスのダークモードと同期する" drive: "ドライブ" +driveSearchbarPlaceholder: "検索ドライブ" fileName: "ファイル名" selectFile: "ファイルを選択" selectFiles: "ファイルを選択" diff --git a/packages/backend/src/server/api/endpoints/drive/files.ts b/packages/backend/src/server/api/endpoints/drive/files.ts index 10c521332d..6d87d5ddf7 100644 --- a/packages/backend/src/server/api/endpoints/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/drive/files.ts @@ -9,6 +9,7 @@ import type { DriveFilesRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['drive'], @@ -37,6 +38,7 @@ export const paramDef = { folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, type: { type: 'string', nullable: true, pattern: /^[a-zA-Z\/\-*]+$/.toString().slice(1, -1) }, sort: { type: 'string', nullable: true, enum: ['+createdAt', '-createdAt', '+name', '-name', '+size', '-size', null] }, + searchQuery: { type: 'string', default: '' } }, required: [], } as const; @@ -60,6 +62,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- query.andWhere('file.folderId IS NULL'); } + if (ps.searchQuery.length > 0) { + query.andWhere('file.name ILIKE :searchQuery OR file.comment ILIKE :searchQuery', { searchQuery: `%${sqlLikeEscape(ps.searchQuery)}%` }); + } + if (ps.type) { if (ps.type.endsWith('/*')) { query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' }); diff --git a/packages/backend/src/server/api/endpoints/drive/folders.ts b/packages/backend/src/server/api/endpoints/drive/folders.ts index 8c4848f8e1..9bcd824882 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders.ts @@ -9,6 +9,7 @@ import type { DriveFoldersRepository } from '@/models/_.js'; import { QueryService } from '@/core/QueryService.js'; import { DriveFolderEntityService } from '@/core/entities/DriveFolderEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape.js'; export const meta = { tags: ['drive'], @@ -35,6 +36,7 @@ export const paramDef = { sinceId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' }, folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + searchQuery: { type: 'string', default: '' } }, required: [], } as const; @@ -58,6 +60,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- query.andWhere('folder.parentId IS NULL'); } + if (ps.searchQuery.length > 0) { + query.andWhere('folder.name ILIKE :searchQuery', { searchQuery: `%${sqlLikeEscape(ps.searchQuery)}%` }); + } const folders = await query.limit(ps.limit).getMany(); return await Promise.all(folders.map(folder => this.driveFolderEntityService.pack(folder))); diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index a9717b4fb7..222fabb8f4 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -30,7 +30,14 @@ SPDX-License-Identifier: AGPL-3.0-only <span v-if="folder != null" :class="[$style.navPathItem, $style.navSeparator]"><i class="ti ti-chevron-right"></i></span> <span v-if="folder != null" :class="[$style.navPathItem, $style.navCurrent]">{{ folder.name }}</span> </div> - <button class="_button" :class="$style.navMenu" @click="showMenu"><i class="ti ti-dots"></i></button> + <div :class="$style.navMenu"> + <!-- "Search drive via alt text or file names" --> + <MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" :placeholder="i18n.ts.driveSearchbarPlaceholder" @enter="fetch"> + <template #prefix><i class="ph-magnifying-glass ph-bold ph-lg"></i></template> + </MkInput> + + <button class="_button" :class="$style.navMenu" @click="showMenu"><i class="ti ti-dots"></i></button> + </div> </nav> <div ref="main" @@ -102,6 +109,7 @@ import type { MenuItem } from '@/types/menu.js'; import XNavFolder from '@/components/MkDrive.navFolder.vue'; import XFolder from '@/components/MkDrive.folder.vue'; import XFile from '@/components/MkDrive.file.vue'; +import MkInput from '@/components/MkInput.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { useStream } from '@/stream.js'; @@ -110,6 +118,8 @@ import { i18n } from '@/i18n.js'; import { uploadFile, uploads } from '@/scripts/upload.js'; import { claimAchievement } from '@/scripts/achievements.js'; +const searchQuery = ref(''); + const props = withDefaults(defineProps<{ initialFolder?: Misskey.entities.DriveFolder; type?: string; @@ -540,6 +550,7 @@ async function fetch() { const foldersPromise = misskeyApi('drive/folders', { folderId: folder.value ? folder.value.id : null, limit: foldersMax + 1, + searchQuery: searchQuery.value.toString().trim(), }).then(fetchedFolders => { if (fetchedFolders.length === foldersMax + 1) { moreFolders.value = true; @@ -552,6 +563,7 @@ async function fetch() { folderId: folder.value ? folder.value.id : null, type: props.type, limit: filesMax + 1, + searchQuery: searchQuery.value.toString().trim(), }).then(fetchedFiles => { if (fetchedFiles.length === filesMax + 1) { moreFiles.value = true; @@ -578,6 +590,7 @@ function fetchMoreFolders() { type: props.type, untilId: folders.value.at(-1)?.id, limit: max + 1, + searchQuery: searchQuery.value.toString().trim(), }).then(folders => { if (folders.length === max + 1) { moreFolders.value = true; @@ -601,6 +614,7 @@ function fetchMoreFiles() { type: props.type, untilId: files.value.at(-1)?.id, limit: max + 1, + searchQuery: searchQuery.value.toString().trim(), }).then(files => { if (files.length === max + 1) { moreFiles.value = true; @@ -747,8 +761,13 @@ onBeforeUnmount(() => { } .navMenu { + display: flex; margin-left: auto; - padding: 0 12px; + align-items: center; +} + +.navMenu > *:not(:last-child) { + padding-right: 12px; } .main { |