Compare commits

...

9 Commits

18 changed files with 2703 additions and 1695 deletions

View File

@ -48,10 +48,11 @@ sist2 (Simple incremental search tool)
- "ES_JAVA_OPTS=-Xms1G -Xmx2G"
```
1. Download sist2 executable
1. Download the [latest sist2 release](https://github.com/simon987/sist2/releases) *
1. *(or)* Download a [development snapshot](https://files.simon987.net/.gate/sist2/simon987_sist2/) *(Not
1. Download the [latest sist2 release](https://github.com/simon987/sist2/releases).
Select the file corresponding to your CPU architecture and mark the binary as executable with `chmod +x` *
2. *(or)* Download a [development snapshot](https://files.simon987.net/.gate/sist2/simon987_sist2/) *(Not
recommended!)*
1. *(or)* `docker pull simon987/sist2:2.11.6-x64-linux`
3. *(or)* `docker pull simon987/sist2:2.11.6-x64-linux`
1. See [Usage guide](docs/USAGE.md)
@ -73,8 +74,8 @@ See [Usage guide](docs/USAGE.md) for more details
| cbz,cbr | [libscan](https://github.com/simon987/sist2/tree/master/third-party/libscan) | - | yes | - |
| `audio/*` | ffmpeg | - | yes | ID3 tags |
| `video/*` | ffmpeg | - | yes | title, comment, artist |
| `image/*` | ffmpeg | - | yes | [Common EXIF tags](https://github.com/simon987/sist2/blob/efdde2734eca9b14a54f84568863b7ffd59bdba3/src/parsing/media.c#L190), GPS tags |
| raw, rw2, dng, cr2, crw, dcr, k25, kdc, mrw, pef, xf3, arw, sr2, srf, erf | LibRaw | - | yes | Common EXIF tags, GPS tags |
| `image/*` | ffmpeg | ocr | yes | [Common EXIF tags](https://github.com/simon987/sist2/blob/efdde2734eca9b14a54f84568863b7ffd59bdba3/src/parsing/media.c#L190), GPS tags |
| raw, rw2, dng, cr2, crw, dcr, k25, kdc, mrw, pef, xf3, arw, sr2, srf, erf | LibRaw | no | yes | Common EXIF tags, GPS tags |
| ttf,ttc,cff,woff,fnt,otf | Freetype2 | - | yes, `bmp` | Name & style |
| `text/plain` | [libscan](https://github.com/simon987/sist2/tree/master/third-party/libscan) | yes | no | - |
| html, xml | [libscan](https://github.com/simon987/sist2/tree/master/third-party/libscan) | yes | no | - |

View File

@ -43,7 +43,9 @@ Scan options
--depth=<int> Scan up to DEPTH subdirectories deep. Use 0 to only scan files in PATH. DEFAULT: -1
--archive=<str> Archive file mode (skip|list|shallow|recurse). skip: Don't parse, list: only get file names as text, shallow: Don't parse archives inside archives. DEFAULT: recurse
--archive-passphrase=<str> Passphrase for encrypted archive files
# TODO: add new --ocr-* options here
--ocr-lang=<str> Tesseract language (use 'tesseract --list-langs' to see which are installed on your machine)
--ocr-images Enable OCR'ing of image files.
--ocr-ebooks Enable OCR'ing of ebook files.
-e, --exclude=<str> Files that match this regex will not be scanned
--fast Only index file names & mime type
--treemap-threshold=<str> Relative size threshold for treemap (see USAGE.md). DEFAULT: 0.0005
@ -51,6 +53,7 @@ Scan options
--read-subtitles Read subtitles from media files.
--fast-epub Faster but less accurate EPUB parsing (no thumbnails, metadata)
--checksums Calculate file checksums when scanning.
--list-file=<str> Specify a list of newline-delimited paths to be scanned instead of normal directory traversal. Use '-' to read from stdin.
Index options
-t, --threads=<int> Number of threads. DEFAULT=1
@ -72,6 +75,7 @@ Web options
--tag-auth=<str> Basic auth in user:password format for tagging
--tagline=<str> Tagline in navbar
--dev Serve html & js files from disk (for development)
--lang=<str> Default UI language. Can be changed by the user
Exec-script options
--es-url=<str> Elasticsearch url. DEFAULT=http://localhost:9200
@ -105,7 +109,7 @@ Exec-script options
* list: Only get file names as text
* shallow: Don't parse archives inside archives.
* recurse: Scan archives recursively (default)
* `--ocr` See [OCR](../README.md#OCR)
* `--ocr-lang`, `--ocr-ebooks`, `--ocr-images` See [OCR](../README.md#OCR)
* `-e, --exclude` Regex pattern to exclude files. A file is excluded if the pattern matches any
part of the full absolute path.
@ -248,6 +252,8 @@ sist2 index --print ./my_index/ | jq | less
`--auth` argument, but authentication is only applied the `/tag/` endpoint.
* `--tagline=<str>` When specified, will replace the default tagline in the navbar.
* `--dev` Serve html & js files from disk (for development, used to modify frontend files without having to recompile)
* `--lang=<str>` Set the default web UI language (See #180 for a list of supported languages, default
is `en`). The user can change the language in the configuration page
### Web examples

9
sist2-vue/dist/css/chunk-vendors.css vendored Normal file

File diff suppressed because one or more lines are too long

1
sist2-vue/dist/css/index.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
},
"dependencies": {
"@egjs/vue-infinitegrid": "3.3.0",
"axios": "^0.21.1",
"axios": "^0.25.0",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.6.5",
"crypto-es": "^1.2.7",

View File

@ -1,5 +1,31 @@
<template>
<div v-if="$store.state.optUseDatePicker">
<b-row>
<b-col sm="6">
<b-form-datepicker
value-as-date
:date-format-options="{ year: 'numeric', month: '2-digit', day: '2-digit' }"
:locale="$store.state.optLang"
class="mb-2"
:value="dateMin" @input="setDateMin"></b-form-datepicker>
</b-col>
<b-col sm="6">
<b-form-datepicker
value-as-date
:date-format-options="{ year: 'numeric', month: '2-digit', day: '2-digit' }"
:locale="$store.state.optLang"
class="mb-2"
:value="dateMax" @input="setDateMax"></b-form-datepicker>
</b-col>
</b-row>
</div>
<div v-else>
<b-row>
<b-col style="height: 70px;">
<div id="dateSlider"></div>
</b-col>
</b-row>
</div>
</template>
<script>
@ -10,11 +36,36 @@ import {mergeTooltips} from "@/util-js";
export default {
name: "DateSlider",
methods: {
setDateMin(val) {
const epochDate = Math.ceil(+val / 1000);
this.$store.commit("setDateMin", epochDate);
},
setDateMax(val) {
const epochDate = Math.ceil(+val / 1000);
this.$store.commit("setDateMax", epochDate);
},
},
computed: {
dateMin() {
const dateMin = this.$store.state.dateMin ? this.$store.state.dateMin : this.$store.state.dateBoundsMin;
return new Date(dateMin * 1000)
},
dateMax() {
const dateMax = this.$store.state.dateMax ? this.$store.state.dateMax : this.$store.state.dateBoundsMax;
return new Date(dateMax * 1000)
}
},
mounted() {
this.$store.subscribe((mutation) => {
if (mutation.type === "setDateBoundsMax") {
const elem = document.getElementById("dateSlider");
if (elem === null) {
// Using b-form-datepicker, skip initialisation of slider
return
}
if (elem.children.length > 0) {
return;
}

View File

@ -16,7 +16,8 @@ export default {
data() {
return {
mimeTree: null,
stashedMimeTreeAttributes: null
stashedMimeTreeAttributes: null,
updateBusy: false
}
},
mounted() {
@ -34,6 +35,10 @@ export default {
return;
}
if (this.updateBusy) {
return;
}
this.$store.commit("setSelectedMimeTypes", getSelectedTreeNodes(this.mimeTree));
},
updateTree() {
@ -42,6 +47,11 @@ export default {
return;
}
if (this.updateBusy) {
return
}
this.updateBusy = true;
if (this.stashedMimeTreeAttributes === null) {
this.stashedMimeTreeAttributes = getTreeNodeAttributes(this.mimeTree);
}
@ -78,6 +88,7 @@ export default {
}
});
this.stashedMimeTreeAttributes = null;
this.updateBusy = false;
});
},

View File

@ -67,7 +67,8 @@ export default {
tagOrOperator: "Use OR operator when specifying multiple tags.",
hideDuplicates: "Hide duplicate results based on checksum",
hideLegacy: "Hide the 'legacyES' Elasticsearch notice",
updateMimeMap: "Update the Media Types tree in real time"
updateMimeMap: "Update the Media Types tree in real time",
useDatePicker: "Use a Date Picker component rather than a slider"
},
queryMode: {
simple: "Simple",
@ -229,7 +230,8 @@ export default {
tagOrOperator: "Utiliser l'opérateur OU lors de la spécification de plusieurs tags",
hideDuplicates: "Masquer les résultats en double",
hideLegacy: "Masquer la notice 'legacyES' Elasticsearch",
updateMimeMap: "Mettre à jour l'arbre de Types de médias en temps réel"
updateMimeMap: "Mettre à jour l'arbre de Types de médias en temps réel",
useDatePicker: "Afficher un composant « Date Picker » plutôt qu'un slider"
},
queryMode: {
simple: "Simple",
@ -391,7 +393,8 @@ export default {
tagOrOperator: "使用或操作OR匹配多个标签。",
hideDuplicates: "使用校验码隐藏重复结果",
hideLegacy: "隐藏'legacyES' Elasticsearch 通知",
updateMimeMap: "媒体类型树的实时更新"
updateMimeMap: "媒体类型树的实时更新",
useDatePicker: "使用日期选择器组件而不是滑块"
},
queryMode: {
simple: "简单",

View File

@ -49,6 +49,7 @@ export default new Vuex.Store({
optLightboxSlideDuration: 15,
optHideLegacy: false,
optUpdateMimeMap: true,
optUseDatePicker: false,
_onLoadSelectedIndices: [] as string[],
_onLoadSelectedMimeTypes: [] as string[],
@ -157,6 +158,7 @@ export default new Vuex.Store({
setOptTreemapColor: (state, val) => state.optTreemapColor = val,
setOptHideLegacy: (state, val) => state.optHideLegacy = val,
setOptUpdateMimeMap: (state, val) => state.optUpdateMimeMap = val,
setOptUseDatePicker: (state, val) => state.optUseDatePicker = val,
setOptLightboxLoadOnlyCurrent: (state, val) => state.optLightboxLoadOnlyCurrent = val,
setOptLightboxSlideDuration: (state, val) => state.optLightboxSlideDuration = val,
@ -366,5 +368,6 @@ export default new Vuex.Store({
optResultSize: state => state.size,
optHideLegacy: state => state.optHideLegacy,
optUpdateMimeMap: state => state.optUpdateMimeMap,
optUseDatePicker: state => state.optUseDatePicker,
}
})

View File

@ -41,6 +41,10 @@
<b-form-checkbox :checked="optUpdateMimeMap" @input="setOptUpdateMimeMap">
{{ $t("opt.updateMimeMap") }}
</b-form-checkbox>
<b-form-checkbox :checked="optUseDatePicker" @input="setOptUseDatePicker">
{{ $t("opt.useDatePicker") }}
</b-form-checkbox>
</b-card>
<br/>
@ -229,6 +233,7 @@ export default {
"optHideDuplicates",
"optHideLegacy",
"optUpdateMimeMap",
"optUseDatePicker",
]),
clientWidth() {
return window.innerWidth;
@ -272,7 +277,8 @@ export default {
"setOptLang",
"setOptHideDuplicates",
"setOptHideLegacy",
"setOptUpdateMimeMap"
"setOptUpdateMimeMap",
"setOptUseDatePicker",
]),
onResetClick() {
localStorage.removeItem("sist2_configuration");

View File

@ -19,11 +19,7 @@
</b-row>
<b-row>
<b-col sm="6">
<b-row>
<b-col style="height: 70px;">
<DateSlider></DateSlider>
</b-col>
</b-row>
<b-row>
<b-col>
<IndexPicker></IndexPicker>

View File

@ -85,8 +85,7 @@ int scan_args_validate(scan_args_t *args, int argc, const char **argv) {
char *abs_path = abspath(argv[1]);
if (abs_path == NULL) {
fprintf(stderr, "File not found: %s\n", argv[1]);
return 1;
LOG_FATALF("cli.c", "Invalid PATH argument. File not found: %s", argv[1])
} else {
args->path = abs_path;
}
@ -335,8 +334,7 @@ int index_args_validate(index_args_t *args, int argc, const char **argv) {
char *index_path = abspath(argv[1]);
if (index_path == NULL) {
fprintf(stderr, "File not found: %s\n", argv[1]);
return 1;
LOG_FATALF("cli.c", "Invalid PATH argument. File not found: %s", argv[1])
} else {
args->index_path = argv[1];
free(index_path);
@ -376,8 +374,16 @@ int index_args_validate(index_args_t *args, int argc, const char **argv) {
LOG_DEBUGF("cli.c", "arg es_index=%s", args->es_index)
LOG_DEBUGF("cli.c", "arg index_path=%s", args->index_path)
LOG_DEBUGF("cli.c", "arg script_path=%s", args->script_path)
LOG_DEBUGF("cli.c", "arg async_script=%s", args->async_script)
LOG_DEBUGF("cli.c", "arg script=%s", args->script)
char log_buf[5000];
strncpy(log_buf, args->script, sizeof(log_buf));
*(log_buf + sizeof(log_buf) - 1) = '\0';
LOG_DEBUGF("cli.c", "arg async_script=%s", log_buf)
strncpy(log_buf, args->script, sizeof(log_buf));
*(log_buf + sizeof(log_buf) - 1) = '\0';
LOG_DEBUGF("cli.c", "arg script=%s", log_buf)
LOG_DEBUGF("cli.c", "arg print=%d", args->print)
LOG_DEBUGF("cli.c", "arg es_mappings_path=%s", args->es_mappings_path)
LOG_DEBUGF("cli.c", "arg es_mappings=%s", args->es_mappings)
@ -474,8 +480,7 @@ int web_args_validate(web_args_t *args, int argc, const char **argv) {
for (int i = 0; i < args->index_count; i++) {
char *abs_path = abspath(args->indices[i]);
if (abs_path == NULL) {
fprintf(stderr, "File not found: %s\n", args->indices[i]);
return 1;
LOG_FATALF("cli.c", "Index not found: %s", args->indices[i])
}
}
@ -515,8 +520,7 @@ int exec_args_validate(exec_args_t *args, int argc, const char **argv) {
char *index_path = abspath(argv[1]);
if (index_path == NULL) {
fprintf(stderr, "File not found: %s\n", argv[1]);
return 1;
LOG_FATALF("cli.c", "Invalid index PATH argument. File not found: %s", argv[1])
} else {
args->index_path = argv[1];
free(index_path);
@ -539,6 +543,11 @@ int exec_args_validate(exec_args_t *args, int argc, const char **argv) {
}
LOG_DEBUGF("cli.c", "arg script_path=%s", args->script_path)
LOG_DEBUGF("cli.c", "arg script=%s", args->script)
char log_buf[5000];
strncpy(log_buf, args->script, sizeof(log_buf));
*(log_buf + sizeof(log_buf) - 1) = '\0';
LOG_DEBUGF("cli.c", "arg script=%s", log_buf)
return 0;
}

View File

@ -48,6 +48,12 @@ void vsist_logf(const char *filepath, int level, char *format, va_list ap) {
size_t maxsize = sizeof(log_str) - log_len;
log_len += vsnprintf(log_str + log_len, maxsize, format, ap);
if (log_len >= maxsize) {
fprintf(stderr, "([%s] FIXME: Log string is too long to display: %dB)\n",
log_levels[level], log_len);
return;
}
if (is_tty) {
log_len += sprintf(log_str + log_len, "\033[0m\n");
} else {

View File

@ -53,7 +53,7 @@
#include <ctype.h>
#include "git_hash.h"
#define VERSION "2.11.6"
#define VERSION "2.11.7"
static const char *const Version = VERSION;
#ifndef SIST_PLATFORM

File diff suppressed because one or more lines are too long