diff --git a/package-lock.json b/package-lock.json index 6ece0030e..bff08c78b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { + "@radix-ui/react-dialog": "^1.0.5", "@xmldom/xmldom": "^0.8.10", "classnames": "^2.5.1", "commonmark": "^0.30.0", @@ -3895,6 +3896,329 @@ "integrity": "sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==", "dev": true }, + "node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@redux-devtools/extension": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", @@ -5983,6 +6307,17 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/aria-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", + "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -12500,6 +12835,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -14299,6 +14642,14 @@ "node": ">= 0.10" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/inversify": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.2.tgz", @@ -21546,6 +21897,51 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", + "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-router": { "version": "6.21.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz", @@ -21576,6 +21972,28 @@ "react-dom": ">=16.8" } }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-svg-core": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/react-svg-core/-/react-svg-core-3.0.3.tgz", diff --git a/package.json b/package.json index 7f68f2aef..bdfa5f408 100644 --- a/package.json +++ b/package.json @@ -251,6 +251,7 @@ } }, "dependencies": { + "@radix-ui/react-dialog": "^1.0.5", "@xmldom/xmldom": "^0.8.10", "classnames": "^2.5.1", "commonmark": "^0.30.0", diff --git a/src/renderer/assets/icons/SaveAs-icon.svg b/src/renderer/assets/icons/SaveAs-icon.svg new file mode 100644 index 000000000..0f6087715 --- /dev/null +++ b/src/renderer/assets/icons/SaveAs-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/renderer/assets/icons/addTag-icon.svg b/src/renderer/assets/icons/addTag-icon.svg new file mode 100644 index 000000000..ecd0500d6 --- /dev/null +++ b/src/renderer/assets/icons/addTag-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/chevron-down.svg b/src/renderer/assets/icons/chevron-down.svg index 1f0b8bc70..38e033c8c 100644 --- a/src/renderer/assets/icons/chevron-down.svg +++ b/src/renderer/assets/icons/chevron-down.svg @@ -1,3 +1,4 @@ - - + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/chevron-up.svg b/src/renderer/assets/icons/chevron-up.svg new file mode 100644 index 000000000..3e06aada7 --- /dev/null +++ b/src/renderer/assets/icons/chevron-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/renderer/assets/icons/followLink-icon.svg b/src/renderer/assets/icons/followLink-icon.svg new file mode 100644 index 000000000..ac217d535 --- /dev/null +++ b/src/renderer/assets/icons/followLink-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/link-icon.svg b/src/renderer/assets/icons/link-icon.svg new file mode 100644 index 000000000..b9bc5d463 --- /dev/null +++ b/src/renderer/assets/icons/link-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/ongoingBook-icon.svg b/src/renderer/assets/icons/ongoingBook-icon.svg new file mode 100644 index 000000000..c560a9522 --- /dev/null +++ b/src/renderer/assets/icons/ongoingBook-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/pen-icon.svg b/src/renderer/assets/icons/pen-icon.svg new file mode 100644 index 000000000..82f84829c --- /dev/null +++ b/src/renderer/assets/icons/pen-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/readBook-icon.svg b/src/renderer/assets/icons/readBook-icon.svg new file mode 100644 index 000000000..9ff38e582 --- /dev/null +++ b/src/renderer/assets/icons/readBook-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/icons/trash-icon.svg b/src/renderer/assets/icons/trash-icon.svg new file mode 100644 index 000000000..583854f7a --- /dev/null +++ b/src/renderer/assets/icons/trash-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/renderer/assets/styles/bookDetailsDialog.css b/src/renderer/assets/styles/bookDetailsDialog.css index 8322a0410..03294421b 100644 --- a/src/renderer/assets/styles/bookDetailsDialog.css +++ b/src/renderer/assets/styles/bookDetailsDialog.css @@ -303,7 +303,7 @@ left: 0; right: 0; background: linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 1)); - height: 2rem; + height: 5rem; } } diff --git a/src/renderer/assets/styles/components/breadcrumb.css b/src/renderer/assets/styles/components/breadcrumb.css index 9900ed465..ed271091f 100644 --- a/src/renderer/assets/styles/components/breadcrumb.css +++ b/src/renderer/assets/styles/components/breadcrumb.css @@ -15,7 +15,6 @@ font-size: 16px; display: flex; align-items: center; - /* color: rgb(59, 59, 59); */ color: var(--color-accent); position: fixed; diff --git a/src/renderer/assets/styles/components/buttons.css b/src/renderer/assets/styles/components/buttons.css index f40963040..6c7feda2c 100644 --- a/src/renderer/assets/styles/components/buttons.css +++ b/src/renderer/assets/styles/components/buttons.css @@ -36,13 +36,13 @@ /* button */ -button, +/* button, .button_primary, .button_primary_small { &:not(:last-child) { margin-right: 10px; } -} +} */ button { padding: 0; @@ -51,9 +51,25 @@ button { height: 30px; fill: var(--color-primary); cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 5px; &:hover { opacity: 1; + background: transparent; + } + + &[type=submit] svg { + width: 13px; + } + + &.disabled, + &[disabled] { + opacity: 0.5; + cursor: default; + pointer-events: none; } } @@ -86,7 +102,6 @@ button { vertical-align: -2px; width: auto; height: 14px; - margin-right: 8px; transition: all 0.2s; fill: var(--color-primary); } @@ -97,17 +112,6 @@ button { margin-left: 8px; } } - - &.disabled, - &[disabled] { - opacity: 0.5; - cursor: default; - pointer-events: none; - - &:hover { - background: transparent; - } - } } .button_primary_small, @@ -193,7 +197,6 @@ button { fill: var(--color-accent-contrast); width: auto; height: 14px; - margin-right: 8px; transition: all 0.2s; } @@ -240,7 +243,6 @@ button { & svg { width: 18px; - margin-right: 8px; vertical-align: -3px; color: var(--color-disabled); } @@ -283,6 +285,50 @@ button { display: inline-block; } +.button_primary_blue { + border: 1px solid var(--color-button-primary); + height: 30px; + border-radius: 4px; + padding: 5px; + min-width: 100px; + background-color: var(--color-button-primary); + color: white; + + svg { + width: 10px; + fill: white; +} +} + +.button_secondary_blue { + border: 1px solid var(--color-button-primary); + height: 30px; + border-radius: 4px; + padding: 5px; + min-width: 100px; + background-color: var(--color-button-secondary); + color: var(--color-button-primary); + + svg { + width: 15px; + fill: var(--color-button-primary); + } +} + +.button_catalog_infos { + color: var(--color-button-primary); + height: 30px; + border-radius: 4px; + padding: 20px 5px; + background-color: var(--color-button-secondary); + margin: 30px 0; + + svg { + width: 20px; + fill: var(--color-button-primary); + } +} + /* 6. .button_keyboard diff --git a/src/renderer/assets/styles/components/buttons.css.d.ts b/src/renderer/assets/styles/components/buttons.css.d.ts index 398924e60..cf7c447a5 100644 --- a/src/renderer/assets/styles/components/buttons.css.d.ts +++ b/src/renderer/assets/styles/components/buttons.css.d.ts @@ -1,16 +1,19 @@ declare const styles: { readonly "___DEBUG___COMPONENTS_BUTTONS_CSS": string; readonly "block_line": string; + readonly "button_catalog_infos": string; readonly "button_icon": string; readonly "button_keyboard": string; readonly "button_link": string; readonly "button_outline_accessibility": string; readonly "button_primary": string; + readonly "button_primary_blue": string; readonly "button_primary_form_default": string; readonly "button_primary_icon": string; readonly "button_primary_small": string; readonly "button_refresh": string; readonly "button_secondary": string; + readonly "button_secondary_blue": string; readonly "button_see_more": string; readonly "button_small": string; readonly "button_transparency": string; diff --git a/src/renderer/assets/styles/components/catalog.scss b/src/renderer/assets/styles/components/catalog.scss new file mode 100644 index 000000000..d942e04e6 --- /dev/null +++ b/src/renderer/assets/styles/components/catalog.scss @@ -0,0 +1,14 @@ +.catalog_infos_text { + margin-bottom: 30px; + font-size: 14px; + max-width: 750px; + a { + color: var(--color-button-primary); + display: flex; + align-items: center; + gap: 5px; + svg { + width: 14px; + } + } +} diff --git a/src/renderer/assets/styles/components/inputs.css b/src/renderer/assets/styles/components/inputs.css index a5fb919b9..d0a79c22e 100644 --- a/src/renderer/assets/styles/components/inputs.css +++ b/src/renderer/assets/styles/components/inputs.css @@ -194,7 +194,7 @@ select { /* 5. form_group */ -.form_group { +/* .form_group { display: flex; justify-content: left; align-items: center; @@ -217,6 +217,62 @@ select { &:not(:last-child):not(:only-child) { margin-bottom: 2rem; } +} */ + +.form_group { + width: 150px; + height: 20px; + padding:5px; + border:1px solid var(--color-primary); + margin:20px 0; + border-radius: 6px; + position: relative; + display: flex; + align-items: center; + + & >label{ + position:absolute; + font-size: 14px; + top:-10px; + left:10px; + background-color:white; + } + + & >input{ + border:none; + width: calc(100% - 35px); + height: 100%; + margin-left: 30px; + + &[type="search"], &[title="Add a tag"] { + margin: 0; + width: 100%; + } + } + + & i { + width: 15px; + padding: 5px; + position: absolute; + } + +} + +.form_group_catalog { + width: 100%; + height: 30px; +} + +.form_group_wrapper { + display: flex; + flex-wrap: nowrap; + align-items: end; + gap: 10px; + + & button { + min-width: 100px; + height: 42px; + } } /* 6. dropzone */ diff --git a/src/renderer/assets/styles/components/inputs.css.d.ts b/src/renderer/assets/styles/components/inputs.css.d.ts index 9ab89d269..97cfac77f 100644 --- a/src/renderer/assets/styles/components/inputs.css.d.ts +++ b/src/renderer/assets/styles/components/inputs.css.d.ts @@ -3,6 +3,8 @@ declare const styles: { readonly "checkbox_keyboard": string; readonly "dropzone": string; readonly "form_group": string; + readonly "form_group_catalog": string; + readonly "form_group_wrapper": string; readonly "outline": string; readonly "radio_list": string; }; diff --git a/src/renderer/assets/styles/components/modals.css b/src/renderer/assets/styles/components/modals.css index cbf229372..59a4a9673 100644 --- a/src/renderer/assets/styles/components/modals.css +++ b/src/renderer/assets/styles/components/modals.css @@ -38,11 +38,14 @@ } .modal_dialog { - margin: 30px; - min-height: 400px; - min-width: 700px; - max-width: calc(100vw - 60px); - max-height: calc(100vh - 60px); + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + + /* min-height: 570px; */ + min-width: 800px; + max-width: 960px; + max-height: calc(100vh - 100px); border-radius: 10px; z-index: 102; display: flex; @@ -52,13 +55,17 @@ overflow-x: hidden; align-content: flex-start; color: var(--color-primary);; - position: relative; + position: absolute; box-sizing: border-box; - &.modal_dialog_full { - width: calc(100vw - 60px); - height: calc(100vh - 60px); + @media screen and (width <= 960px) { + width: 100vw; } + + /* &.modal_dialog_full { + width: calc(100vw - 60px); + height: calc(100vh - 100px); + } */ } /* @@ -87,7 +94,7 @@ .modal_dialog_footer { display: flex; flex: none; - padding: 0 20px; + margin: 0 20px; align-items: center; height: 70px; } @@ -110,6 +117,11 @@ .modal_dialog_footer { justify-content: end; border-top: 1px solid var(--color-medium-grey); + position: sticky; + bottom: 0; + right: 0; + background-color: var(--color-secondary); + gap: 10px; & [type="submit"] { min-width: 100px; @@ -171,3 +183,13 @@ .___DEBUG___COMPONENTS_MODALS_CSS { display: none; } + + +.modal_dialog-collapsed { + min-height: 0; +} + +.modal_dialog_body-collapsed { + height: 0; + display: none; +} diff --git a/src/renderer/assets/styles/components/modals.css.d.ts b/src/renderer/assets/styles/components/modals.css.d.ts index 84f29abd7..a4ccce376 100644 --- a/src/renderer/assets/styles/components/modals.css.d.ts +++ b/src/renderer/assets/styles/components/modals.css.d.ts @@ -5,10 +5,11 @@ declare const styles: { readonly "close_button": string; readonly "field": string; readonly "modal_dialog": string; + readonly "modal_dialog-collapsed": string; readonly "modal_dialog_body": string; + readonly "modal_dialog_body-collapsed": string; readonly "modal_dialog_body_centered": string; readonly "modal_dialog_footer": string; - readonly "modal_dialog_full": string; readonly "modal_dialog_header": string; readonly "modal_dialog_overlay": string; readonly "modal_dialog_overlay_hidden": string; diff --git a/src/renderer/assets/styles/components/tags.css b/src/renderer/assets/styles/components/tags.css index bf1f7aca6..594f996e5 100644 --- a/src/renderer/assets/styles/components/tags.css +++ b/src/renderer/assets/styles/components/tags.css @@ -21,12 +21,12 @@ .tag { display: flex; align-items: center; - background-color: #e7f1fb; + background-color: var(--color-button-secondary); padding: 2px 6px; font-size: 1.1rem; border-radius: 5px; - border: 1px solid var(--color-tertiary); - color: var(--color-tertiary); + border: 0.5px solid var(--color-button-primary); + color: var(--color-button-primary); cursor: pointer; text-decoration: none; transition: all 0.2s; diff --git a/src/renderer/assets/styles/partials/variables.css b/src/renderer/assets/styles/partials/variables.css index 9de392aff..130ae5a99 100644 --- a/src/renderer/assets/styles/partials/variables.css +++ b/src/renderer/assets/styles/partials/variables.css @@ -34,4 +34,4 @@ .___DEBUG___PARTIALS_VARIABLES_CSS { display: none; -} \ No newline at end of file +} diff --git a/src/renderer/assets/styles/publicationInfos.scss b/src/renderer/assets/styles/publicationInfos.scss new file mode 100644 index 000000000..64a090dcf --- /dev/null +++ b/src/renderer/assets/styles/publicationInfos.scss @@ -0,0 +1,149 @@ +.publicationInfo-container { + display: flex; + margin-left: -15px; + margin-right: -15px; + flex-direction: row; + align-items: flex-start; + button { + font-weight: 400; + transition: 200ms linear; + } + svg { + width: 16px; + height: 16px; + } + section { + margin-bottom: 30px; + } + .button_primary { + border: 1px solid var(--color-button-primary); + height: 30px; + border-radius: 4px; + padding: 5px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--color-button-primary); + color: white; + } + .button_secondary, .button_transparency { + border: 1px solid var(--color-button-primary); + height: 30px; + border-radius: 4px; + padding: 5px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: var(--color-button-secondary); + color: var(--color-button-primary); + &:hover { + background-color: white; + color: var(--color-button-primary); + } + } +} + +.publicationInfo-leftSide { + flex: 1; + max-width: 35%; + text-align: center; + &-coverWrapper { + width: 100%; + position: relative; + display: flex; + min-height: 400px; + align-items: center; + background-color: var(--color-light-grey); + border: 1px solid var(--color-medium-grey); + border-radius: 6px; + } + &-buttonsWrapper { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 20px 0; + flex-wrap: wrap; + > div { + width: 100%; + } + button { + flex: 1 0 25%; + margin: 5px 0; + } + } +} + +.publicationInfo { + &-rightSide { + padding: 0 20px; + flex: 2; + h2 { + font-style: italic; + } + } + &-heading h3 { + position: relative; + font-weight: 600; + margin-bottom: 10px; + font-size: 18px; + } + &-description-bloc { + position: relative; + font-size: 1rem; + &-seeMore { + color: var(--color-button-primary); + text-decoration: underline; + font-size: 16px; + display: flex; + width: 100px; + align-items: center; + justify-content: center; + svg { + width: 20px; + margin: auto; + } + } + } + &-moreInfo-content, &-lcpInfo-content { + font-size: 16px; + div { + margin-bottom: 5px; + strong { + font-weight: 600; + } + } + } +} + +.publicationInfo-tagContainer { + .tag { + font-size: 14px; + } + form { + display: flex; + align-items: center; + gap: 10px; + button { + width: 80px !important; + min-width: 80px; + svg { + fill: white; + } + } + } +} + +.publicationInfo-progressionContainer { + display: flex; + flex-direction: column; + gap: 10px; + p { + display: flex; + align-items: center; + gap: 10px; + } +} diff --git a/src/renderer/assets/styles/reader-app.css b/src/renderer/assets/styles/reader-app.css index f35891f98..6f2ca3eae 100644 --- a/src/renderer/assets/styles/reader-app.css +++ b/src/renderer/assets/styles/reader-app.css @@ -17,6 +17,8 @@ =-=-= reader-app.css */ +@import url('./components/inputs.css'); + /* :global */ :root.HIDE_CURSOR_CLASS, @@ -87,11 +89,12 @@ body { } button { + display: inline; background: none; border: 0; cursor: pointer; - color: var(--reader-fontColor) !important; - fill: var(--reader-fontColor) !important; + color: var(--reader-fontColor); + fill: var(--reader-fontColor); height: auto; &:hover { diff --git a/src/renderer/common/components/dialog/Dialog.tsx b/src/renderer/common/components/dialog/Dialog.tsx index 02745cc8c..277a48d5e 100644 --- a/src/renderer/common/components/dialog/Dialog.tsx +++ b/src/renderer/common/components/dialog/Dialog.tsx @@ -102,7 +102,7 @@ class Dialog extends React.Component, undefined>

{this.props.title}

@@ -164,7 +164,7 @@ class Dialog extends React.Component, undefined> onClick={(_e) => { this.props.closeDialog(); }} - className={stylesButtons.button_primary} + className={stylesButtons.button_secondary_blue} > {__("dialog.cancel")} @@ -177,7 +177,7 @@ class Dialog extends React.Component, undefined> this.submitForm(e); }} - className={classNames(stylesButtons.button_primary, stylesButtons.button_primary_form_default)} + className={classNames(stylesButtons.button_primary_blue, stylesButtons.button_primary_form_default)} ref={this.okRef} > {this.props.submitButtonTitle} diff --git a/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx b/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx index dd8550c27..e2c56b4a5 100644 --- a/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/LcpInfo.tsx @@ -102,7 +102,7 @@ class LcpInfo extends React.Component { return ( <> -
+

LCP

@@ -134,24 +134,24 @@ class LcpInfo extends React.Component { } {lcpRightsStartDateStr && <> - {__("publication.lcpStart")}: {lcpRightsStartDateStr} + {__("publication.lcpStart")}: {lcpRightsStartDateStr}
} {lcpRightsEndDateStr && <> - {__("publication.lcpEnd")}: {lcpRightsEndDateStr} + {__("publication.lcpEnd")}: {lcpRightsEndDateStr}

} {lcpRightsCopy ? <> {__("publication.lcpRightsCopy")}: - {lcpRightsCopies} / {lcpRightsCopy}
+ {lcpRightsCopies} / {lcpRightsCopy}
: undefined} {lcpRightsPrint ? <> {__("publication.lcpRightsPrint")}: - 0 / {lcpRightsPrint}
+ 0 / {lcpRightsPrint}
: undefined}
diff --git a/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx b/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx index 5a801f41e..9d3af2719 100644 --- a/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx +++ b/src/renderer/common/components/dialog/publicationInfos/PublicationInfoDescription.tsx @@ -12,9 +12,12 @@ import * as React from "react"; import { I18nTyped, Translator } from "readium-desktop/common/services/translator"; import { TPublication } from "readium-desktop/common/type/publication.type"; import * as stylesBookDetailsDialog from "readium-desktop/renderer/assets/styles/bookDetailsDialog.css"; -import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; -import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +// import * as stylesBlocks from "readium-desktop/renderer/assets/styles/components/blocks.css"; +// import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +// import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import SVG from "../../SVG"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as ChevronUp from "readium-desktop/renderer/assets/icons/chevron-up.svg"; // Logger const debug = debug_("readium-desktop:renderer:publicationInfoDescription"); @@ -68,15 +71,14 @@ export default class PublicationInfoDescription extends React.Component; return ( <> -
+

{__("catalog.description")}

-
+
{ this.state.needSeeMore && - diff --git a/src/renderer/library/components/dialog/ApiappAddForm.tsx b/src/renderer/library/components/dialog/ApiappAddForm.tsx index 86c06f2ef..422373190 100644 --- a/src/renderer/library/components/dialog/ApiappAddForm.tsx +++ b/src/renderer/library/components/dialog/ApiappAddForm.tsx @@ -6,104 +6,62 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; +import * as Dialog from "@radix-ui/react-dialog"; import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import { TDispatch } from "readium-desktop/typings/redux"; -// import * as SearchIcon from "readium-desktop/renderer/assets/icons/baseline-search-24px-grey.svg"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; import * as magnifyingGlass from "readium-desktop/renderer/assets/icons/magnifying_glass.svg"; import SVG from "readium-desktop/renderer/common/components/SVG"; import { IApiappSearchResultView } from "readium-desktop/common/api/interface/apiappApi.interface"; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType, ReturnType { -} - -interface IState { - name: string | undefined; - url: string | undefined; - searchResultView: IApiappSearchResultView[]; - selectSearchResult: IApiappSearchResultView | undefined; - query: string; -} - -class ApiappAddForm extends React.Component { - // private focusRef: React.RefObject; - private inputRef: React.RefObject; - - constructor(props: IProps) { - super(props); - - // this.focusRef = React.createRef(); - this.inputRef = React.createRef(); - - this.state = { - name: undefined, - url: undefined, - searchResultView: [], - selectSearchResult: undefined, - query: "", - }; - } - - public componentDidMount() { - if (this.inputRef?.current) { - this.inputRef.current.focus(); - } - } - - public render(): React.ReactElement<{}> { - if (!this.props.open) { - return (<>); - } - - const { __ } = this.props; - const listItems = this.state.searchResultView.map((v, idx) => -
  • +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; +import { useApi } from "readium-desktop/renderer/common/hooks/useApi"; +import { nanoid } from "nanoid"; +import * as AddIcon from "readium-desktop/renderer/assets/icons/add-alone.svg"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/outline-info-24px.svg"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as ChevronUp from "readium-desktop/renderer/assets/icons/chevron-up.svg"; +import * as FollowLinkIcon from "readium-desktop/renderer/assets/icons/followLink-icon.svg"; +import classNames from "classnames"; + +const context = React.createContext<{ + selectSearchResult: IApiappSearchResultView; + setSelectSearchResult: React.Dispatch>; + submitAction: () => void; +}>(undefined); + +const Item = ({v}: {v: IApiappSearchResultView}) => { + + const {selectSearchResult, setSelectSearchResult, submitAction } = React.useContext(context); + return
  • this.setState({ selectSearchResult: v })} - onDoubleClick={(e) => { - this.setState({ selectSearchResult: v }); + onClick={() => setSelectSearchResult(v)} + onDoubleClick={() => { + // e.preventDefault(); + setSelectSearchResult(v); setTimeout(() => { - this.addDoubleClick(e); + submitAction(); }, 0); }} onKeyDown={(e) => { if (e.key === "Enter") { - this.setState({ selectSearchResult: v }); + // e.preventDefault(); + // e.stopPropagation(); + setSelectSearchResult(v); setTimeout(() => { - this.addDoubleClick(e); + submitAction(); }, 0); - - // e.preventDefault(); - e.stopPropagation(); } }} > @@ -113,109 +71,151 @@ class ApiappAddForm extends React.Component {
    {v.address}
    -
  • ); + ; +}; - return ( - -
    -
    - { - if (e.key === "Enter") { - this.search(undefined); - // e.preventDefault(); - e.stopPropagation(); - } - }} - /> - -
    -
    - { - listItems.length - ?
      - {listItems} -
    - : - this.state.query ? __("apiapp.noLibraryFound", { name: this.state.query }) : <> - } -
    -
    -
    - ); - } +const ApiappAddForm = () => { + const [__] = useTranslator(); + const searchInputRef = React.useRef(); + const [infoOpen, setInfoOpen] = React.useState(false); + + const ItemListWithStyle = () => +
    + { + searchResultView?.length ?
      + {searchResultView.map((v) => )} +
    + : searchInputRef?.current?.value ? __("apiapp.noLibraryFound", { name: searchInputRef?.current.value }) : <> + } +
    ; - private addDoubleClick = (e: React.UIEvent) => { - e.preventDefault(); - this.add(); - this.props.closeDialog(); - }; + const [resultApiAppSearchAction, apiAppSearchAction] = useApi(undefined, "apiapp/search"); + const searchResultView = resultApiAppSearchAction?.data?.result || []; - private add = () => { - if (!this.state.selectSearchResult?.name || !this.state.selectSearchResult?.id || !this.state.selectSearchResult?.url) { - return; - } - const title = this.state.selectSearchResult.name; - const url = `apiapp://${this.state.selectSearchResult.id}:apiapp:${this.state.selectSearchResult.url}`; - apiAction("opds/addFeed", { title, url }).catch((err) => { - console.error("Error to fetch api opds/addFeed", err); - }); + const openInfo = (e: any) => { + e.preventDefault(); + setInfoOpen(!infoOpen); }; - private search: React.MouseEventHandler = (e) => { - e?.preventDefault(); // undefined on enter keydown input search - - const value = this.inputRef?.current?.value; - this.setState({ query: "" }); + return ( +
    +
    +
    + + { + if (e.key === "Enter") { + const v = searchInputRef.current?.value; + if (!v) return ; + apiAppSearchAction(v); + // e.preventDefault(); + // e.stopPropagation(); + } + }} + /> +
    + +
    + +
    + + { infoOpen ? +
    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Phasellus elit libero, pharetra vitae cursus sed, tincidunt et elit. + Morbi laoreet iaculis nibh, non condimentum nulla euismod sed. +

    + + Vivamus quis pharetra eros. + + +
    + : <>} +
    +
    + ); +}; - if (value && typeof value === "string") { - apiAction("apiapp/search", value) - .then((searchResultView) => { - this.setState({ searchResultView }); - this.setState({ query: value }); - }) - .catch((error) => console.error("Error to fetch api apiapp/search", error)); +export const ApiappAddFormDialog = () => { + const [__] = useTranslator(); + const [, apiAddFeedAction] = useApi(undefined, "opds/addFeed"); + const [selectSearchResult, setSelectSearchResult] = React.useState(undefined); + const addFeedAction = React.useCallback(() => { + if (!selectSearchResult?.name || !selectSearchResult?.id || !selectSearchResult?.url) { + return; } - }; -} - -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - return { - closeDialog: () => { - dispatch( - dialogActions.closeRequest.build(), - ); - }, - }; + const title = selectSearchResult.name; + const url = `apiapp://${selectSearchResult.id}:apiapp:${selectSearchResult.url}`; + apiAddFeedAction({title, url}); + }, [selectSearchResult, apiAddFeedAction]); + + const submitButtonRef = React.useRef(); + const contextValue = {selectSearchResult, setSelectSearchResult, submitAction: () => submitButtonRef.current.click()}; + + return + + + + +
    + + +
    + + {__("opds.addFormApiapp.title")} + +
    + + + +
    +
    + + +
    + + + + + + +
    +
    +
    +
    +
    ; }; -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.ApiappAddForm, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(withTranslator(ApiappAddForm)); +export default ApiappAddFormDialog; diff --git a/src/renderer/library/components/dialog/DialogManager.tsx b/src/renderer/library/components/dialog/DialogManager.tsx index 670023217..6805473c8 100644 --- a/src/renderer/library/components/dialog/DialogManager.tsx +++ b/src/renderer/library/components/dialog/DialogManager.tsx @@ -9,13 +9,11 @@ import * as React from "react"; import { connect } from "react-redux"; import PublicationInfo from "readium-desktop/renderer/library/components/dialog/publicationInfos/PublicationInfo"; import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; -import ApiappAddForm from "./ApiappAddForm"; import DeleteOpdsFeedConfirm from "./DeleteOpdsFeedConfirm"; import DeletePublicationConfirm from "./DeletePublicationConfirm"; import FileImport from "./FileImport"; import LcpAuthentication from "./LcpAuthentication"; -import OpdsFeedAddForm from "./OpdsFeedAddForm"; import OpdsFeedUpdateForm from "./OpdsFeedUpdateForm"; import RenewLsdConfirm from "./RenewLsdConfirm"; import ReturnLsdConfirm from "./ReturnLsdConfirm"; @@ -46,8 +44,6 @@ class DialogManager extends React.Component { return ( <> - - diff --git a/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx b/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx index f86670d74..f200c407f 100644 --- a/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx +++ b/src/renderer/library/components/dialog/OpdsFeedAddForm.tsx @@ -6,117 +6,130 @@ // ==LICENSE-END== import * as React from "react"; -import { connect } from "react-redux"; -import { DialogTypeName } from "readium-desktop/common/models/dialog"; -import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.css"; +import * as Dialog from "@radix-ui/react-dialog"; +import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; +import SVG from "readium-desktop/renderer/common/components/SVG"; +import * as AddIcon from "readium-desktop/renderer/assets/icons/add-alone.svg"; +import { useApi } from "readium-desktop/renderer/common/hooks/useApi"; +import { useTranslator } from "readium-desktop/renderer/common/hooks/useTranslator"; import * as stylesInputs from "readium-desktop/renderer/assets/styles/components/inputs.css"; import * as stylesModals from "readium-desktop/renderer/assets/styles/components/modals.css"; -import Dialog from "readium-desktop/renderer/common/components/dialog/Dialog"; -import { - TranslatorProps, withTranslator, -} from "readium-desktop/renderer/common/components/hoc/translator"; -import { apiAction } from "readium-desktop/renderer/library/apiAction"; -import { ILibraryRootState } from "readium-desktop/common/redux/states/renderer/libraryRootState"; +import * as QuitIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; +import "readium-desktop/renderer/assets/styles/components/catalog.scss"; +import classNames from "classnames"; +import * as InfoIcon from "readium-desktop/renderer/assets/icons/outline-info-24px.svg"; +import * as ChevronDown from "readium-desktop/renderer/assets/icons/chevron-down.svg"; +import * as ChevronUp from "readium-desktop/renderer/assets/icons/chevron-up.svg"; +import * as FollowLinkIcon from "readium-desktop/renderer/assets/icons/followLink-icon.svg"; +import * as penIcon from "readium-desktop/renderer/assets/icons/pen-icon.svg"; +import * as linkIcon from "readium-desktop/renderer/assets/icons/link-icon.svg"; -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IBaseProps extends TranslatorProps { -} -// IProps may typically extend: -// RouteComponentProps -// ReturnType -// ReturnType -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface IProps extends IBaseProps, ReturnType { -} +export const ApiappAddFormDialog = () => { + const [__] = useTranslator(); + const [, apiAddFeedAction] = useApi(undefined, "opds/addFeed"); -interface IState { - name: string | undefined; - url: string | undefined; -} - -class OpdsFeedAddForm extends React.Component { - private focusRef: React.RefObject; - - constructor(props: IProps) { - super(props); - - this.focusRef = React.createRef(); - - this.state = { - name: undefined, - url: undefined, - }; - - } - - public componentDidMount() { - if (this.focusRef?.current) { - this.focusRef.current.focus(); + const [title, setTitle] = React.useState(""); + const [url, setUrl] = React.useState(""); + const [infoOpen, setInfoOpen] = React.useState(false); + const addAction = () => { + if (!title || !url) { + return; } - } + apiAddFeedAction({ title, url }); + }; - public render(): React.ReactElement<{}> { - if (!this.props.open) { - return (<>); - } + const openInfo = (e: any) => { + e.preventDefault(); + setInfoOpen(!infoOpen); + }; - const { __ } = this.props; - const { name, url } = this.state; - return ( - + + + + +
    + +
    + + {__("opds.addMenu")} + +
    + + + +
    +
    +
    +
    + + this.setState({ - name: e.target.value, - })} + id="title" + value={title} + onChange={(e) => setTitle(e?.target?.value)} type="text" aria-label={__("opds.addForm.name")} - placeholder={__("opds.addForm.namePlaceholder")} - defaultValue={name} - ref={this.focusRef} + // placeholder={__("opds.addForm.namePlaceholder")} + required />
    -
    - +
    + + {/* */} + this.setState({ - url: e.target.value, - })} + id="url" + value={url} + onChange={(e) => setUrl(e?.target?.value)} type="text" aria-label={__("opds.addForm.url")} - placeholder={__("opds.addForm.urlPlaceholder")} - defaultValue={url} + // placeholder={__("opds.addForm.urlPlaceholder")} + required />
    -
    -
    - ); - } - - public add = () => { - const title = this.state.name; - const url = this.state.url; - if (!title || !url) { - return; - } - apiAction("opds/addFeed", { title, url }).catch((err) => { - console.error("Error to fetch api opds/addFeed", err); - }); - }; - -} -const mapStateToProps = (state: ILibraryRootState, _props: IBaseProps) => ({ - open: state.dialog.type === DialogTypeName.OpdsFeedAddForm, -}); +
    + + {infoOpen ? +
    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Phasellus elit libero, pharetra vitae cursus sed, tincidunt et elit. + Morbi laoreet iaculis nibh, non condimentum nulla euismod sed. +

    + + Vivamus quis pharetra eros. + + +
    + : <>} +
    +
    + + + + + + +
    + + + + ; +}; -export default connect(mapStateToProps)(withTranslator(OpdsFeedAddForm)); +export default ApiappAddFormDialog; diff --git a/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx b/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx index 52b1270d8..7676873a6 100644 --- a/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/catalogControls.tsx @@ -11,8 +11,9 @@ import { DialogTypeName } from "readium-desktop/common/models/dialog"; import { readerActions } from "readium-desktop/common/redux/actions"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { PublicationView } from "readium-desktop/common/views/publication"; -import * as DeleteIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as ExportIcon from "readium-desktop/renderer/assets/icons/download.svg"; +import * as SaveAsIcon from "readium-desktop/renderer/assets/icons/SaveAs-icon.svg"; +import * as TrashIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; +import * as ReadBook from "readium-desktop/renderer/assets/icons/readBook-icon.svg"; import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; import { TranslatorProps, withTranslator, @@ -54,15 +55,16 @@ export class CatalogControls extends React.Component { return ( <> diff --git a/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx b/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx index a034a0885..c481ec176 100644 --- a/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/catalogLcpControls.tsx @@ -12,8 +12,6 @@ import { readerActions } from "readium-desktop/common/redux/actions"; import * as dialogActions from "readium-desktop/common/redux/actions/dialog"; import { PublicationView } from "readium-desktop/common/views/publication"; import * as ArrowIcon from "readium-desktop/renderer/assets/icons/arrow-right.svg"; -import * as DeleteIcon from "readium-desktop/renderer/assets/icons/baseline-close-24px.svg"; -import * as ExportIcon from "readium-desktop/renderer/assets/icons/download.svg"; import * as LoopIcon from "readium-desktop/renderer/assets/icons/loop.svg"; import * as stylesButtons from "readium-desktop/renderer/assets/styles/components/buttons.css"; import { @@ -26,6 +24,10 @@ import { apiAction } from "readium-desktop/renderer/library/apiAction"; import { StatusEnum } from "@r2-lcp-js/parser/epub/lsd"; +import * as ReadBook from "readium-desktop/renderer/assets/icons/readBook-icon.svg"; +import * as SaveAsIcon from "readium-desktop/renderer/assets/icons/SaveAs-icon.svg"; +import * as TrashIcon from "readium-desktop/renderer/assets/icons/trash-icon.svg"; + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface IBaseProps extends TranslatorProps { publicationView: PublicationView; @@ -83,6 +85,7 @@ class CatalogLcpControls extends React.Component { onClick={this.handleRead} className={stylesButtons.button_primary} > + {__("catalog.readBook")} : <> @@ -112,12 +115,12 @@ class CatalogLcpControls extends React.Component { onClick={ this.deletePublication } className={stylesButtons.button_transparency} > - + {__("catalog.deleteBook")} diff --git a/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx b/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx index e89beb272..318a0df88 100644 --- a/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx +++ b/src/renderer/library/components/dialog/publicationInfos/opdsControls/OpdsControls.tsx @@ -57,7 +57,7 @@ export class OpdsControls extends React.Component { __, } = this.props; - const boxStyle = {border: "1px solid silver", borderRadius: "8px", padding: "0.4em", paddingTop: "0.2em", marginBottom: "0.5em", marginTop: "0.4em"}; + const boxStyle = {fontSize: "16px",border: "1px solid silver", borderRadius: "8px", padding: "0.4em", paddingTop: "0.2em", marginBottom: "0.5em", marginTop: "0.4em"}; const m = findMimeTypeWithExtension(ADOBE_ADEPT_XML); const orderLinks = (links: IOpdsLinkView[]) => { @@ -118,7 +118,7 @@ export class OpdsControls extends React.Component { ln, opdsPublicationView, )} - className={stylesButtons.button_primary} + className={stylesButtons.button_transparency} disabled={sampleButtonIsDisabled()} > @@ -152,7 +152,6 @@ export class OpdsControls extends React.Component { {__("opds.menu.goBuyBook")} -
    , ) @@ -164,7 +163,7 @@ export class OpdsControls extends React.Component { (ln, idx) =>
    - - - ); - } -} - -const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => { - return { - openOpdsFeedAddForm: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.OpdsFeedAddForm, {})); - }, - openApiappAddForm: () => { - dispatch(dialogActions.openRequest.build(DialogTypeName.ApiappAddForm, {})); - }, - }; }; -export default connect(undefined, mapDispatchToProps)(withTranslator(OpdsAddForm)); +export default OpdsAddForm; diff --git a/src/resources/locales/en.json b/src/resources/locales/en.json index b9e12d4f8..b3ec76feb 100644 --- a/src/resources/locales/en.json +++ b/src/resources/locales/en.json @@ -109,6 +109,7 @@ "sort": "Sort by", "tagCount": "Tag count", "tags": "Tags", + "tag": "Tag", "update": "Edit" }, "dialog": { diff --git a/src/typings/en.translation.d.ts b/src/typings/en.translation.d.ts index 9112437e3..506921ed3 100644 --- a/src/typings/en.translation.d.ts +++ b/src/typings/en.translation.d.ts @@ -152,6 +152,7 @@ declare namespace typed_i18n { readonly "sort": string, readonly "tagCount": string, readonly "tags": string, + readonly "tag": string, readonly "update": string }; (_: "catalog.about", __?: {}): { readonly "button": string, readonly "title": string }; @@ -266,7 +267,7 @@ declare namespace typed_i18n { (_: "catalog.released", __?: {}): string; (_: "catalog.sort", __?: {}): string; (_: "catalog.tagCount", __?: {}): string; - (_: "catalog.tags", __?: {}): string; + (_: "catalog.tags", __?: {}): string; (_: "catalog.tag", __?: {}): string; (_: "catalog.update", __?: {}): string; (_: "dialog", __?: {}): { readonly "cancel": string,