6 Commits

Author SHA1 Message Date
Eva
5387e4f187 Merge 5e54caf04c into 376f687c38 2025-02-20 22:02:35 +01:00
376f687c38 chore: questionable is not a recognized rating 2025-02-11 21:50:27 +01:00
4fd848abf2 doc: use docker compose instead of docker-compose
The minimum version requirements are rough guesses, in practice any decently modern docker installation should work.
2025-02-11 21:25:10 +01:00
Eva
5e54caf04c client/views: fix middle click prevention on buttons for modern browsers
Browsers no longer fire the primary 'click' event for middle clicks.
Old way kept for compatibility as it doesn't hurt anything. All browsers
that support auxclick also have standardized MouseEvent.button values.
2024-05-06 19:45:24 +02:00
Eva
337cdc091e client: replace deprecated KeyboardEvent.which with KeyboardEvent.key
Also fixes moving notes by arrow keys.

Removed left click detection IE8 hack we inherited from the original
visionmedia/page.js code (cf. https://unixpapa.com/js/mouse.html) as
proper KeyboardEvent.key was introduced in IE9 and it's time to move on.

ArrowUp/Down/Left/Right names have to be mangled to maintain IE9 compat.
2024-05-06 19:45:19 +02:00
Eva
e0a04acb06 client/search: fix js error when pressing esc key
`this` became inaccessible from hide() when the function was called
from outside.
Note: I don't like the behavior of Escape and Delete, as pressing them
more than once reverses their action.
2024-05-06 19:45:13 +02:00
11 changed files with 45 additions and 70 deletions

View File

@ -2,13 +2,6 @@
const views = require("../util/views.js");
const KEY_TAB = 9;
const KEY_RETURN = 13;
const KEY_DELETE = 46;
const KEY_ESCAPE = 27;
const KEY_UP = 38;
const KEY_DOWN = 40;
function _getSelectionStart(input) {
if ("selectionStart" in input) {
return input.selectionStart;
@ -142,34 +135,36 @@ class AutoCompleteControl {
}
_evtKeyDown(e) {
const key = e.which;
const key = (e.key || "").replace("Arrow", "");
const shift = e.shiftKey;
let func = null;
if (this._isVisible) {
if (key === KEY_ESCAPE) {
func = this.hide;
} else if (key === KEY_TAB && shift) {
if (key === "Escape") {
func = () => {
this.hide();
};
} else if (key === "Tab" && shift) {
func = () => {
this._selectPrevious();
};
} else if (key === KEY_TAB && !shift) {
} else if (key === "Tab" && !shift) {
func = () => {
this._selectNext();
};
} else if (key === KEY_UP) {
} else if (key === "Up") {
func = () => {
this._selectPrevious();
};
} else if (key === KEY_DOWN) {
} else if (key === "Down") {
func = () => {
this._selectNext();
};
} else if (key === KEY_RETURN && this._activeResult >= 0) {
} else if (key === "Enter" && this._activeResult >= 0) {
func = () => {
this._confirm(this._getActiveSuggestion());
this.hide();
};
} else if (key === KEY_DELETE && this._activeResult >= 0) {
} else if (key === "Delete" && this._activeResult >= 0) {
func = () => {
this._delete(this._getActiveSuggestion());
this.hide();

View File

@ -5,8 +5,6 @@ const views = require("../util/views.js");
const template = views.getTemplate("file-dropper");
const KEY_RETURN = 13;
class FileDropperControl extends events.EventTarget {
constructor(target, options) {
super();
@ -152,7 +150,7 @@ class FileDropperControl extends events.EventTarget {
}
_evtUrlInputKeyDown(e) {
if (e.which !== KEY_RETURN) {
if (e.key !== "Enter") {
return;
}
e.preventDefault();

View File

@ -10,9 +10,6 @@ const events = require("../events.js");
const views = require("../util/views.js");
const PoolAutoCompleteControl = require("./pool_auto_complete_control.js");
const KEY_SPACE = 32;
const KEY_RETURN = 13;
const SOURCE_INIT = "init";
const SOURCE_IMPLICATION = "implication";
const SOURCE_USER_INPUT = "user-input";

View File

@ -11,15 +11,6 @@ const svgNS = "http://www.w3.org/2000/svg";
const snapThreshold = 10;
const circleSize = 10;
const MOUSE_BUTTON_LEFT = 1;
const KEY_LEFT = 37;
const KEY_UP = 38;
const KEY_RIGHT = 39;
const KEY_DOWN = 40;
const KEY_ESCAPE = 27;
const KEY_RETURN = 13;
function _getDistance(point1, point2) {
return Math.sqrt(
Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)
@ -188,16 +179,17 @@ class SelectedState extends ActiveState {
evtCanvasKeyDown(e) {
const delta = e.ctrlKey ? 10 : 1;
const offsetMap = {
[KEY_LEFT]: [-delta, 0],
[KEY_UP]: [0, -delta],
[KEY_DOWN]: [0, delta],
[KEY_RIGHT]: [delta, 0],
["Left"]: [-delta, 0],
["Up"]: [0, -delta],
["Down"]: [0, delta],
["Right"]: [delta, 0],
};
if (Object.prototype.hasOwnProperty.call(offsetMap, e.witch)) {
const key = (e.key || "").replace("Arrow", "");
if (Object.prototype.hasOwnProperty.call(offsetMap, key)) {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();
const args = offsetMap[e.which];
const args = offsetMap[key];
if (e.shiftKey) {
this._scaleEditedNote(...args);
} else {
@ -331,7 +323,7 @@ class MovingPointState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which === KEY_ESCAPE) {
if (e.key === "Escape") {
this._notePoint.x = this._originalNotePoint.x;
this._notePoint.y = this._originalNotePoint.y;
this._control._state = new SelectedState(
@ -364,7 +356,7 @@ class MovingNoteState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which === KEY_ESCAPE) {
if (e.key === "Escape") {
for (let i of misc.range(this._note.polygon.length)) {
this._note.polygon.at(i).x = this._originalPolygon[i].x;
this._note.polygon.at(i).y = this._originalPolygon[i].y;
@ -402,7 +394,7 @@ class ScalingNoteState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which === KEY_ESCAPE) {
if (e.key === "Escape") {
for (let i of misc.range(this._note.polygon.length)) {
this._note.polygon.at(i).x = this._originalPolygon[i].x;
this._note.polygon.at(i).y = this._originalPolygon[i].y;
@ -516,12 +508,12 @@ class DrawingPolygonState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which === KEY_ESCAPE) {
if (e.key === "Escape") {
this._note.polygon.remove(this._note.polygon.secondLastPoint);
if (this._note.polygon.length === 1) {
this._cancel();
}
} else if (e.which === KEY_RETURN) {
} else if (e.key === "Enter") {
this._finish();
}
}
@ -683,7 +675,7 @@ class PostNotesOverlayControl extends events.EventTarget {
_evtCanvasMouseDown(e) {
e.preventDefault();
if (e.which !== MOUSE_BUTTON_LEFT) {
if (e.button !== 0) {
return;
}
const hoveredNode = document.elementFromPoint(e.clientX, e.clientY);

View File

@ -10,9 +10,6 @@ const events = require("../events.js");
const views = require("../util/views.js");
const TagAutoCompleteControl = require("./tag_auto_complete_control.js");
const KEY_SPACE = 32;
const KEY_RETURN = 13;
const SOURCE_INIT = "init";
const SOURCE_IMPLICATION = "implication";
const SOURCE_USER_INPUT = "user-input";
@ -273,7 +270,7 @@ class TagInputControl extends events.EventTarget {
}
_evtInputKeyDown(e) {
if (e.which === KEY_RETURN || e.which === KEY_SPACE) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
this._hideAutoComplete();
this.addTagByText(this._tagInputNode.value, SOURCE_USER_INPUT);

View File

@ -258,7 +258,7 @@ const _onPopState = (router) => {
const _onClick = (router) => {
return (e) => {
if (1 !== _which(e)) {
if (e.button !== 0) {
return;
}
if (e.metaKey || e.ctrlKey || e.shiftKey) {
@ -310,11 +310,6 @@ const _onClick = (router) => {
};
};
function _which(e) {
e = e || window.event;
return e.which === null ? e.button : e.which;
}
Router.prototype.Context = Context;
Router.prototype.Route = Route;
module.exports = new Router();

View File

@ -571,6 +571,11 @@ document.addEventListener("click", (e) => {
e.preventDefault();
}
});
document.addEventListener("auxclick", (e) => {
if (e.target.getAttribute("href") === "" && e.button === 1) {
e.preventDefault();
}
});
module.exports = {
htmlToDom: htmlToDom,

View File

@ -3,7 +3,6 @@
const events = require("../events.js");
const views = require("../util/views.js");
const KEY_RETURN = 13;
const template = views.getTemplate("post-merge");
const sideTemplate = views.getTemplate("post-merge-side");
@ -110,8 +109,7 @@ class PostMergeView extends events.EventTarget {
}
_evtPostSearchFieldKeyDown(e) {
const key = e.which;
if (key !== KEY_RETURN) {
if (e.key !== "Enter") {
return;
}
e.target.blur();

View File

@ -789,7 +789,7 @@ data.
| `fav-time` | alias of `fav-date` |
| `feature-date` | featured at given date |
| `feature-time` | alias of `feature-time` |
| `safety` | having given safety. `<value>` can be either `safe`, `sketchy` (or `questionable`) or `unsafe`. |
| `safety` | having given safety. `<value>` can be either `safe`, `sketchy` or `unsafe`. |
| `rating` | alias of `safety` |
**Sort style tokens**

View File

@ -1,5 +1,5 @@
This assumes that you have Docker (version 17.05 or greater)
and Docker Compose (version 1.6.0 or greater) already installed.
This assumes that you have Docker (version 19.03 or greater)
and the Docker Compose CLI (version 1.27.0 or greater) already installed.
### Prepare things
@ -38,7 +38,7 @@ and Docker Compose (version 1.6.0 or greater) already installed.
This pulls the latest containers from docker.io:
```console
user@host:szuru$ docker-compose pull
user@host:szuru$ docker compose pull
```
If you have modified the application's source and would like to manually
@ -49,17 +49,17 @@ and Docker Compose (version 1.6.0 or greater) already installed.
For first run, it is recommended to start the database separately:
```console
user@host:szuru$ docker-compose up -d sql
user@host:szuru$ docker compose up -d sql
```
To start all containers:
```console
user@host:szuru$ docker-compose up -d
user@host:szuru$ docker compose up -d
```
To view/monitor the application logs:
```console
user@host:szuru$ docker-compose logs -f
user@host:szuru$ docker compose logs -f
# (CTRL+C to exit)
```
@ -84,13 +84,13 @@ and Docker Compose (version 1.6.0 or greater) already installed.
2. Build the containers:
```console
user@host:szuru$ docker-compose build
user@host:szuru$ docker compose build
```
That will attempt to build both containers, but you can specify `client`
or `server` to make it build only one.
If `docker-compose build` spits out:
If `docker compose build` spits out:
```
ERROR: Service 'server' failed to build: failed to parse platform : "" is an invalid component of "": platform specifier component must match "^[A-Za-z0-9_-]+$": invalid argument
@ -102,7 +102,7 @@ and Docker Compose (version 1.6.0 or greater) already installed.
user@host:szuru$ export DOCKER_BUILDKIT=1; export COMPOSE_DOCKER_CLI_BUILD=1
```
...and run `docker-compose build` again.
...and run `docker compose build` again.
*Note: If your changes are not taking effect in your builds, consider building
with `--no-cache`.*
@ -117,7 +117,7 @@ with `--no-cache`.*
run from docker:
```console
user@host:szuru$ docker-compose run server ./szuru-admin --help
user@host:szuru$ docker compose run server ./szuru-admin --help
```
will give you a breakdown on all available commands.

View File

@ -1,9 +1,7 @@
## Example Docker Compose configuration
##
## Use this as a template to set up docker-compose, or as guide to set up other
## Use this as a template to set up docker compose, or as guide to set up other
## orchestration services
version: '2'
services:
server: