Compare commits
5 Commits
f974d5361e
...
v0.6.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 73206d41ec | |||
| 86345117f7 | |||
| 5cae80636b | |||
| 7cadfac350 | |||
| 5a7d23f7e3 |
21
.env.default
Normal file
@@ -0,0 +1,21 @@
|
||||
PROJECT=puzzlez
|
||||
SDK_PATH=$HOME/sdk
|
||||
PUBLISH_PATH=$HOME/public/$PROJECT
|
||||
BUILD_PATH=./build
|
||||
TARGET_PATH=./target
|
||||
KEY_STORE=<keystore.jks>
|
||||
KEY_PASS=<passphrase>
|
||||
REPO=https://git.shmyga.ru/api/packages/InfernalGames
|
||||
PUBLISH_USER=<username>
|
||||
PUBLISH_PASSWORD=<passphrase>
|
||||
|
||||
DOCKER_REPO=git.shmyga.ru
|
||||
DOCKER_GROUP=infernalgames
|
||||
DOCKER_ROOT="$DOCKER_REPO/$DOCKER_GROUP"
|
||||
VERSION=$(grep -m 1 'version' ./package.json | grep -oP '"version"\s*:\s*"\K\d+\.\d+.\d+')
|
||||
DOCKER_PROJECTS=(
|
||||
"$PROJECT-web:web"
|
||||
)
|
||||
DOCKER_ARGS=(
|
||||
"PROJECT_NAME=$PROJECT"
|
||||
)
|
||||
1
.gitignore
vendored
@@ -14,3 +14,4 @@ config.json
|
||||
/log
|
||||
/ansible/*.retry
|
||||
.npmrc
|
||||
.env
|
||||
35
Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
FROM ubuntu:noble AS base
|
||||
RUN apt update && apt install -y \
|
||||
nodejs \
|
||||
npm \
|
||||
openjdk-11-jre \
|
||||
protobuf-compiler \
|
||||
jq
|
||||
RUN node -v
|
||||
RUN npm -v
|
||||
|
||||
FROM base AS builder
|
||||
ENV GRADLE_USER_HOME=/sdk/gradle
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
COPY gulpfile.js protohx.json ./
|
||||
COPY tasks ./tasks
|
||||
COPY config.example.json ./config.example.json
|
||||
RUN --mount=type=secret,id=KEY_STORE \
|
||||
cat /run/secrets/KEY_STORE > ./key.jks
|
||||
RUN --mount=type=secret,id=KEY_PASS,env=KEY_PASS \
|
||||
jq --arg key_pass "$KEY_PASS" \
|
||||
'.SdkDir = "/sdk" | .PublishDir = "/app/publish" | .Key.store = "key.jks" | .Key.pass = $key_pass' \
|
||||
config.example.json > config.json
|
||||
COPY src ./src
|
||||
COPY dependencies ./dependencies
|
||||
VOLUME ["/sdk", "/app/build", "/app/target", "/app/publish", "/app/src-gen"]
|
||||
CMD ["npx", "gulp", "default"]
|
||||
|
||||
FROM hello-world AS web
|
||||
ARG PROJECT_NAME
|
||||
VOLUME ["/app/${PROJECT_NAME}"]
|
||||
COPY ./target/app/html5 /app/${PROJECT_NAME}/html5
|
||||
COPY ./target/app/flash /app/${PROJECT_NAME}/flash
|
||||
CMD ["/hello"]
|
||||
15
README.md
@@ -1,10 +1,9 @@
|
||||
`.bashrc`
|
||||
```bash
|
||||
export NEKO_VERSION="2.2.0"
|
||||
export HAXE_VERSION="4.2.5"
|
||||
# Puzzlez
|
||||
|
||||
export NEKO_SDK="$HOME/sdk/neko/$NEKO_VERSION"
|
||||
export HAXE_SDK="$HOME/sdk/haxe/$HAXE_VERSION"
|
||||
## Play
|
||||
|
||||
alias haxe-activate=". $NEKO_SDK/activate && . $HAXE_SDK/activate"
|
||||
```
|
||||
https://shmyga.ru/puzzlez/html5/index.html
|
||||
|
||||
## Packages
|
||||
|
||||
https://git.shmyga.ru/InfernalGames/-/packages/generic/puzzlez
|
||||
|
||||
23
docker-compose.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
name: $PROJECT
|
||||
services:
|
||||
builder:
|
||||
container_name: $PROJECT-builder
|
||||
image: infernal-games/$PROJECT-builder
|
||||
build:
|
||||
context: .
|
||||
target: builder
|
||||
secrets:
|
||||
- KEY_STORE
|
||||
- KEY_PASS
|
||||
volumes:
|
||||
- ${SDK_PATH}:/sdk
|
||||
- ${BUILD_PATH}:/app/build
|
||||
- ${TARGET_PATH}:/app/target
|
||||
- ${PUBLISH_PATH}:/app/publish
|
||||
- ./src-gen:/app/src-gen
|
||||
|
||||
secrets:
|
||||
KEY_STORE:
|
||||
file: $KEY_STORE
|
||||
KEY_PASS:
|
||||
environment: KEY_PASS
|
||||
200
gulpfile.js
@@ -1,139 +1,139 @@
|
||||
const gulp = require('gulp');
|
||||
const gulpClean = require('gulp-clean');
|
||||
const Config = require('./config.json');
|
||||
const packageInfo = require('./package.json');
|
||||
const {System, Sdk, Haxe, Project} = require('gulp-haxetool');
|
||||
const dateformat = require('dateformat');
|
||||
const argv = require('yargs').argv;
|
||||
const publish = require('./tasks/gulp-publish');
|
||||
const gulp = require("gulp");
|
||||
const gulpClean = require("gulp-clean");
|
||||
const Config = require("./config.json");
|
||||
const packageInfo = require("./package.json");
|
||||
const { System, Sdk, Haxe, Project } = require("gulp-haxetool");
|
||||
const dateformat = require("dateformat");
|
||||
const publish = require("./tasks/gulp-publish");
|
||||
|
||||
if (packageInfo.haxe) {
|
||||
Haxe.VERSION = packageInfo.haxe;
|
||||
Haxe.VERSION = packageInfo.haxe;
|
||||
}
|
||||
|
||||
if (Config.SdkDir) {
|
||||
Sdk.dir = Config.SdkDir;
|
||||
Sdk.dir = Config.SdkDir;
|
||||
}
|
||||
|
||||
if (Config.BuildDir) {
|
||||
Haxe.buildDir = Config.BuildDir;
|
||||
Haxe.buildDir = Config.BuildDir;
|
||||
}
|
||||
|
||||
exports.clean = function clean() {
|
||||
return gulp.src('target/*', {read: false}).pipe(gulpClean());
|
||||
return gulp.src("target/*", { read: false }).pipe(gulpClean());
|
||||
};
|
||||
|
||||
exports.generate = function generate() {
|
||||
return new Haxe().haxelib(['run', 'protohx', 'generate', 'protohx.json']).then(({stdout}) => {
|
||||
if (stdout.indexOf('FAIL') > -1) {
|
||||
throw stdout;
|
||||
exports.setup = function setup() {
|
||||
const builder = Project.Builder.new(
|
||||
app.config,
|
||||
Project.Platform.ANDROID,
|
||||
app.buildSystem,
|
||||
);
|
||||
return builder.prepare();
|
||||
};
|
||||
|
||||
exports.generate = function generate() {
|
||||
return exports.setup().then(() =>
|
||||
new Haxe()
|
||||
.haxelib(["run", "protohx", "generate", "protohx.json"])
|
||||
.then(({ stdout }) => {
|
||||
if (stdout.indexOf("FAIL") > -1) {
|
||||
throw stdout;
|
||||
}
|
||||
});
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const config = new Project.Config({
|
||||
meta: {
|
||||
title: 'Puzzle\'z',
|
||||
filename: 'puzzlez',
|
||||
icon: 'src/app/resources/icon.png',
|
||||
pack: 'ru.m.puzzlez',
|
||||
author: 'shmyga <shmyga.z@gmail.com>',
|
||||
company: 'MegaLoMania',
|
||||
version: packageInfo.version + (Config.Develop ? '-SNAPSHOT' : ''),
|
||||
},
|
||||
key: Config.Key,
|
||||
libs: packageInfo.haxeDependencies,
|
||||
macros: [
|
||||
`CompilationOption.set('build','${dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss')}')`,
|
||||
`CompilationOption.set('UNSPLASH_KEY','${Config.UnsplashKey}')`,
|
||||
`CompilationOption.set('PIXABAY_KEY','${Config.PixabayKey}')`,
|
||||
],
|
||||
flags: [
|
||||
'proto_debug',
|
||||
]
|
||||
meta: {
|
||||
title: "Puzzle'z",
|
||||
filename: "puzzlez",
|
||||
icon: "src/app/resources/icon.png",
|
||||
pack: "ru.m.puzzlez",
|
||||
author: "shmyga <shmyga.z@gmail.com>",
|
||||
company: "MegaLoMania",
|
||||
version: packageInfo.version + (Config.Develop ? "-SNAPSHOT" : ""),
|
||||
},
|
||||
key: Config.Key,
|
||||
libs: packageInfo.haxeDependencies,
|
||||
macros: [
|
||||
`CompilationOption.set('build','${dateformat(new Date(), "yyyy-mm-dd HH:MM:ss")}')`,
|
||||
`CompilationOption.set('UNSPLASH_KEY','${Config.UnsplashKey}')`,
|
||||
`CompilationOption.set('PIXABAY_KEY','${Config.PixabayKey}')`,
|
||||
],
|
||||
flags: ["proto_debug"],
|
||||
});
|
||||
|
||||
const app = new Project(
|
||||
Project.BuildSystem.OPENFL,
|
||||
[
|
||||
Project.Platform.FLASH,
|
||||
Project.Platform.HTML5,
|
||||
Project.Platform.LINUX,
|
||||
Project.Platform.WINDOWS,
|
||||
Project.Platform.ANDROID,
|
||||
Project.BuildSystem.OPENFL,
|
||||
[
|
||||
Project.Platform.FLASH,
|
||||
Project.Platform.HTML5,
|
||||
Project.Platform.LINUX,
|
||||
Project.Platform.WINDOWS,
|
||||
Project.Platform.ANDROID,
|
||||
],
|
||||
config.branch({
|
||||
name: "app",
|
||||
sources: ["src-gen/haxe", "src/common/haxe", "src/app/haxe"],
|
||||
android: [
|
||||
{
|
||||
path: "dependencies/android",
|
||||
extensions: ["ru.m.android.FileUtil"],
|
||||
},
|
||||
],
|
||||
config.branch({
|
||||
name: 'app',
|
||||
sources: [
|
||||
'src-gen/haxe',
|
||||
'src/common/haxe',
|
||||
'src/app/haxe',
|
||||
],
|
||||
android: [{
|
||||
path: 'dependencies/android',
|
||||
extensions: ['ru.m.android.FileUtil'],
|
||||
}],
|
||||
assets: [
|
||||
'src/app/resources',
|
||||
],
|
||||
main: 'ru.m.puzzlez.PuzzlezApp',
|
||||
meta: {
|
||||
width: 1280,
|
||||
height: 768,
|
||||
},
|
||||
flags: [
|
||||
'app',
|
||||
]
|
||||
}),
|
||||
assets: ["src/app/resources"],
|
||||
main: "ru.m.puzzlez.PuzzlezApp",
|
||||
meta: {
|
||||
width: 1280,
|
||||
height: 768,
|
||||
},
|
||||
flags: ["app"],
|
||||
}),
|
||||
).bind(module, gulp);
|
||||
|
||||
const server = new Project(
|
||||
Project.BuildSystem.HAXE,
|
||||
[
|
||||
Project.Platform.NEKO,
|
||||
Project.Platform.CPP,
|
||||
],
|
||||
config.branch({
|
||||
name: 'server',
|
||||
sources: [
|
||||
'src-gen/haxe',
|
||||
'src/common/haxe',
|
||||
'src/server/haxe',
|
||||
],
|
||||
main: 'ru.m.puzzlez.PuzzlezServer',
|
||||
})
|
||||
Project.BuildSystem.HAXE,
|
||||
[Project.Platform.NEKO, Project.Platform.CPP],
|
||||
config.branch({
|
||||
name: "server",
|
||||
sources: ["src-gen/haxe", "src/common/haxe", "src/server/haxe"],
|
||||
main: "ru.m.puzzlez.PuzzlezServer",
|
||||
}),
|
||||
).bind(module, gulp);
|
||||
|
||||
module.exports.publish = publish(packageInfo.name, packageInfo.version, Config.PublishDir, Config.PublishUrl);
|
||||
module.exports.publish = publish(
|
||||
packageInfo.name,
|
||||
packageInfo.version,
|
||||
Config.PublishDir,
|
||||
Config.PublishUrl,
|
||||
);
|
||||
|
||||
const defaultSeries = [
|
||||
exports.clean,
|
||||
exports.generate,
|
||||
module.exports['app:flash:build'],
|
||||
module.exports['app:flash:html'],
|
||||
module.exports['app:html5:build'],
|
||||
exports.clean,
|
||||
exports.generate,
|
||||
module.exports["app:flash:build"],
|
||||
module.exports["app:flash:html"],
|
||||
module.exports["app:html5:build"],
|
||||
];
|
||||
|
||||
if (System.isLinux) {
|
||||
defaultSeries.push(
|
||||
module.exports['app:linux:build'],
|
||||
module.exports['app:linux:archive'],
|
||||
module.exports['app:linux:deb'],
|
||||
defaultSeries.push(
|
||||
module.exports["app:linux:build"],
|
||||
module.exports["app:linux:archive"],
|
||||
module.exports["app:linux:deb"],
|
||||
|
||||
module.exports['app:android:build'],
|
||||
);
|
||||
module.exports["app:android:build"],
|
||||
);
|
||||
}
|
||||
|
||||
if (System.isWindows) {
|
||||
defaultSeries.push(
|
||||
module.exports['app:windows:build'],
|
||||
module.exports['app:windows:archive'],
|
||||
module.exports['app:windows:installer'],
|
||||
);
|
||||
defaultSeries.push(
|
||||
module.exports["app:windows:build"],
|
||||
module.exports["app:windows:archive"],
|
||||
module.exports["app:windows:installer"],
|
||||
);
|
||||
}
|
||||
|
||||
defaultSeries.push(
|
||||
exports.publish,
|
||||
);
|
||||
defaultSeries.push(exports.publish);
|
||||
|
||||
module.exports.default = gulp.series(defaultSeries);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"indentation": {
|
||||
"character": " "
|
||||
},
|
||||
"wrapping": {
|
||||
"maxLineLength": 120
|
||||
}
|
||||
}
|
||||
|
||||
4
package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "puzzlez",
|
||||
"version": "0.4.4",
|
||||
"version": "0.6.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.4.4",
|
||||
"version": "0.6.1",
|
||||
"devDependencies": {
|
||||
"dateformat": "^3.0.3",
|
||||
"fs-extra": "^10.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "puzzlez",
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.1",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"dateformat": "^3.0.3",
|
||||
|
||||
@@ -1,46 +1,53 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
"path": ".",
|
||||
},
|
||||
],
|
||||
"settings": {
|
||||
"haxe.executable": {
|
||||
"path": "/home/shmyga/sdk/haxe/4.2.5/haxe",
|
||||
"env": {
|
||||
"HAXE_STD_PATH": "/home/shmyga/sdk/haxe/4.2.5/std"
|
||||
}
|
||||
"HAXE_STD_PATH": "/home/shmyga/sdk/haxe/4.2.5/std",
|
||||
},
|
||||
},
|
||||
"haxe.configurations": [["build/app/flash/haxe/debug.hxml"]],
|
||||
"haxe.displayServer": {
|
||||
"arguments": [
|
||||
//"-v"
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
"extensions": {
|
||||
"recommendations": ["nadako.vshaxe"]
|
||||
"recommendations": ["nadako.vshaxe"],
|
||||
},
|
||||
"launch": {
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"args": ["app:flash:test"],
|
||||
"name": "app:flash:test",
|
||||
"args": ["${input:target}"],
|
||||
"name": "${input:target}",
|
||||
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
|
||||
"request": "launch",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"type": "node"
|
||||
"type": "node",
|
||||
"consoleTitle": "${input:target}",
|
||||
},
|
||||
{
|
||||
"args": ["server:cpp:test"],
|
||||
"name": "server:cpp:test",
|
||||
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
|
||||
"request": "launch",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"type": "node"
|
||||
}
|
||||
],
|
||||
"compounds": []
|
||||
}
|
||||
"inputs": [
|
||||
{
|
||||
"id": "target",
|
||||
"description": "Please enter target name",
|
||||
"options": [
|
||||
"app:flash:test",
|
||||
"app:html5:test",
|
||||
"app:linux:test",
|
||||
"server:cpp:test",
|
||||
],
|
||||
"type": "pickString",
|
||||
"default": "app:flash:test",
|
||||
},
|
||||
],
|
||||
"compounds": [],
|
||||
},
|
||||
}
|
||||
|
||||
7
scripts/build
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd "$(dirname $(dirname "$0"))" || exit
|
||||
|
||||
source .env
|
||||
mkdir -p "$SDK_PATH" "$PUBLISH_PATH" "$BUILD_PATH" "$TARGET_PATH" "src-gen"
|
||||
docker compose run --rm --user $(id -u):$(id -g) --build --remove-orphans builder
|
||||
45
scripts/docker-action
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd "$(dirname $(dirname "$0"))" || exit
|
||||
|
||||
. .env
|
||||
|
||||
build () {
|
||||
echo "build: $1"
|
||||
. "$1/.env"
|
||||
for PROJECT in "${DOCKER_PROJECTS[@]}"; do
|
||||
IFS=: read -r PROJECT_NAME PROJECT_TARGET <<< "$PROJECT"
|
||||
ARGS=("build")
|
||||
for ARG in ${DOCKER_ARGS[@]}; do
|
||||
ARGS+=("--build-arg" "$ARG")
|
||||
done
|
||||
if [ -n "$PROJECT_TARGET" ]; then
|
||||
ARGS+=("--target" "$PROJECT_TARGET")
|
||||
fi
|
||||
ARGS+=("-t" "$DOCKER_GROUP/$PROJECT_NAME" ".")
|
||||
ARGS+=("-f" "$1/Dockerfile")
|
||||
echo "${ARGS[@]}"
|
||||
docker "${ARGS[@]}"
|
||||
done
|
||||
}
|
||||
|
||||
publish () {
|
||||
echo "publish: $1"
|
||||
. "$1/.env"
|
||||
for PROJECT in "${DOCKER_PROJECTS[@]}"; do
|
||||
IFS=: read -r PROJECT_NAME PROJECT_TARGET <<< "$PROJECT"
|
||||
docker tag $DOCKER_GROUP/$PROJECT_NAME $DOCKER_ROOT/$PROJECT_NAME:$VERSION
|
||||
docker tag $DOCKER_GROUP/$PROJECT_NAME $DOCKER_ROOT/$PROJECT_NAME:latest
|
||||
docker push $DOCKER_ROOT/$PROJECT_NAME:$VERSION
|
||||
docker push $DOCKER_ROOT/$PROJECT_NAME:latest
|
||||
done
|
||||
}
|
||||
|
||||
DEFAULT_TARGETS="."
|
||||
TARGETS="${@-$DEFAULT_TARGETS}"
|
||||
|
||||
DOCKER_ACTION="${DOCKER_ACTION-build}"
|
||||
|
||||
for TARGET in $TARGETS; do
|
||||
$DOCKER_ACTION "$TARGET"
|
||||
done
|
||||
35
scripts/publish
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd "$(dirname $(dirname "$0"))" || exit
|
||||
source .env
|
||||
|
||||
VERSION=$(grep -m 1 'version' ./package.json | grep -oP '"version"\s*:\s*"\K\d+\.\d+\.\d+')
|
||||
|
||||
PACKAGES=(
|
||||
"android/${PROJECT}_${VERSION}.apk"
|
||||
"debian/${PROJECT}_${VERSION}_all.deb"
|
||||
"archive/${PROJECT}_${VERSION}_linux.tar.gz"
|
||||
"archive/${PROJECT}_${VERSION}_win.zip"
|
||||
"installer/${PROJECT}_${VERSION}.exe"
|
||||
)
|
||||
|
||||
for PACKAGE in "${PACKAGES[@]}"
|
||||
do
|
||||
if [ -f "${PUBLISH_PATH}/${PACKAGE}" ]; then
|
||||
PACKAGE_NAME=$(basename "$PACKAGE")
|
||||
echo "publish: $PACKAGE"
|
||||
curl --user "${PUBLISH_USER}:${PUBLISH_PASSWORD}" -X DELETE \
|
||||
"${REPO}/generic/${PROJECT}/${VERSION}/${PACKAGE_NAME}"
|
||||
curl --user "${PUBLISH_USER}:${PUBLISH_PASSWORD}" \
|
||||
--upload-file "${PUBLISH_PATH}/${PACKAGE}" \
|
||||
"${REPO}/generic/${PROJECT}/${VERSION}/${PACKAGE_NAME}"
|
||||
|
||||
if [[ "$PACKAGE" == *.deb ]]; then
|
||||
curl --user "${PUBLISH_USER}:${PUBLISH_PASSWORD}" -X DELETE \
|
||||
"${REPO}/debian/pool/noble/main/${PROJECT}/${VERSION}/all"
|
||||
curl --user "${PUBLISH_USER}:${PUBLISH_PASSWORD}" \
|
||||
--upload-file "${PUBLISH_PATH}/${PACKAGE}" \
|
||||
"${REPO}/debian/pool/noble/main/upload"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -8,6 +8,7 @@ import ru.m.puzzlez.render.part.IPartBuilder;
|
||||
import ru.m.puzzlez.settings.Settings;
|
||||
import ru.m.puzzlez.source.AssetImageSource;
|
||||
import ru.m.puzzlez.source.FileImageSource;
|
||||
import ru.m.puzzlez.source.NginxImageSource;
|
||||
import ru.m.puzzlez.source.PixabayImageSource;
|
||||
import ru.m.puzzlez.source.UnsplashImageSource;
|
||||
import ru.m.puzzlez.storage.GameStorage;
|
||||
@@ -25,8 +26,9 @@ class PuzzlezApp {
|
||||
GameStorage;
|
||||
sourceBundle.register(new AssetImageSource());
|
||||
sourceBundle.register(new FileImageSource());
|
||||
sourceBundle.register(new PixabayImageSource());
|
||||
sourceBundle.register(new UnsplashImageSource());
|
||||
sourceBundle.register(new PixabayImageSource(CompilationOption.get("PIXABAY_KEY")));
|
||||
sourceBundle.register(new UnsplashImageSource(CompilationOption.get("UNSPLASH_KEY")));
|
||||
sourceBundle.register(new NginxImageSource("https://home.shmyga.ru/puzzlez/"));
|
||||
L.push(new TraceLogger());
|
||||
updater = new Updater(Const.instance.VERSION, "https://shmyga.ru/repo/puzzlez/packages.json");
|
||||
var app = new App();
|
||||
|
||||
@@ -11,19 +11,25 @@ import ru.m.skin.ButtonSVGSkin;
|
||||
|
||||
class PuzzlezTheme extends Theme {
|
||||
private static var ICONS:Map<String, String> = [
|
||||
"close" => "times-circle-solid.svg",
|
||||
"setting" => "cog-solid.svg",
|
||||
"image" => "image-polaroid.svg",
|
||||
"lock" => "lock-alt-solid.svg",
|
||||
"restore" => "window-restore-solid.svg",
|
||||
"compress" => "compress-solid.svg",
|
||||
"expand" => "expand-solid.svg",
|
||||
"spread" => "clone.svg",
|
||||
"close" => "close-circle.svg",
|
||||
"setting" => "cog.svg",
|
||||
"image" => "image.svg",
|
||||
"lock" => "lock.svg",
|
||||
"lock-open" => "lock-open.svg",
|
||||
"restore" => "window-restore.svg",
|
||||
"compress" => "arrow-collapse-all.svg",
|
||||
"expand" => "arrow-expand-all.svg",
|
||||
"shuffle" => "shuffle.svg",
|
||||
"spread" => "format-align-justify.svg",
|
||||
];
|
||||
|
||||
public function new() {
|
||||
super({embed: true}, {light: "gray"}, {base: "4h"});
|
||||
register(new Style("frame", ["geometry.padding" => Box.fromFloat(8),]));
|
||||
register(new Style("button.source", [
|
||||
"geometry.width" => SizeValue.fromString("30%"),
|
||||
"geometry.height" => SizeValue.fromString("40%"),
|
||||
], "button"));
|
||||
register(new Style("view", [
|
||||
"skin.background.color" => colors.light,
|
||||
"skin.border.color" => colors.border,
|
||||
@@ -37,6 +43,7 @@ class PuzzlezTheme extends Theme {
|
||||
"geometry.height" => SizeValue.fromString("8h"),
|
||||
"skin" => function() return new ButtonSVGSkin(),
|
||||
"skin.color" => colors.light,
|
||||
"skin.svgScale" => 16.0,
|
||||
]));
|
||||
for (key in ICONS.keys()) {
|
||||
register(new Style('icon.${key}', ["skin.svg" => Assets.getText('resources/icon/${ICONS.get(key)}'),]));
|
||||
|
||||
@@ -7,4 +7,5 @@ import ru.m.puzzlez.proto.game.ImageId;
|
||||
interface ImageSource extends DataSource<ImageId> {
|
||||
public var id(default, never):String;
|
||||
public function load(id:String, thumb:Bool = false):Promise<ImageValue>;
|
||||
public function getCategories():Null<Promise<Array<String>>>;
|
||||
}
|
||||
|
||||
@@ -101,8 +101,8 @@ class SpritePartView extends PartView {
|
||||
|
||||
if (playerId != null) {
|
||||
var rect = cast(part.rect, RectangleExt).clone();
|
||||
rect.x += (image.width - size.x) / 2;
|
||||
rect.y += (image.height - size.y) / 2;
|
||||
rect.x = (image.width - size.x) / 2;
|
||||
rect.y = (image.height - size.y) / 2;
|
||||
var path = builder.build(rect, part.bounds);
|
||||
graphics.lineStyle(4, 0xffff00, 0.3);
|
||||
path.draw(graphics);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ru.m.puzzlez.settings;
|
||||
|
||||
import hw.storage.SharedObjectStorage;
|
||||
import ru.m.puzzlez.proto.game.ImageId;
|
||||
import ru.m.puzzlez.render.Background;
|
||||
|
||||
@:provide class Settings extends SharedObjectStorage {
|
||||
@@ -10,8 +11,12 @@ import ru.m.puzzlez.render.Background;
|
||||
|
||||
public var background(get, set):Background;
|
||||
|
||||
private function defaultBackground():Background {
|
||||
return Background.IMAGE(new ImageId().setSource('asset').setId('resources/texture/pool-table.png'));
|
||||
}
|
||||
|
||||
private inline function get_background():Background {
|
||||
return exists(BACKGROUND_KEY) ? read(BACKGROUND_KEY) : NONE;
|
||||
return exists(BACKGROUND_KEY) ? read(BACKGROUND_KEY) : this.defaultBackground();
|
||||
}
|
||||
|
||||
private inline function set_background(value:Background):Background {
|
||||
@@ -22,7 +27,7 @@ import ru.m.puzzlez.render.Background;
|
||||
public var locked(get, set):Bool;
|
||||
|
||||
private inline function get_locked():Bool {
|
||||
return exists(LOCKED_KEY) ? read(LOCKED_KEY) : false;
|
||||
return exists(LOCKED_KEY) ? read(LOCKED_KEY) : true;
|
||||
}
|
||||
|
||||
private inline function set_locked(value:Bool):Bool {
|
||||
|
||||
@@ -13,6 +13,7 @@ class AssetImageSource implements ImageSource {
|
||||
|
||||
private var _data:Array<ImageId>;
|
||||
private var data(get, null):Array<ImageId>;
|
||||
private var key:String;
|
||||
|
||||
private function get_data():Array<ImageId> {
|
||||
if (_data == null) {
|
||||
@@ -21,11 +22,14 @@ class AssetImageSource implements ImageSource {
|
||||
return _data;
|
||||
}
|
||||
|
||||
public function new() {}
|
||||
public function new(key:String = "resources/image") {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
private function resolveData():Array<ImageId> {
|
||||
var keyLength = this.key.length;
|
||||
return [
|
||||
for (name in Assets.list(AssetType.IMAGE).filter((name:String) -> name.substr(0, 15) == "resources/image"))
|
||||
for (name in Assets.list(AssetType.IMAGE).filter((name:String) -> name.substr(0, keyLength) == this.key))
|
||||
new ImageId().setSource(id).setId(name)
|
||||
];
|
||||
}
|
||||
@@ -41,4 +45,8 @@ class AssetImageSource implements ImageSource {
|
||||
public function load(id:String, thumb:Bool = false):Promise<ImageValue> {
|
||||
return Promise.promise(ImageValue.BITMAP(Assets.getBitmapData(id)));
|
||||
}
|
||||
|
||||
public function getCategories():Null<Promise<Array<String>>> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,8 @@ class FileImageSource implements ImageSource {
|
||||
public function load(id:String, thumb:Bool = false):Promise<ImageValue> {
|
||||
return storage.get(id).then(bytes -> ImageValue.BYTES(bytes));
|
||||
}
|
||||
|
||||
public function getCategories():Null<Promise<Array<String>>> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
78
src/app/haxe/ru/m/puzzlez/source/NginxImageSource.hx
Normal file
@@ -0,0 +1,78 @@
|
||||
package ru.m.puzzlez.source;
|
||||
|
||||
import hw.net.JsonLoader;
|
||||
import promhx.Promise;
|
||||
import ru.m.data.DataSource;
|
||||
import ru.m.puzzlez.core.ImageSource;
|
||||
import ru.m.puzzlez.core.ImageValue;
|
||||
import ru.m.puzzlez.proto.game.ImageId;
|
||||
|
||||
enum abstract NginxResponseItemType(String) from String to String {
|
||||
var FILE = "file";
|
||||
var DIRECTORY = "directory";
|
||||
}
|
||||
|
||||
typedef NginxResponseItem = {
|
||||
var name:String;
|
||||
var type:NginxResponseItemType;
|
||||
var mtime:String;
|
||||
var size:Int;
|
||||
}
|
||||
|
||||
typedef NginxResponse = Array<NginxResponseItem>;
|
||||
|
||||
class NginxImageSource implements ImageSource {
|
||||
public var id(default, never):String = "nginx";
|
||||
|
||||
private var baseUrl:String;
|
||||
|
||||
public function new(baseUrl:String) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
private function buildUrl(name:String):String {
|
||||
return baseUrl + name;
|
||||
}
|
||||
|
||||
public function getPage(page:Page):Promise<DataPage<ImageId>> {
|
||||
var category = page.filter.get("category");
|
||||
return new JsonLoader<NginxResponse>().GET(category != null ? this.baseUrl + category + "/" : this.baseUrl)
|
||||
.then((response:NginxResponse) -> {
|
||||
var data:Array<ImageId> = [];
|
||||
for (item in response) {
|
||||
if (item.type == NginxResponseItemType.FILE) {
|
||||
var itemId = category != null ? category + "@" + item.name : item.name;
|
||||
data.push(new ImageId().setSource(id).setId(itemId));
|
||||
}
|
||||
}
|
||||
return {
|
||||
page: page,
|
||||
data: data,
|
||||
total: response.length,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function load(id:String, thumb:Bool = false):Promise<ImageValue> {
|
||||
var url = this.baseUrl + StringTools.replace(id, "@", "/");
|
||||
if (thumb) {
|
||||
var parts = url.split(".");
|
||||
var index = parts.length - 2;
|
||||
parts[index] = parts[index] + "-thumbnail";
|
||||
url = parts.join(".");
|
||||
}
|
||||
return Promise.promise(ImageValue.URL(url));
|
||||
}
|
||||
|
||||
public function getCategories():Null<Promise<Array<String>>> {
|
||||
return new JsonLoader<NginxResponse>().GET(this.baseUrl).then((response:NginxResponse) -> {
|
||||
var data:Array<String> = [];
|
||||
for (item in response) {
|
||||
if (item.type == NginxResponseItemType.DIRECTORY) {
|
||||
data.push(item.name);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -14,24 +14,24 @@ class PixabayImageSource implements ImageSource {
|
||||
|
||||
private static var imageUrlsCache:Map<String, String> = new Map();
|
||||
|
||||
public function new() {
|
||||
var key:String = CompilationOption.get("PIXABAY_KEY");
|
||||
public function new(key:String) {
|
||||
api = new PixabayApi(key);
|
||||
}
|
||||
|
||||
public function getPage(page:Page):Promise<DataPage<ImageId>> {
|
||||
return this.api.getPage(page.index + 1, page.count, page.filter.get("category")).then((response:PixabayResponse) -> {
|
||||
var data:Array<ImageId> = [];
|
||||
for (hit in response.hits) {
|
||||
imageUrlsCache.set('${hit.id}', hit.largeImageURL);
|
||||
data.push(new ImageId().setSource(id).setId(Std.string(hit.id)));
|
||||
}
|
||||
return {
|
||||
page: page,
|
||||
data: data,
|
||||
total: response.totalHits,
|
||||
}
|
||||
});
|
||||
return this.api.getPage(page.index + 1, page.count, page.filter.get("category"))
|
||||
.then((response:PixabayResponse) -> {
|
||||
var data:Array<ImageId> = [];
|
||||
for (hit in response.hits) {
|
||||
imageUrlsCache.set('${hit.id}', hit.largeImageURL);
|
||||
data.push(new ImageId().setSource(id).setId(Std.string(hit.id)));
|
||||
}
|
||||
return {
|
||||
page: page,
|
||||
data: data,
|
||||
total: response.totalHits,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function load(id:String, thumb:Bool = false):Promise<ImageValue> {
|
||||
@@ -50,4 +50,8 @@ class PixabayImageSource implements ImageSource {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function getCategories():Null<Promise<Array<String>>> {
|
||||
return Promise.promise(AbstractEnumTools.getValues(PixabayCategory));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +51,7 @@ class UnsplashImageSource implements ImageSource {
|
||||
|
||||
private static var resolver:ImageResolver;
|
||||
|
||||
public function new() {
|
||||
var key:String = CompilationOption.get("UNSPLASH_KEY");
|
||||
public function new(key:String) {
|
||||
api = new UnsplashApi(key);
|
||||
resolver = new ImageResolver((imageId, thumb) -> {
|
||||
return api.get(imageId).then(data -> thumb ? data.urls.small : data.urls.regular);
|
||||
@@ -60,22 +59,28 @@ class UnsplashImageSource implements ImageSource {
|
||||
}
|
||||
|
||||
public function getPage(page:Page):Promise<DataPage<ImageId>> {
|
||||
return this.api.getPage(page.index + 1, page.count, page.filter.get("category")).then((response:UnsplashResponse) -> {
|
||||
var data:Array<ImageId> = [];
|
||||
for (image in response.results) {
|
||||
resolver.setValue(image.id, image.urls.small, true);
|
||||
resolver.setValue(image.id, image.urls.regular);
|
||||
data.push(new ImageId().setSource(id).setId(image.id));
|
||||
}
|
||||
return {
|
||||
page: page,
|
||||
data: data,
|
||||
total: response.total,
|
||||
}
|
||||
});
|
||||
return this.api.getPage(page.index + 1, page.count, page.filter.get("category"))
|
||||
.then((response:UnsplashResponse) -> {
|
||||
var data:Array<ImageId> = [];
|
||||
for (image in response.results) {
|
||||
resolver.setValue(image.id, image.urls.small, true);
|
||||
resolver.setValue(image.id, image.urls.regular);
|
||||
data.push(new ImageId().setSource(id).setId(image.id));
|
||||
}
|
||||
return {
|
||||
page: page,
|
||||
data: data,
|
||||
total: response.total,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function load(id:String, thumb:Bool = false):Promise<ImageValue> {
|
||||
return resolver.resolve(id, thumb);
|
||||
}
|
||||
|
||||
public function getCategories():Null<Promise<Array<String>>> {
|
||||
// TODO: unsplash categories list
|
||||
return Promise.promise([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import ru.m.puzzlez.view.popup.PreviewPopup;
|
||||
}
|
||||
|
||||
override public function onShow(state:GameState):Void {
|
||||
L.d("Frame", '$ID: ${state.preset.image.source}:${state.preset.image.id}');
|
||||
onHide();
|
||||
if (state.online) {
|
||||
// game = new NetworkGame(state);
|
||||
|
||||
@@ -22,11 +22,13 @@ views:
|
||||
settings.locked = render.manager.locked;
|
||||
cast(button, hw.view.form.ToggleButtonView).on = !render.manager.locked;
|
||||
}
|
||||
visible: false
|
||||
- $type: hw.view.form.ButtonView
|
||||
style: icon.restore
|
||||
+onPress: ~render.manager.reset()
|
||||
visible: false
|
||||
- $type: hw.view.form.ButtonView
|
||||
style: icon.spread
|
||||
style: icon.shuffle
|
||||
+onPress: ~shuffle()
|
||||
- $type: hw.view.form.ButtonView
|
||||
style: icon.spread
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef GameListConfig = {
|
||||
}
|
||||
|
||||
override public function onShow(data:GameListConfig):Void {
|
||||
L.d("Frame", '$ID: $data');
|
||||
games.reset();
|
||||
if (data != null) {
|
||||
header.text = data.title;
|
||||
|
||||
@@ -23,11 +23,18 @@ typedef ImageListConfig = {
|
||||
@:provide var switcher:FrameSwitcher;
|
||||
@:provide var sourceBundle:ImageSourceBundle;
|
||||
|
||||
private var config:ImageListConfig;
|
||||
|
||||
public function new() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
override public function onShow(data:ImageListConfig):Void {
|
||||
if (data == null) {
|
||||
data = config;
|
||||
}
|
||||
L.d("Frame", '$ID: $data');
|
||||
config = data;
|
||||
images.reset();
|
||||
if (data != null) {
|
||||
header.text = data.title;
|
||||
|
||||
@@ -48,6 +48,7 @@ import ru.m.puzzlez.view.common.PresetView;
|
||||
|
||||
override public function onShow(data:ImageId):Void {
|
||||
super.onShow(data);
|
||||
L.d("Frame", '$ID: ${data.source}:${data.id}');
|
||||
imageId = data;
|
||||
selectSize(sizesView.data[sizesView.data.length - 1]);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import hw.view.data.DataView;
|
||||
import hw.view.form.ButtonView;
|
||||
import hw.view.frame.FrameSwitcher;
|
||||
import hw.view.frame.FrameView;
|
||||
import ru.m.api.PixabayApi;
|
||||
import ru.m.puzzlez.FileUtil;
|
||||
import ru.m.puzzlez.image.ImageSourceBundle;
|
||||
import ru.m.puzzlez.proto.game.GameStatus;
|
||||
import ru.m.puzzlez.storage.FileStorage;
|
||||
import ru.m.puzzlez.storage.GameStorage;
|
||||
@@ -27,24 +27,41 @@ import ru.m.update.Updater;
|
||||
|
||||
@:provide var fileStorage:FileStorage;
|
||||
@:provide var gameStorage:GameStorage;
|
||||
@:provide var sourceBundle:ImageSourceBundle;
|
||||
|
||||
private var fileSource:ImageListConfig = {title: "Files", sourceId: "file"};
|
||||
private var startedGames:GameListConfig = {title: "Started", source: gameStorage, filter: ["status" => GameStatus.STARTED]};
|
||||
private var completedGames:GameListConfig = {title: "Completed", source: gameStorage, filter: ["status" => GameStatus.COMPLETE]};
|
||||
private var startedGames:GameListConfig = {
|
||||
title: "Started",
|
||||
source: gameStorage,
|
||||
filter: ["status" => GameStatus.STARTED]
|
||||
};
|
||||
private var completedGames:GameListConfig = {
|
||||
title: "Completed",
|
||||
source: gameStorage,
|
||||
filter: ["status" => GameStatus.COMPLETE]
|
||||
};
|
||||
|
||||
public function new() {
|
||||
super(ID);
|
||||
var data:Array<ImageListConfig> = [];
|
||||
// data.push({title: "Assets", sourceId: "asset"});
|
||||
data.push(fileSource);
|
||||
for (type in AbstractEnumTools.getValues(PixabayCategory)) {
|
||||
data.push({title: type, sourceId: "unsplash", filter: ["category" => type]});
|
||||
}
|
||||
sourceBundle.get(fileSource.sourceId).getPage({index: 0, count: 0}).then((page) -> {
|
||||
if (page.total > 0) {
|
||||
data.unshift(fileSource);
|
||||
sources.data = data;
|
||||
}
|
||||
});
|
||||
sources.data = data;
|
||||
sourceBundle.get("nginx").getCategories().then((categories) -> {
|
||||
for (category in categories) {
|
||||
data.push({title: category, sourceId: "nginx", filter: ["category" => category]});
|
||||
}
|
||||
sources.data = data;
|
||||
});
|
||||
}
|
||||
|
||||
private function sourceViewFactory(index:Int, source:ImageListConfig):ButtonView {
|
||||
var result = new ButtonView();
|
||||
result.style = "button.source";
|
||||
result.text = source.title;
|
||||
return result;
|
||||
}
|
||||
@@ -62,6 +79,7 @@ import ru.m.update.Updater;
|
||||
}
|
||||
|
||||
override public function onShow(data:Dynamic):Void {
|
||||
L.d("Frame", '$ID');
|
||||
appUpdater.check().then((info:Null<PackageInfo>) -> {
|
||||
if (info != null) {
|
||||
updateButton.visible = true;
|
||||
@@ -74,9 +92,11 @@ import ru.m.update.Updater;
|
||||
private function refresh():Void {
|
||||
gameStorage.getIndexPage({index: 0, count: 0, filter: startedGames.filter}).then(response -> {
|
||||
startedButton.text = response.total > 0 ? 'Started (${response.total})' : 'Started';
|
||||
startedButton.disabled = response.total == 0;
|
||||
});
|
||||
gameStorage.getIndexPage({index: 0, count: 0, filter: completedGames.filter}).then(response -> {
|
||||
completedButton.text = response.total > 0 ? 'Completed (${response.total})' : 'Completed';
|
||||
completedButton.disabled = response.total == 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using hw.color.ColorUtil;
|
||||
@:style(null) public var svg:String;
|
||||
@:style(0) public var color:Null<Color>;
|
||||
@:style(false) public var solid:Null<Bool>;
|
||||
@:style(0.8) public var svgScale:Null<Float>;
|
||||
|
||||
private var svgs:Map<ButtonState, SVG>;
|
||||
private var needUpdate:Bool;
|
||||
@@ -60,7 +61,7 @@ using hw.color.ColorUtil;
|
||||
graphics.lineStyle(2, color.multiply(1.5));
|
||||
}
|
||||
// ToDo: padding
|
||||
svg.render(graphics, 0, 0, Std.int(view.width * 0.8), Std.int(view.height * 0.8));
|
||||
svg.render(graphics, 0, 0, Std.int(view.width * this.svgScale), Std.int(view.height * this.svgScale));
|
||||
graphics.lineStyle();
|
||||
graphics.endFill();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package ru.m.storage;
|
||||
|
||||
import haxe.Unserializer;
|
||||
import flash.net.SharedObject;
|
||||
import haxe.Serializer;
|
||||
import haxe.Unserializer;
|
||||
import haxe.crypto.Md5;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.Serializer;
|
||||
import promhx.Promise;
|
||||
import ru.m.data.DataSource;
|
||||
|
||||
@@ -124,7 +124,8 @@ class SharedObjectDataStorage<D, I> implements DataStorage<D, I> {
|
||||
}
|
||||
}
|
||||
applyOrder(page.order, values);
|
||||
var result:Array<I> = values.slice(page.index * page.count, page.index * page.count + page.count).map(value -> value.id);
|
||||
var result:Array<I> = values.slice(page.index * page.count, page.index * page.count + page.count)
|
||||
.map(value -> value.id);
|
||||
return Promise.promise({
|
||||
page: page,
|
||||
total: values.length,
|
||||
@@ -138,7 +139,7 @@ class SharedObjectDataStorage<D, I> implements DataStorage<D, I> {
|
||||
return {
|
||||
page: indexPage.page,
|
||||
total: indexPage.total,
|
||||
data: data,
|
||||
data: data.filter((item:D) -> item != null),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="arrow-alt-circle-left" class="svg-inline--fa fa-arrow-alt-circle-left fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zm116-292H256v-70.9c0-10.7-13-16.1-20.5-8.5L121.2 247.5c-4.7 4.7-4.7 12.2 0 16.9l114.3 114.9c7.6 7.6 20.5 2.2 20.5-8.5V300h116c6.6 0 12-5.4 12-12v-64c0-6.6-5.4-12-12-12z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 503 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="arrow-alt-circle-right" class="svg-inline--fa fa-arrow-alt-circle-right fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zM140 300h116v70.9c0 10.7 13 16.1 20.5 8.5l114.3-114.9c4.7-4.7 4.7-12.2 0-16.9l-114.3-115c-7.6-7.6-20.5-2.2-20.5 8.5V212H140c-6.6 0-12 5.4-12 12v64c0 6.6 5.4 12 12 12z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 499 B |
4
src/app/resources/icon/arrow-collapse-all.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M19.5,3.09L20.91,4.5L16.41,9H20V11H13V4H15V7.59L19.5,3.09M20.91,19.5L19.5,20.91L15,16.41V20H13V13H20V15H16.41L20.91,19.5M4.5,3.09L9,7.59V4H11V11H4V9H7.59L3.09,4.5L4.5,3.09M3.09,19.5L7.59,15H4V13H11V20H9V16.41L4.5,20.91L3.09,19.5Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 336 B |
4
src/app/resources/icon/arrow-expand-all.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M9.5,13.09L10.91,14.5L6.41,19H10V21H3V14H5V17.59L9.5,13.09M10.91,9.5L9.5,10.91L5,6.41V10H3V3H10V5H6.41L10.91,9.5M14.5,13.09L19,17.59V14H21V21H14V19H17.59L13.09,14.5L14.5,13.09M13.09,9.5L17.59,5H14V3H21V10H19V6.41L14.5,10.91L13.09,9.5Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 341 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="bars" class="svg-inline--fa fa-bars fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 569 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 464H288c8.8 0 16-7.2 16-16V384h48v64c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h64v48H64c-8.8 0-16 7.2-16 16V448c0 8.8 7.2 16 16 16zM224 304H448c8.8 0 16-7.2 16-16V64c0-8.8-7.2-16-16-16H224c-8.8 0-16 7.2-16 16V288c0 8.8 7.2 16 16 16zm-64-16V64c0-35.3 28.7-64 64-64H448c35.3 0 64 28.7 64 64V288c0 35.3-28.7 64-64 64H224c-35.3 0-64-28.7-64-64z"/></svg>
|
||||
|
Before Width: | Height: | Size: 604 B |
4
src/app/resources/icon/close-circle.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 307 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="cog" class="svg-inline--fa fa-cog fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
4
src/app/resources/icon/cog.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1014 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="compress" class="svg-inline--fa fa-compress fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M436 192H312c-13.3 0-24-10.7-24-24V44c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v84h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-276-24V44c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v84H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24zm0 300V344c0-13.3-10.7-24-24-24H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-84h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H312c-13.3 0-24 10.7-24 24v124c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 741 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="expand" class="svg-inline--fa fa-expand fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M0 180V56c0-13.3 10.7-24 24-24h124c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H64v84c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12zM288 44v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12V56c0-13.3-10.7-24-24-24H300c-6.6 0-12 5.4-12 12zm148 276h-40c-6.6 0-12 5.4-12 12v84h-84c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24V332c0-6.6-5.4-12-12-12zM160 468v-40c0-6.6-5.4-12-12-12H64v-84c0-6.6-5.4-12-12-12H12c-6.6 0-12 5.4-12 12v124c0 13.3 10.7 24 24 24h124c6.6 0 12-5.4 12-12z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 740 B |
3
src/app/resources/icon/format-align-justify.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M3,3H21V5H3V3M3,7H21V9H3V7M3,11H21V13H3V11M3,15H21V17H3V15M3,19H21V21H3V19Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 178 B |
@@ -1,6 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="image-polaroid" role="img"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-image-polaroid fa-w-14 fa-2x">
|
||||
<path fill="currentColor"
|
||||
d="M128 192a32 32 0 1 0-32-32 32 32 0 0 0 32 32zM416 32H32A32 32 0 0 0 0 64v384a32 32 0 0 0 32 32h384a32 32 0 0 0 32-32V64a32 32 0 0 0-32-32zm-32 320H64V96h320zM268.8 209.07a16 16 0 0 0-25.6 0l-49.32 65.75L173.31 244a16 16 0 0 0-26.62 0L96 320h256z"
|
||||
class=""></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 540 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="image" class="svg-inline--fa fa-image fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 564 B |
4
src/app/resources/icon/image.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M8.5,13.5L11,16.5L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 222 B |
@@ -1,6 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="lock-alt" role="img"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" class="svg-inline--fa fa-lock-alt fa-w-14 fa-2x">
|
||||
<path fill="currentColor"
|
||||
d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zM264 392c0 22.1-17.9 40-40 40s-40-17.9-40-40v-48c0-22.1 17.9-40 40-40s40 17.9 40 40v48zm32-168H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"
|
||||
class=""></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 582 B |
4
src/app/resources/icon/lock-open.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10A2,2 0 0,1 6,8H15V6A3,3 0 0,0 12,3A3,3 0 0,0 9,6H7A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,17A2,2 0 0,0 14,15A2,2 0 0,0 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 328 B |
4
src/app/resources/icon/lock.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 342 B |
4
src/app/resources/icon/shuffle.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M14.83,13.41L13.42,14.82L16.55,17.95L14.5,20H20V14.5L17.96,16.54L14.83,13.41M14.5,4L16.54,6.04L4,18.59L5.41,20L17.96,7.46L20,9.5V4M10.59,9.17L5.41,4L4,5.41L9.17,10.58L10.59,9.17Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 285 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="times-circle" class="svg-inline--fa fa-times-circle fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 619 B |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="window-close" class="svg-inline--fa fa-window-close fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-83.6 290.5c4.8 4.8 4.8 12.6 0 17.4l-40.5 40.5c-4.8 4.8-12.6 4.8-17.4 0L256 313.3l-66.5 67.1c-4.8 4.8-12.6 4.8-17.4 0l-40.5-40.5c-4.8-4.8-4.8-12.6 0-17.4l67.1-66.5-67.1-66.5c-4.8-4.8-4.8-12.6 0-17.4l40.5-40.5c4.8-4.8 12.6-4.8 17.4 0l66.5 67.1 66.5-67.1c4.8-4.8 12.6-4.8 17.4 0l40.5 40.5c4.8 4.8 4.8 12.6 0 17.4L313.3 256l67.1 66.5z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 681 B |
@@ -1,6 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="window-restore" role="img"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-window-restore fa-w-16 fa-2x">
|
||||
<path fill="currentColor"
|
||||
d="M512 48v288c0 26.5-21.5 48-48 48h-48V176c0-44.1-35.9-80-80-80H128V48c0-26.5 21.5-48 48-48h288c26.5 0 48 21.5 48 48zM384 176v288c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V176c0-26.5 21.5-48 48-48h288c26.5 0 48 21.5 48 48zm-68 28c0-6.6-5.4-12-12-12H76c-6.6 0-12 5.4-12 12v52h252v-52z"
|
||||
class=""></path>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 580 B |
3
src/app/resources/icon/window-restore.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M4,8H8V4H20V16H16V20H4V8M16,8V14H18V6H10V8H16M6,12V18H14V12H6Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 165 B |