From 9dd61a7c0f600c85ce4b1ba90e162b0acebe86d6 Mon Sep 17 00:00:00 2001 From: Jan Ackermann Date: Tue, 6 Feb 2024 16:07:35 +0100 Subject: [PATCH 1/5] Init epub reader --- config/config.json.dist | 3 +- config/config.json.sample-ocis | 3 +- dev/docker/ocis.web-federated.config.json | 3 +- dev/docker/ocis.web.config.json | 3 +- .../assets/icons/resource-type-epub-fill.svg | 6 + .../assets/icons/resource-type-epub-line.svg | 6 + packages/web-app-epub-reader/l10n/.tx/config | 9 + .../l10n/translations.json | 1 + packages/web-app-epub-reader/package.json | 16 ++ packages/web-app-epub-reader/src/App.vue | 159 +++++++++++++++++ packages/web-app-epub-reader/src/index.ts | 86 ++++++++++ .../tests/unit/app.spec.ts | 23 +++ .../components/AppTemplates/AppWrapper.vue | 13 +- .../AppTemplates/AppWrapperRoute.ts | 3 +- .../appDefaults/useAppFileHandling.ts | 9 +- packages/web-pkg/src/helpers/resource/icon.ts | 19 +- pnpm-lock.yaml | 162 ++++++++++++++++-- 17 files changed, 487 insertions(+), 37 deletions(-) create mode 100644 packages/design-system/src/assets/icons/resource-type-epub-fill.svg create mode 100644 packages/design-system/src/assets/icons/resource-type-epub-line.svg create mode 100644 packages/web-app-epub-reader/l10n/.tx/config create mode 100644 packages/web-app-epub-reader/l10n/translations.json create mode 100644 packages/web-app-epub-reader/package.json create mode 100644 packages/web-app-epub-reader/src/App.vue create mode 100644 packages/web-app-epub-reader/src/index.ts create mode 100644 packages/web-app-epub-reader/tests/unit/app.spec.ts diff --git a/config/config.json.dist b/config/config.json.dist index 3c8094d1142..b3543bee538 100644 --- a/config/config.json.dist +++ b/config/config.json.dist @@ -12,7 +12,8 @@ "pdf-viewer", "preview", "search", - "text-editor" + "text-editor", + "epub-reader" ], "applications" : [] } diff --git a/config/config.json.sample-ocis b/config/config.json.sample-ocis index 05f76564916..f64a6dda665 100644 --- a/config/config.json.sample-ocis +++ b/config/config.json.sample-ocis @@ -16,7 +16,8 @@ "text-editor", "draw-io", "external", - "admin-settings" + "admin-settings", + "epub-reader" ], "options": { "previewFileMimeTypes": [ diff --git a/dev/docker/ocis.web-federated.config.json b/dev/docker/ocis.web-federated.config.json index 8ea54093ede..9658008e63b 100644 --- a/dev/docker/ocis.web-federated.config.json +++ b/dev/docker/ocis.web-federated.config.json @@ -36,7 +36,8 @@ "external", "admin-settings", "ocm", - "webfinger" + "webfinger", + "epub-reader" ], "external_apps": [ { diff --git a/dev/docker/ocis.web.config.json b/dev/docker/ocis.web.config.json index 6696b48d521..0858abc2d5c 100644 --- a/dev/docker/ocis.web.config.json +++ b/dev/docker/ocis.web.config.json @@ -36,7 +36,8 @@ "external", "admin-settings", "ocm", - "webfinger" + "webfinger", + "epub-reader" ], "external_apps": [ { diff --git a/packages/design-system/src/assets/icons/resource-type-epub-fill.svg b/packages/design-system/src/assets/icons/resource-type-epub-fill.svg new file mode 100644 index 00000000000..aa1c338ab33 --- /dev/null +++ b/packages/design-system/src/assets/icons/resource-type-epub-fill.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/design-system/src/assets/icons/resource-type-epub-line.svg b/packages/design-system/src/assets/icons/resource-type-epub-line.svg new file mode 100644 index 00000000000..0dca4e0417f --- /dev/null +++ b/packages/design-system/src/assets/icons/resource-type-epub-line.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/web-app-epub-reader/l10n/.tx/config b/packages/web-app-epub-reader/l10n/.tx/config new file mode 100644 index 00000000000..1f3ff81b972 --- /dev/null +++ b/packages/web-app-epub-reader/l10n/.tx/config @@ -0,0 +1,9 @@ +[main] +host = https://www.transifex.com + +[o:owncloud-org:p:owncloud-web:r:epub-reader] +file_filter = locale//LC_MESSAGES/app.po +minimum_perc = 0 +source_file = template.pot +source_lang = en +type = PO diff --git a/packages/web-app-epub-reader/l10n/translations.json b/packages/web-app-epub-reader/l10n/translations.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/packages/web-app-epub-reader/l10n/translations.json @@ -0,0 +1 @@ +{} diff --git a/packages/web-app-epub-reader/package.json b/packages/web-app-epub-reader/package.json new file mode 100644 index 00000000000..f5fbc413359 --- /dev/null +++ b/packages/web-app-epub-reader/package.json @@ -0,0 +1,16 @@ +{ + "name": "epub-reader", + "version": "0.0.0", + "private": true, + "description": "ownCloud Web epub-reader", + "license": "AGPL-3.0", + "devDependencies": { + "web-test-helpers": "workspace:*" + }, + "peerDependencies": { + "@ownclouders/web-client": "workspace:*", + "@ownclouders/web-pkg": "workspace:*", + "vue3-gettext": "2.4.0", + "epubjs": "^0.3.93" + } +} diff --git a/packages/web-app-epub-reader/src/App.vue b/packages/web-app-epub-reader/src/App.vue new file mode 100644 index 00000000000..fc11d4bf712 --- /dev/null +++ b/packages/web-app-epub-reader/src/App.vue @@ -0,0 +1,159 @@ + + + + diff --git a/packages/web-app-epub-reader/src/index.ts b/packages/web-app-epub-reader/src/index.ts new file mode 100644 index 00000000000..323a8ab0419 --- /dev/null +++ b/packages/web-app-epub-reader/src/index.ts @@ -0,0 +1,86 @@ +import { useGettext } from 'vue3-gettext' +import translations from '../l10n/translations.json' +import EpubReader from './App.vue' +import { + AppWrapperRoute, + ApplicationFileExtension, + defineWebApplication +} from '@ownclouders/web-pkg' + +export default defineWebApplication({ + setup({ applicationConfig }) { + const { $gettext } = useGettext() + + const appId = 'epub-reader' + + const fileExtensions = () => { + const extensions: ApplicationFileExtension[] = [ + { + extension: 'epub', + label: $gettext('EPUB file') + } + ] + + const config = applicationConfig || {} + extensions.push(...(config.extraExtensions || []).map((ext: string) => ({ extension: ext }))) + + let primaryExtensions: string[] = config.primaryExtensions || ['epub'] + + if (typeof primaryExtensions === 'string') { + primaryExtensions = [primaryExtensions] + } + + return extensions.reduce((acc, extensionItem) => { + const isPrimary = primaryExtensions.includes(extensionItem.extension) + if (isPrimary) { + extensionItem.newFileMenu = { + menuTitle() { + return $gettext(extensionItem.label) + } + } + } + acc.push(extensionItem) + return acc + }, []) + } + + const routes = [ + { + path: '/:driveAliasAndItem(.*)?', + component: AppWrapperRoute(EpubReader, { + applicationId: appId, + fileContentOptions: { + responseType: 'blob' + } + }), + name: 'epub-reader', + meta: { + authContext: 'hybrid', + title: $gettext('Epub Reader'), + patchCleanPath: true + } + } + ] + + return { + appInfo: { + name: $gettext('Epub Reader'), + id: appId, + icon: 'file-text', + color: '#0D856F', + isFileEditor: true, + defaultExtension: 'epub', + extensions: fileExtensions().map((extensionItem) => { + return { + extension: extensionItem.extension, + ...(Object.hasOwn(extensionItem, 'newFileMenu') && { + newFileMenu: extensionItem.newFileMenu + }) + } + }) + }, + routes, + translations + } + } +}) diff --git a/packages/web-app-epub-reader/tests/unit/app.spec.ts b/packages/web-app-epub-reader/tests/unit/app.spec.ts new file mode 100644 index 00000000000..3aebb06f9b4 --- /dev/null +++ b/packages/web-app-epub-reader/tests/unit/app.spec.ts @@ -0,0 +1,23 @@ +import { Resource } from '@ownclouders/web-client/src' +import { AppConfigObject } from '@ownclouders/web-pkg' +import { mount } from 'web-test-helpers' +import App from '../../src/App.vue' + +vi.mock('@ownclouders/web-pkg') + +describe.skip('Epub reader app', () => { + it('shows the epub reader', () => { + const { wrapper } = getWrapper({ + applicationConfig: {} + }) + expect(wrapper.html()).toMatchSnapshot() + }) +}) + +function getWrapper(props: { applicationConfig: AppConfigObject; resource?: Resource }) { + return { + wrapper: mount(App, { + props + }) + } +} diff --git a/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue b/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue index ad27f2827d8..bec94f55910 100644 --- a/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue +++ b/packages/web-pkg/src/components/AppTemplates/AppWrapper.vue @@ -56,7 +56,8 @@ import { useSpacesStore, useAppsStore, useConfigStore, - useResourcesStore + useResourcesStore, + FileContentOptions } from '../../composables' import { Action, @@ -96,6 +97,11 @@ export default defineComponent({ default: () => null, required: false }, + fileContentOptions: { + type: Object as PropType, + default: () => null, + required: false + }, wrappedComponent: { type: Object as PropType>, default: null @@ -262,7 +268,10 @@ export default defineComponent({ ) if (unref(hasProp('currentContent'))) { - const fileContentsResponse = yield getFileContents(currentFileContext) + const fileContentsResponse = yield getFileContents( + currentFileContext, + props.fileContentOptions + ) serverContent.value = currentContent.value = fileContentsResponse.body currentETag.value = fileContentsResponse.headers['OC-ETag'] } diff --git a/packages/web-pkg/src/components/AppTemplates/AppWrapperRoute.ts b/packages/web-pkg/src/components/AppTemplates/AppWrapperRoute.ts index a7d0deaf7b0..7e664c85199 100644 --- a/packages/web-pkg/src/components/AppTemplates/AppWrapperRoute.ts +++ b/packages/web-pkg/src/components/AppTemplates/AppWrapperRoute.ts @@ -1,7 +1,7 @@ import { defineComponent, h } from 'vue' import AppWrapper from './AppWrapper.vue' import { AppWrapperSlotArgs } from './types' -import { UrlForResourceOptions } from '../../composables' +import { FileContentOptions, UrlForResourceOptions } from '../../composables' import { Resource } from '@ownclouders/web-client/src' export function AppWrapperRoute( @@ -9,6 +9,7 @@ export function AppWrapperRoute( options: { applicationId: string urlForResourceOptions?: UrlForResourceOptions + fileContentOptions?: FileContentOptions importResourceWithExtension?: (resource: Resource) => string } ) { diff --git a/packages/web-pkg/src/composables/appDefaults/useAppFileHandling.ts b/packages/web-pkg/src/composables/appDefaults/useAppFileHandling.ts index d1aedc78faf..036a06e193c 100644 --- a/packages/web-pkg/src/composables/appDefaults/useAppFileHandling.ts +++ b/packages/web-pkg/src/composables/appDefaults/useAppFileHandling.ts @@ -13,6 +13,10 @@ interface AppFileHandlingOptions { clientService: ClientService } +export type FileContentOptions = { responseType?: 'arrayBuffer' | 'blob' | 'text' } & Record< + string, + any +> export type UrlForResourceOptions = Omit[2], 'isUrlSigningEnabled'> export interface AppFileHandlingResult { @@ -23,10 +27,7 @@ export interface AppFileHandlingResult { ): Promise revokeUrl(url: string): void getFileInfo(fileContext: MaybeRef, options?: ListFilesOptions): Promise - getFileContents( - fileContext: MaybeRef, - options?: { responseType?: 'arrayBuffer' | 'blob' | 'text' } & Record - ): Promise + getFileContents(fileContext: MaybeRef, options?: FileContentOptions): Promise putFileContents( fileContext: MaybeRef, putFileOptions: { content?: string } & Record diff --git a/packages/web-pkg/src/helpers/resource/icon.ts b/packages/web-pkg/src/helpers/resource/icon.ts index 64875e57962..9b08aaa6368 100644 --- a/packages/web-pkg/src/helpers/resource/icon.ts +++ b/packages/web-pkg/src/helpers/resource/icon.ts @@ -192,20 +192,7 @@ const fileIcon = { }, text: { icon: { name: 'resource-type-text', color: 'var(--oc-color-text-default)' }, - extensions: [ - 'cb7', - 'cba', - 'cbr', - 'cbt', - 'cbtc', - 'cbz', - 'cvbdl', - 'eml', - 'epub', - 'mdb', - 'tex', - 'txt' - ] + extensions: ['cb7', 'cba', 'cbr', 'cbt', 'cbtc', 'cbz', 'cvbdl', 'eml', 'mdb', 'tex', 'txt'] }, url: { icon: { name: 'resource-type-url', color: 'var(--oc-color-text-default)' }, @@ -217,6 +204,10 @@ const fileIcon = { color: 'var(--oc-color-icon-video)' }, extensions: ['mov', 'mp4', 'webm', 'wmv'] + }, + epub: { + icon: { name: 'resource-type-epub', color: 'var(--oc-color-text-default)' }, + extensions: ['epub'] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52ffff96237..c3a43e27363 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -618,6 +618,25 @@ importers: specifier: workspace:* version: link:../web-test-helpers + packages/web-app-epub-reader: + dependencies: + '@ownclouders/web-client': + specifier: workspace:* + version: link:../web-client + '@ownclouders/web-pkg': + specifier: workspace:* + version: link:../web-pkg + epubjs: + specifier: ^0.3.93 + version: 0.3.93 + vue3-gettext: + specifier: 2.4.0 + version: 2.4.0(@vue/compiler-sfc@3.3.8)(vue@3.3.8) + devDependencies: + web-test-helpers: + specifier: workspace:* + version: link:../web-test-helpers + packages/web-app-external: dependencies: '@ownclouders/web-client': @@ -3768,6 +3787,13 @@ packages: /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + /@types/localforage@0.0.34: + resolution: {integrity: sha512-tJxahnjm9dEI1X+hQSC5f2BSd/coZaqbIl1m3TCl0q9SVuC52XcXfV0XmoCU1+PmjyucuVITwoTnN8OlTbEXXA==} + deprecated: This is a stub types definition for localforage (https://github.com/localForage/localForage). localforage provides its own type definitions, so you don't need @types/localforage installed! + dependencies: + localforage: 1.10.0 + dev: false + /@types/lodash-es@4.17.7: resolution: {integrity: sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==} dependencies: @@ -3835,12 +3861,8 @@ packages: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} dev: true - /@types/parse-json@4.0.0: - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - /@types/parse-json@4.0.2: resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - dev: true /@types/parse5@5.0.3: resolution: {integrity: sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==} @@ -4601,6 +4623,11 @@ packages: '@xtuc/long': 4.2.2 dev: true + /@xmldom/xmldom@0.7.13: + resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==} + engines: {node: '>=10.0.0'} + dev: false + /@xtuc/ieee754@1.2.0: resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} dev: true @@ -6413,7 +6440,6 @@ packages: /core-js@3.30.2: resolution: {integrity: sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==} requiresBuild: true - dev: true /core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -6421,7 +6447,6 @@ packages: /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true /cosmiconfig@6.0.0: resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} @@ -6438,7 +6463,7 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} dependencies: - '@types/parse-json': 4.0.0 + '@types/parse-json': 4.0.2 import-fresh: 3.3.0 parse-json: 5.2.0 path-type: 4.0.0 @@ -6733,6 +6758,13 @@ packages: resolution: {integrity: sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==} dev: true + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: false + /dashdash@1.14.1: resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} engines: {node: '>=0.10'} @@ -7357,6 +7389,20 @@ packages: hasBin: true dev: true + /epubjs@0.3.93: + resolution: {integrity: sha512-c06pNSdBxcXv3dZSbXAVLE1/pmleRhOT6mXNZo6INKmvuKpYB65MwU/lO7830czCtjIiK9i+KR+3S+p0wtljrw==} + dependencies: + '@types/localforage': 0.0.34 + '@xmldom/xmldom': 0.7.13 + core-js: 3.30.2 + event-emitter: 0.3.5 + jszip: 3.10.1 + localforage: 1.10.0 + lodash: 4.17.21 + marks-pane: 1.0.9 + path-webpack: 0.0.3 + dev: false + /errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} hasBin: true @@ -7443,6 +7489,24 @@ packages: is-symbol: 1.0.4 dev: true + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: false + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: false + /es6-object-assign@1.1.0: resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==} dev: true @@ -7455,6 +7519,13 @@ packages: resolution: {integrity: sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==} dev: true + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: false + /esbuild@0.19.5: resolution: {integrity: sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==} engines: {node: '>=12'} @@ -7807,6 +7878,13 @@ packages: engines: {node: '>= 0.6'} dev: true + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: false + /eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -7938,6 +8016,12 @@ packages: - supports-color dev: true + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: false + /extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} @@ -9292,6 +9376,10 @@ packages: resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} engines: {node: '>= 4'} + /immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: false + /immer@9.0.21: resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} dev: true @@ -9845,7 +9933,6 @@ packages: /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -10212,6 +10299,15 @@ packages: is-promise: 2.2.2 promise: 7.3.1 + /jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + dev: false + /jwt-decode@3.1.2: resolution: {integrity: sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==} dev: false @@ -10355,6 +10451,18 @@ packages: - supports-color dev: true + /lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + dependencies: + immediate: 3.0.6 + dev: false + + /lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + dependencies: + immediate: 3.0.6 + dev: false + /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -10413,6 +10521,12 @@ packages: mlly: 1.5.0 pkg-types: 1.0.3 + /localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + dev: false + /locate-path@3.0.0: resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} engines: {node: '>=6'} @@ -10785,6 +10899,10 @@ packages: unquote: 1.1.1 dev: true + /marks-pane@1.0.9: + resolution: {integrity: sha512-Ahs4oeG90tbdPWwAJkAAoHg2lRR8lAs9mZXETNPO9hYg3AkjUJBKi1NQ4aaIQZVGrig7c/3NUV1jANl8rFTeMg==} + dev: false + /mathml-tag-names@2.1.3: resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} dev: true @@ -11338,6 +11456,10 @@ packages: engines: {node: '>= 0.4.0'} dev: true + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: false + /nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true @@ -12074,6 +12196,10 @@ packages: repeat-string: 1.6.1 dev: true + /pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: false + /parallel-transform@1.2.0: resolution: {integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==} dependencies: @@ -12234,6 +12360,10 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + /path-webpack@0.0.3: + resolution: {integrity: sha512-AmeDxedoo5svf7aB3FYqSAKqMxys014lVKBzy1o/5vv9CtU7U4wgGWL1dA2o6MOzcD53ScN4Jmiq6VbtLz1vIQ==} + dev: false + /pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -12985,7 +13115,6 @@ packages: /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true /process-warning@1.0.0: resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} @@ -13699,7 +13828,6 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 - dev: true /readable-stream@3.6.0: resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} @@ -14242,7 +14370,6 @@ packages: /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -14539,6 +14666,10 @@ packages: split-string: 3.1.0 dev: true + /setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: false + /setprototypeof@1.1.0: resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} dev: true @@ -15080,7 +15211,6 @@ packages: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: safe-buffer: 5.1.2 - dev: true /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -15900,6 +16030,14 @@ packages: mime-types: 2.1.35 dev: true + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: false + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: false + /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} From 17050629f6fba52e7e3c00de67821e0768a6be31 Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Thu, 8 Feb 2024 14:17:22 +0100 Subject: [PATCH 2/5] style: css tweaks --- packages/web-app-epub-reader/src/App.vue | 34 ++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/web-app-epub-reader/src/App.vue b/packages/web-app-epub-reader/src/App.vue index fc11d4bf712..658c19da0e0 100644 --- a/packages/web-app-epub-reader/src/App.vue +++ b/packages/web-app-epub-reader/src/App.vue @@ -1,10 +1,10 @@ @@ -86,7 +88,7 @@ export default defineComponent({ rendition = book.renderTo(unref(bookContainer), { flow: 'paginated', - width: 700, + width: 650, height: '100%' }) rendition.display() @@ -138,7 +140,12 @@ export default defineComponent({ } &-chapters-list { + position: absolute; + left: var(--oc-space-small); overflow-y: auto; + max-width: 210px; + height: calc(100% - 52px - (2 * var(--oc-space-small))); + max-height: calc(100% - 52px - (2 * var(--oc-space-small))); &-item { padding-top: var(--oc-space-small); @@ -151,7 +158,6 @@ export default defineComponent({ } &-item:not(:last-child) { - border-bottom: 1px solid var(--oc-color-border); padding-bottom: var(--oc-space-small); } } From 82f64cfabeff5a0c9b865bc548f3117f65e12672 Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Thu, 8 Feb 2024 14:35:05 +0100 Subject: [PATCH 3/5] change icon for epub --- .../src/assets/icons/resource-type-book-fill.svg | 1 + .../src/assets/icons/resource-type-epub-fill.svg | 6 ------ .../src/assets/icons/resource-type-epub-line.svg | 6 ------ packages/web-app-epub-reader/package.json | 6 ++++-- packages/web-app-epub-reader/src/index.ts | 3 +-- packages/web-pkg/src/helpers/resource/icon.ts | 2 +- 6 files changed, 7 insertions(+), 17 deletions(-) create mode 100644 packages/design-system/src/assets/icons/resource-type-book-fill.svg delete mode 100644 packages/design-system/src/assets/icons/resource-type-epub-fill.svg delete mode 100644 packages/design-system/src/assets/icons/resource-type-epub-line.svg diff --git a/packages/design-system/src/assets/icons/resource-type-book-fill.svg b/packages/design-system/src/assets/icons/resource-type-book-fill.svg new file mode 100644 index 00000000000..4b5e37df1aa --- /dev/null +++ b/packages/design-system/src/assets/icons/resource-type-book-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/design-system/src/assets/icons/resource-type-epub-fill.svg b/packages/design-system/src/assets/icons/resource-type-epub-fill.svg deleted file mode 100644 index aa1c338ab33..00000000000 --- a/packages/design-system/src/assets/icons/resource-type-epub-fill.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/design-system/src/assets/icons/resource-type-epub-line.svg b/packages/design-system/src/assets/icons/resource-type-epub-line.svg deleted file mode 100644 index 0dca4e0417f..00000000000 --- a/packages/design-system/src/assets/icons/resource-type-epub-line.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/packages/web-app-epub-reader/package.json b/packages/web-app-epub-reader/package.json index f5fbc413359..759dfacc577 100644 --- a/packages/web-app-epub-reader/package.json +++ b/packages/web-app-epub-reader/package.json @@ -4,13 +4,15 @@ "private": true, "description": "ownCloud Web epub-reader", "license": "AGPL-3.0", + "dependencies": { + "epubjs": "^0.3.93" + }, "devDependencies": { "web-test-helpers": "workspace:*" }, "peerDependencies": { "@ownclouders/web-client": "workspace:*", "@ownclouders/web-pkg": "workspace:*", - "vue3-gettext": "2.4.0", - "epubjs": "^0.3.93" + "vue3-gettext": "2.4.0" } } diff --git a/packages/web-app-epub-reader/src/index.ts b/packages/web-app-epub-reader/src/index.ts index 323a8ab0419..22ab484d5a8 100644 --- a/packages/web-app-epub-reader/src/index.ts +++ b/packages/web-app-epub-reader/src/index.ts @@ -66,8 +66,7 @@ export default defineWebApplication({ appInfo: { name: $gettext('Epub Reader'), id: appId, - icon: 'file-text', - color: '#0D856F', + icon: 'book-read', isFileEditor: true, defaultExtension: 'epub', extensions: fileExtensions().map((extensionItem) => { diff --git a/packages/web-pkg/src/helpers/resource/icon.ts b/packages/web-pkg/src/helpers/resource/icon.ts index 9b08aaa6368..23abc1381ad 100644 --- a/packages/web-pkg/src/helpers/resource/icon.ts +++ b/packages/web-pkg/src/helpers/resource/icon.ts @@ -206,7 +206,7 @@ const fileIcon = { extensions: ['mov', 'mp4', 'webm', 'wmv'] }, epub: { - icon: { name: 'resource-type-epub', color: 'var(--oc-color-text-default)' }, + icon: { name: 'resource-type-book', color: 'var(--oc-color-text-default)' }, extensions: ['epub'] } } From 45160157c43191119776ec634b02672d19a416d1 Mon Sep 17 00:00:00 2001 From: Jan Ackermann Date: Thu, 8 Feb 2024 15:58:34 +0100 Subject: [PATCH 4/5] Add color token for epub --- packages/design-system/src/tokens/ods/color.yaml | 2 ++ packages/web-app-epub-reader/src/App.vue | 2 +- packages/web-pkg/src/helpers/resource/icon.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/design-system/src/tokens/ods/color.yaml b/packages/design-system/src/tokens/ods/color.yaml index d43b72949ea..7084d0b474d 100644 --- a/packages/design-system/src/tokens/ods/color.yaml +++ b/packages/design-system/src/tokens/ods/color.yaml @@ -148,3 +148,5 @@ color: value: rgb(0, 187, 219) medical: value: rgb(9, 132, 219) + epub: + value: rgb(244, 187, 68) diff --git a/packages/web-app-epub-reader/src/App.vue b/packages/web-app-epub-reader/src/App.vue index 658c19da0e0..e267cb6e6a5 100644 --- a/packages/web-app-epub-reader/src/App.vue +++ b/packages/web-app-epub-reader/src/App.vue @@ -7,7 +7,7 @@ class="epub-reader-chapters-list-item oc-ml-m" :class="{ active: currentChapter.id === chapter.id }" > - + diff --git a/packages/web-pkg/src/helpers/resource/icon.ts b/packages/web-pkg/src/helpers/resource/icon.ts index 23abc1381ad..bb3c7094be4 100644 --- a/packages/web-pkg/src/helpers/resource/icon.ts +++ b/packages/web-pkg/src/helpers/resource/icon.ts @@ -206,7 +206,7 @@ const fileIcon = { extensions: ['mov', 'mp4', 'webm', 'wmv'] }, epub: { - icon: { name: 'resource-type-book', color: 'var(--oc-color-text-default)' }, + icon: { name: 'resource-type-book', color: 'var(--oc-color-icon-epub)' }, extensions: ['epub'] } } From 035a5c140a3d70b42616e36f2e9dd9aaa236bde2 Mon Sep 17 00:00:00 2001 From: Jan Ackermann Date: Thu, 8 Feb 2024 16:18:08 +0100 Subject: [PATCH 5/5] Clean index.ts --- packages/web-app-epub-reader/src/index.ts | 53 +++-------------------- 1 file changed, 7 insertions(+), 46 deletions(-) diff --git a/packages/web-app-epub-reader/src/index.ts b/packages/web-app-epub-reader/src/index.ts index 22ab484d5a8..467435c8566 100644 --- a/packages/web-app-epub-reader/src/index.ts +++ b/packages/web-app-epub-reader/src/index.ts @@ -1,49 +1,14 @@ import { useGettext } from 'vue3-gettext' import translations from '../l10n/translations.json' import EpubReader from './App.vue' -import { - AppWrapperRoute, - ApplicationFileExtension, - defineWebApplication -} from '@ownclouders/web-pkg' +import { AppWrapperRoute, defineWebApplication } from '@ownclouders/web-pkg' export default defineWebApplication({ - setup({ applicationConfig }) { + setup() { const { $gettext } = useGettext() const appId = 'epub-reader' - const fileExtensions = () => { - const extensions: ApplicationFileExtension[] = [ - { - extension: 'epub', - label: $gettext('EPUB file') - } - ] - - const config = applicationConfig || {} - extensions.push(...(config.extraExtensions || []).map((ext: string) => ({ extension: ext }))) - - let primaryExtensions: string[] = config.primaryExtensions || ['epub'] - - if (typeof primaryExtensions === 'string') { - primaryExtensions = [primaryExtensions] - } - - return extensions.reduce((acc, extensionItem) => { - const isPrimary = primaryExtensions.includes(extensionItem.extension) - if (isPrimary) { - extensionItem.newFileMenu = { - menuTitle() { - return $gettext(extensionItem.label) - } - } - } - acc.push(extensionItem) - return acc - }, []) - } - const routes = [ { path: '/:driveAliasAndItem(.*)?', @@ -67,16 +32,12 @@ export default defineWebApplication({ name: $gettext('Epub Reader'), id: appId, icon: 'book-read', - isFileEditor: true, - defaultExtension: 'epub', - extensions: fileExtensions().map((extensionItem) => { - return { - extension: extensionItem.extension, - ...(Object.hasOwn(extensionItem, 'newFileMenu') && { - newFileMenu: extensionItem.newFileMenu - }) + extensions: [ + { + extension: 'epub', + routeName: 'epub-reader' } - }) + ] }, routes, translations