improved search ui and efficiency:
- 15% less ram - colored icons - context bar - more search type filters
This commit is contained in:
parent
5806060775
commit
5fc0839f1e
Binary file not shown.
|
@ -8,23 +8,18 @@ import (
|
||||||
var searchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var searchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
response := []map[string]interface{}{}
|
response := []map[string]interface{}{}
|
||||||
query := r.URL.Query().Get("query")
|
query := r.URL.Query().Get("query")
|
||||||
files, dirs, fileTypes := search.SearchAllIndexes(query, r.URL.Path)
|
indexInfo, fileTypes := search.SearchAllIndexes(query, r.URL.Path)
|
||||||
for _,path := range(files){
|
for _,path := range(indexInfo){
|
||||||
f := fileTypes[path]
|
f := fileTypes[path]
|
||||||
responseObj := map[string]interface{}{
|
responseObj := map[string]interface{}{
|
||||||
"dir" : false,
|
|
||||||
"path" : path,
|
"path" : path,
|
||||||
}
|
}
|
||||||
for _,filterType := range(search.FilterableTypes) {
|
for filterType,_ := range(f) {
|
||||||
if f[filterType] { responseObj[filterType] = f[filterType] }
|
if f[filterType] {
|
||||||
|
responseObj[filterType] = f[filterType]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
response = append(response,responseObj)
|
response = append(response,responseObj)
|
||||||
}
|
}
|
||||||
for _,v := range(dirs){
|
|
||||||
response = append(response, map[string]interface{}{
|
|
||||||
"dir": true,
|
|
||||||
"path": v,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return renderJSON(w, r, response)
|
return renderJSON(w, r, response)
|
||||||
})
|
})
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-babel": "^6.0.3",
|
||||||
|
"@rollup/plugin-replace": "^5.0.2",
|
||||||
|
"rollup": "^2.79.1",
|
||||||
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
|
"rollup-plugin-livereload": "^2.0.5",
|
||||||
|
"rollup-plugin-node-resolve": "^5.2.0",
|
||||||
|
"rollup-plugin-postcss": "^4.0.2",
|
||||||
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
|
"rollup-plugin-vue": "^6.0.0",
|
||||||
|
"vue-template-compiler": "^2.7.14"
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,6 +58,10 @@ func ParseSearch(value string) *searchOptions {
|
||||||
opts.Conditions["doc"] = true
|
opts.Conditions["doc"] = true
|
||||||
case "archive":
|
case "archive":
|
||||||
opts.Conditions["archive"] = true
|
opts.Conditions["archive"] = true
|
||||||
|
case "folder":
|
||||||
|
opts.Conditions["dir"] = true
|
||||||
|
case "file":
|
||||||
|
opts.Conditions["dir"] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
var (
|
var (
|
||||||
rootPath string = "/srv"
|
rootPath string = "/srv"
|
||||||
indexes = map[string][]string{}
|
indexes = map[string][]string{}
|
||||||
FilterableTypes = []string{"audio","image","video","doc","archive"}
|
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
lastIndexed time.Time
|
lastIndexed time.Time
|
||||||
)
|
)
|
||||||
|
@ -108,13 +107,12 @@ func addToIndex(path string, fileName string, isDir bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SearchAllIndexes(search string, scope string) ([]string, []string, map[string]map[string]bool) {
|
func SearchAllIndexes(search string, scope string) ([]string, map[string]map[string]bool) {
|
||||||
searchOptions := ParseSearch(search)
|
searchOptions := ParseSearch(search)
|
||||||
mutex.RLock()
|
mutex.RLock()
|
||||||
defer mutex.RUnlock()
|
defer mutex.RUnlock()
|
||||||
fileListTypes := make(map[string]map[string]bool)
|
fileListTypes := make(map[string]map[string]bool)
|
||||||
var matchingFiles []string
|
var matching []string
|
||||||
var matchingDirs []string
|
|
||||||
maximum := 125
|
maximum := 125
|
||||||
|
|
||||||
for _, searchTerm := range searchOptions.Terms {
|
for _, searchTerm := range searchOptions.Terms {
|
||||||
|
@ -131,12 +129,13 @@ func SearchAllIndexes(search string, scope string) ([]string, []string, map[stri
|
||||||
if pathName == "" {
|
if pathName == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
matches, _ := containsSearchTerm(pathName, searchTerm, searchOptions.Conditions)
|
matches, fileType := containsSearchTerm(pathName, searchTerm, searchOptions.Conditions, true)
|
||||||
if !matches {
|
if !matches {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
matchingDirs = append(matchingDirs, pathName)
|
matching = append(matching, pathName+"/")
|
||||||
|
fileListTypes[pathName+"/"] = fileType
|
||||||
}
|
}
|
||||||
count = 0
|
count = 0
|
||||||
for _, fileName := range indexes["files"] {
|
for _, fileName := range indexes["files"] {
|
||||||
|
@ -148,28 +147,22 @@ func SearchAllIndexes(search string, scope string) ([]string, []string, map[stri
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Check if the path name contains the search term
|
// Check if the path name contains the search term
|
||||||
matches, fileType := containsSearchTerm(pathName, searchTerm, searchOptions.Conditions)
|
matches, fileType := containsSearchTerm(pathName, searchTerm, searchOptions.Conditions, false)
|
||||||
if !matches {
|
if !matches {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
matchingFiles = append(matchingFiles, pathName)
|
matching = append(matching, pathName)
|
||||||
fileListTypes[pathName] = fileType
|
fileListTypes[pathName] = fileType
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sort the strings based on the number of elements after splitting by "/"
|
// Sort the strings based on the number of elements after splitting by "/"
|
||||||
sort.Slice(matchingFiles, func(i, j int) bool {
|
sort.Slice(matching, func(i, j int) bool {
|
||||||
parts1 := strings.Split(matchingFiles[i], "/")
|
parts1 := strings.Split(matching[i], "/")
|
||||||
parts2 := strings.Split(matchingFiles[j], "/")
|
parts2 := strings.Split(matching[j], "/")
|
||||||
return len(parts1) < len(parts2)
|
return len(parts1) < len(parts2)
|
||||||
})
|
})
|
||||||
// Sort the strings based on the number of elements after splitting by "/"
|
return matching, fileListTypes
|
||||||
sort.Slice(matchingDirs, func(i, j int) bool {
|
|
||||||
parts1 := strings.Split(matchingDirs[i], "/")
|
|
||||||
parts2 := strings.Split(matchingDirs[j], "/")
|
|
||||||
return len(parts1) < len(parts2)
|
|
||||||
})
|
|
||||||
return matchingFiles, matchingDirs, fileListTypes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func scopedPathNameFilter(pathName string, scope string) string {
|
func scopedPathNameFilter(pathName string, scope string) string {
|
||||||
|
@ -182,24 +175,25 @@ func scopedPathNameFilter(pathName string, scope string) string {
|
||||||
return pathName
|
return pathName
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsSearchTerm(pathName string, searchTerm string, conditions map[string]bool) (bool, map[string]bool) {
|
func containsSearchTerm(pathName string, searchTerm string, conditions map[string]bool, isDir bool) (bool, map[string]bool) {
|
||||||
path := getLastPathComponent(pathName)
|
path := getLastPathComponent(pathName)
|
||||||
fileTypes := map[string]bool{}
|
fileTypes := map[string]bool{}
|
||||||
matchesCondition := false
|
matchesCondition := false
|
||||||
extension := filepath.Ext(strings.ToLower(path))
|
extension := filepath.Ext(strings.ToLower(path))
|
||||||
mimetype := mime.TypeByExtension(extension)
|
mimetype := mime.TypeByExtension(extension)
|
||||||
filterTypes := FilterableTypes
|
|
||||||
fileTypes["audio"] = strings.HasPrefix(mimetype, "audio")
|
fileTypes["audio"] = strings.HasPrefix(mimetype, "audio")
|
||||||
fileTypes["image"] = strings.HasPrefix(mimetype, "image")
|
fileTypes["image"] = strings.HasPrefix(mimetype, "image")
|
||||||
fileTypes["video"] = strings.HasPrefix(mimetype, "video")
|
fileTypes["video"] = strings.HasPrefix(mimetype, "video")
|
||||||
fileTypes["doc"] = isDoc(extension)
|
fileTypes["doc"] = isDoc(extension)
|
||||||
fileTypes["archive"] = isArchive(extension)
|
fileTypes["archive"] = isArchive(extension)
|
||||||
|
fileTypes["dir"] = isDir
|
||||||
anyFilter := false
|
anyFilter := false
|
||||||
for _,t := range(filterTypes){
|
for t,v := range conditions {
|
||||||
if conditions[t] {
|
if t == "exact" {
|
||||||
anyFilter = true
|
continue
|
||||||
matchesCondition = fileTypes[t]
|
|
||||||
}
|
}
|
||||||
|
matchesCondition = v == fileTypes[t]
|
||||||
|
anyFilter = true
|
||||||
}
|
}
|
||||||
if !anyFilter {
|
if !anyFilter {
|
||||||
matchesCondition = true
|
matchesCondition = true
|
||||||
|
|
|
@ -2,7 +2,7 @@ package version
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Version is the current File Browser version.
|
// Version is the current File Browser version.
|
||||||
Version = "(0.1.0)"
|
Version = "(0.1.2)"
|
||||||
// CommitSHA is the commmit sha.
|
// CommitSHA is the commmit sha.
|
||||||
CommitSHA = "(unknown)"
|
CommitSHA = "(unknown)"
|
||||||
)
|
)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,20 +9,19 @@
|
||||||
"watch": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitignore' -exec rm -r {} + && vue-cli-service build --watch --no-clean"
|
"watch": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitignore' -exec rm -r {} + && vue-cli-service build --watch --no-clean"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"normalize.css": "^8.0.1",
|
||||||
|
"file-loader": "^6.2.0",
|
||||||
"ace-builds": "^1.4.7",
|
"ace-builds": "^1.4.7",
|
||||||
"clipboard": "^2.0.4",
|
"clipboard": "^2.0.4",
|
||||||
"core-js": "^3.9.1",
|
|
||||||
"css-vars-ponyfill": "^2.4.3",
|
"css-vars-ponyfill": "^2.4.3",
|
||||||
"js-base64": "^2.5.1",
|
"js-base64": "^2.5.1",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"material-icons": "^1.10.5",
|
"material-icons": "^1.10.5",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"normalize.css": "^8.0.1",
|
|
||||||
"noty": "^3.2.0-beta",
|
"noty": "^3.2.0-beta",
|
||||||
"pretty-bytes": "^6.0.0",
|
"pretty-bytes": "^6.0.0",
|
||||||
"qrcode.vue": "^1.7.0",
|
"qrcode.vue": "^1.7.0",
|
||||||
"semver": "^7.5.3",
|
|
||||||
"utif": "^3.1.0",
|
"utif": "^3.1.0",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
"vue-async-computed": "^3.9.0",
|
"vue-async-computed": "^3.9.0",
|
||||||
|
@ -35,11 +34,8 @@
|
||||||
"whatwg-fetch": "^3.6.2"
|
"whatwg-fetch": "^3.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^5.0.8",
|
|
||||||
"@vue/cli-service": "^5.0.8",
|
"@vue/cli-service": "^5.0.8",
|
||||||
"compression-webpack-plugin": "^10.0.0",
|
"compression-webpack-plugin": "^10.0.0",
|
||||||
"file-loader": "^6.2.0",
|
|
||||||
"prettier": "^2.2.1",
|
|
||||||
"vue-template-compiler": "^2.6.10"
|
"vue-template-compiler": "^2.6.10"
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import vue from 'rollup-plugin-vue'
|
||||||
|
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||||
|
import commonjs from '@rollup/plugin-commonjs'
|
||||||
|
import { terser } from "rollup-plugin-terser"
|
||||||
|
import postcss from 'rollup-plugin-postcss'
|
||||||
|
import babel from '@rollup/plugin-babel'
|
||||||
|
import replace from '@rollup/plugin-replace'
|
||||||
|
import livereload from 'rollup-plugin-livereload'
|
||||||
|
import css from 'rollup-plugin-css-only'
|
||||||
|
import autoprefixer from 'autoprefixer'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: 'src/main.js', // Entry file
|
||||||
|
output: {
|
||||||
|
file: 'dist/build.js', // Output file
|
||||||
|
format: 'iife', // Immediately Invoked Function Expression format suitable for <script> tag
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
replace({
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||||
|
'process.env.VUE_ENV': '"client"'
|
||||||
|
}),
|
||||||
|
nodeResolve({ browser: true, jsnext: true }), // Resolve modules from node_modules
|
||||||
|
commonjs(), // Convert CommonJS modules to ES6
|
||||||
|
vue({ css: false }), // Handle .vue files
|
||||||
|
css({ output: 'bundle.css' }), // css to separate file
|
||||||
|
postcss({ plugins: [autoprefixer()]}),
|
||||||
|
babel({ babelHelpers: 'bundled' }), // Transpile to ES5
|
||||||
|
terser(), // Minify the build
|
||||||
|
livereload('dist') // Live reload for development
|
||||||
|
],
|
||||||
|
}
|
|
@ -1,72 +1,50 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="search" @click="open" v-bind:class="{ active, ongoing }">
|
<div id="search" @click="open" v-bind:class="{ active, ongoing }">
|
||||||
<div id="input">
|
<div id="input">
|
||||||
<button
|
<button v-if="active" class="action" @click="close" :aria-label="$t('buttons.close')" :title="$t('buttons.close')">
|
||||||
v-if="active"
|
|
||||||
class="action"
|
|
||||||
@click="close"
|
|
||||||
:aria-label="$t('buttons.close')"
|
|
||||||
:title="$t('buttons.close')"
|
|
||||||
>
|
|
||||||
<i class="material-icons">arrow_back</i>
|
<i class="material-icons">arrow_back</i>
|
||||||
</button>
|
</button>
|
||||||
<i v-else class="material-icons">search</i>
|
<i v-else class="material-icons">search</i>
|
||||||
<input
|
<input type="text" @keyup.exact="keyup" @input="submit" ref="input" :autofocus="active" v-model.trim="value"
|
||||||
type="text"
|
:aria-label="$t('search.search')" :placeholder="$t('search.search')" />
|
||||||
@keyup.exact="keyup"
|
|
||||||
@input="submit"
|
|
||||||
ref="input"
|
|
||||||
:autofocus="active"
|
|
||||||
v-model.trim="value"
|
|
||||||
:aria-label="$t('search.search')"
|
|
||||||
:placeholder="$t('search.search')"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="result" ref="result">
|
<div id="result" ref="result">
|
||||||
<div id="result-list">
|
<div id="result-list">
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
<div class="button" style="width:100%">Search Context: {{ getContext(this.$route.path) }}</div>
|
||||||
<template v-if="isEmpty">
|
<template v-if="isEmpty">
|
||||||
<p>{{ text }}</p>
|
<p>{{ text }}</p>
|
||||||
|
|
||||||
<template v-if="value.length === 0">
|
<template v-if="value.length === 0">
|
||||||
<div class="boxes">
|
<div class="boxes">
|
||||||
<h3>{{ $t("search.types") }}</h3>
|
<h3>{{ $t("search.types") }}</h3>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div tabindex="0" v-for="(v, k) in boxes" :key="k" role="button" @click="init('type:' + k)"
|
||||||
tabindex="0"
|
:aria-label="(v.label)">
|
||||||
v-for="(v, k) in boxes"
|
|
||||||
:key="k"
|
|
||||||
role="button"
|
|
||||||
@click="init('type:' + k)"
|
|
||||||
:aria-label="$t('search.' + v.label)"
|
|
||||||
>
|
|
||||||
<i class="material-icons">{{ v.icon }}</i>
|
<i class="material-icons">{{ v.icon }}</i>
|
||||||
<p>{{ $t("search." + v.label) }}</p>
|
<p>{{ v.label }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<ul v-show="filteredResults.length > 0">
|
<ul v-show="results.length > 0">
|
||||||
<div>Searching Scope : {{ path }}</div>
|
<li v-for="(s, k) in results" :key="k" @click.stop.prevent="navigateTo(s.url)" style="cursor: pointer">
|
||||||
<li v-for="(s, k) in filteredResults" :key="k" @click="navigate(s.url,$event)" style="cursor: pointer;">
|
<router-link to="#" event="">
|
||||||
<router-link :to="s.url">
|
|
||||||
<i v-if="s.dir" class="material-icons folder-icons"> folder </i>
|
<i v-if="s.dir" class="material-icons folder-icons"> folder </i>
|
||||||
<i v-else-if="s.audio" class="material-icons audio-icons"> volume_up </i>
|
<i v-else-if="s.audio" class="material-icons audio-icons"> volume_up </i>
|
||||||
<i v-else-if="s.image" class="material-icons image-icons"> photo </i>
|
<i v-else-if="s.image" class="material-icons image-icons"> photo </i>
|
||||||
<i v-else-if="s.video" class="material-icons video-icons"> movie </i>
|
<i v-else-if="s.video" class="material-icons video-icons"> movie </i>
|
||||||
<i v-else-if="s.archive" class="material-icons archive-icons"> archive </i>
|
<i v-else-if="s.archive" class="material-icons archive-icons"> archive </i>
|
||||||
<i v-else class="material-icons file-icons"> insert_drive_file </i>
|
<i v-else class="material-icons file-icons"> insert_drive_file </i>
|
||||||
{{ s.path }}
|
<span class="text-container">
|
||||||
|
{{ basePath(s.path) }}<b>{{ baseName(s.path) }}</b>
|
||||||
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<p id="renew">
|
|
||||||
<i class="material-icons spin">autorenew</i>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -77,10 +55,13 @@ import url from "@/utils/url";
|
||||||
import { search } from "@/api";
|
import { search } from "@/api";
|
||||||
|
|
||||||
var boxes = {
|
var boxes = {
|
||||||
image: { label: "images", icon: "insert_photo" },
|
folder: { label: "folders", icon: "folder" },
|
||||||
audio: { label: "music", icon: "volume_up" },
|
file: { label: "files", icon: "insert_drive_file" },
|
||||||
video: { label: "video", icon: "movie" },
|
archive: { label: "archives", icon: "archive" },
|
||||||
pdf: { label: "pdf", icon: "picture_as_pdf" },
|
image: { label: "images", icon: "photo" },
|
||||||
|
audio: { label: "audio files", icon: "volume_up" },
|
||||||
|
video: { label: "videos", icon: "movie" },
|
||||||
|
doc: { label: "documents", icon: "picture_as_pdf" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -139,9 +120,6 @@ export default {
|
||||||
? this.$t("search.typeToSearch")
|
? this.$t("search.typeToSearch")
|
||||||
: this.$t("search.pressToSearch");
|
: this.$t("search.pressToSearch");
|
||||||
},
|
},
|
||||||
filteredResults() {
|
|
||||||
return this.results.slice(0, this.resultsCount);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$refs.result.addEventListener("scroll", (event) => {
|
this.$refs.result.addEventListener("scroll", (event) => {
|
||||||
|
@ -154,26 +132,38 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async navigateTo(url) {
|
||||||
|
this.closeHovers();
|
||||||
|
await this.$nextTick();
|
||||||
|
setTimeout(() => this.$router.push(url), 0);
|
||||||
|
},
|
||||||
|
getContext(url) {
|
||||||
|
url = url.slice(1)
|
||||||
|
let path = "./" + url.substring(url.indexOf('/') + 1);
|
||||||
|
return path.replace(/\/+$/, '') + "/"
|
||||||
|
},
|
||||||
|
basePath(str) {
|
||||||
|
let parts = str.replace(/\/$/, '').split("/")
|
||||||
|
parts.pop()
|
||||||
|
return parts.join("/") + "/"
|
||||||
|
},
|
||||||
|
baseName(str) {
|
||||||
|
let parts = str.replace(/\/$/, '').split("/")
|
||||||
|
return parts.pop();
|
||||||
|
},
|
||||||
...mapMutations(["showHover", "closeHovers", "setReload"]),
|
...mapMutations(["showHover", "closeHovers", "setReload"]),
|
||||||
open() {
|
open() {
|
||||||
this.showHover("search");
|
this.showHover("search");
|
||||||
},
|
},
|
||||||
close(event) {
|
close(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
|
||||||
console.log("closing")
|
|
||||||
this.closeHovers();
|
this.closeHovers();
|
||||||
},
|
},
|
||||||
navigate(url, event) {
|
|
||||||
this.close(event); // pass the event object to the close method
|
|
||||||
this.$router.push(url);
|
|
||||||
},
|
|
||||||
keyup(event) {
|
keyup(event) {
|
||||||
if (event.keyCode === 27) {
|
if (event.keyCode === 27) {
|
||||||
this.close(event);
|
this.close(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.results.length === 0;
|
this.results.length === 0;
|
||||||
},
|
},
|
||||||
init(string) {
|
init(string) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
header {
|
header {
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background-color: #fff;
|
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.075);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.075);
|
||||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -12,6 +11,7 @@ header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.5em 0.5em 0.5em 1em;
|
padding: 0.5em 0.5em 0.5em 1em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
}
|
}
|
||||||
|
|
||||||
header > * {
|
header > * {
|
||||||
|
@ -119,11 +119,20 @@ header .menu-button {
|
||||||
#result-list {
|
#result-list {
|
||||||
width: 60em;
|
width: 60em;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding: 0.5em;
|
padding-top: 3em;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-container {
|
||||||
|
white-space: nowrap; /* Prevents the text from wrapping */
|
||||||
|
overflow: hidden; /* Hides the content that exceeds the div size */
|
||||||
|
text-overflow: ellipsis; /* Adds "..." when the text overflows */
|
||||||
|
width: 100%; /* Ensures the content takes the full width available */
|
||||||
|
text-align: left;
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
#search #result {
|
#search #result {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: white;
|
background: white;
|
||||||
|
@ -165,8 +174,7 @@ body.rtl #search #result ul>* {
|
||||||
}
|
}
|
||||||
|
|
||||||
#search.active #result {
|
#search.active #result {
|
||||||
padding: .5em;
|
height: 100vh
|
||||||
height: 100%
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#search ul {
|
#search ul {
|
||||||
|
@ -176,7 +184,7 @@ body.rtl #search #result ul>* {
|
||||||
}
|
}
|
||||||
|
|
||||||
#search li {
|
#search li {
|
||||||
margin-bottom: .5em;
|
margin: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search #result #renew {
|
#search #result #renew {
|
||||||
|
|
|
@ -805,9 +805,7 @@ export default {
|
||||||
prompt: "download",
|
prompt: "download",
|
||||||
confirm: (format) => {
|
confirm: (format) => {
|
||||||
this.$store.commit("closeHovers");
|
this.$store.commit("closeHovers");
|
||||||
|
|
||||||
let files = [];
|
let files = [];
|
||||||
|
|
||||||
if (this.selectedCount > 0) {
|
if (this.selectedCount > 0) {
|
||||||
for (let i of this.selected) {
|
for (let i of this.selected) {
|
||||||
files.push(this.req.items[i].url);
|
files.push(this.req.items[i].url);
|
||||||
|
@ -822,7 +820,6 @@ export default {
|
||||||
},
|
},
|
||||||
switchView: async function () {
|
switchView: async function () {
|
||||||
this.$store.commit("closeHovers");
|
this.$store.commit("closeHovers");
|
||||||
|
|
||||||
const modes = {
|
const modes = {
|
||||||
list: "mosaic",
|
list: "mosaic",
|
||||||
mosaic: "mosaic gallery",
|
mosaic: "mosaic gallery",
|
||||||
|
|
Loading…
Reference in New Issue