quasarframework / app-extension-qpdfviewer

View PDF documents in your Quasar app
https://quasarframework.github.io/app-extension-qpdfviewer
MIT License
104 stars 19 forks source link

Extension(@quasar/qpdfviewer): is not compatible with @quasar/app v3.0.0-beta.25 #87

Closed nedadoncic closed 3 years ago

nedadoncic commented 3 years ago

Hello,

I have this issue and cannot use extension:

Extension(@quasar/qpdfviewer): is not compatible with @quasar/app v3.0.0-beta.25. Required version: ^1.0.0 || ^2.0.0

Thanks in advance

Brock-oly commented 3 years ago

This the only plugin stopping me from upgrading to Quasar 2

hawkeye64 commented 3 years ago

@nedadoncic and @Brock-oly This is on the list of app-exts that need conversion.

Also, https://github.com/quasarframework/quasar/discussions/9560

CharlieDigital commented 3 years ago

I've completed a conversion locally with only one small hiccup: the __renderText function didn't like the nested h('a') for some reason so I removed the parent p and only left the nested a.

component/QPdfviewer.js

import { defineComponent, h } from "vue"
import { useQuasar } from "quasar"

import useModelToggle, { useModelToggleProps, useModelToggleEmits } from "quasar/src/composables/private/use-model-toggle.js"

export default defineComponent({
  name: "QPdfviewer",

  props: {
    src: String,
    type: {
      type: String,
      default: "html5",
      validator: (v) => ["html5", "pdfjs"].indexOf(v) !== -1,
    },
    errorString: {
      type: String,
      default:
        "This browser does not support PDFs. Download the PDF to view it:",
    },
    contentStyle: [String, Object, Array],
    contentClass: [String, Object, Array],
    innerContentStyle: [String, Object, Array],
    innerContentClass: [String, Object, Array],

    ...useModelToggleProps,
  },

  emits: [
    ...useModelToggleEmits
  ],

  data() {
    return {
        hashId: "q-pdfviewer-" + Math.random().toString(36).substr(2, 9)
    }
  },

  render(prop) {
    const $q = useQuasar()

    function __renderObject () {
        return h('object', {
          class: [prop.innerContentClass],
          style: [prop.innerContentStyle],
          id: prop.hashId,
          data: prop.src,
          type: 'application/pdf',
          width: '100%',
          height: '100%'
        }, [
          // browser object not supported, try iframe
          __renderIFrame()
        ])
      }

    function __renderIFrame () {
        return h('iframe', {
          class: ['q-pdfviewer__iframe'],
          src: prop.src,
          width: '100%',
          height: '100%'
        }, [
          // iframe not supported either, give user a link to download
          __renderText()
        ])
      }

    function __renderIFramePDFJS () {
        return h('iframe', {
          class: ['q-pdfviewer__iframe'],
          src: 'pdfjs/web/viewer.html?file=' + encodeURIComponent(prop.src)
        }, [
          // iframe not supported either, give user a link to download
          __renderText()
        ])
      }

    function __renderText () {
        // TODO: ????
        /*return h('p',
          'This browser does not support PDFs. Download the PDF to view it:', [
          h('a', {
            href: prop.src,
            target: '_blank'
          })
        ])*/
        return h('a', {
            href: prop.src,
            target: '_blank'
          })
      }

    if (prop.src !== void 0 && prop.src.length > 0) {
        return h(
          "div",
          {
            class: ["q-pdfviewer", prop.contentClass],
            style: [prop.contentStyle],
          },
          [
            $q.platform.is.electron || prop.type === "pdfjs"
              ? __renderIFramePDFJS(h)
              : __renderObject(h),
          ]
        );
      }
      return "";
  },

  setup() {
    return {
      ...useModelToggle
    }
  }
})

Note the encodeURIComponent added to the URL when concatenating with viewer.html?file=. This addresses a use case where you may be appending a query string to locate the file (e.g. an access token). I confirmed that the script used by viewer.html calls decodeURIComponent already.

component/QPdfviewer.json

{
  "mixins": [ "composables/private/use-model-toggle" ],

  "type": "component",

  "props": {
    // Unchanged
  }
}

boot/qpdfviewer.js

import QPdfviewer from '@quasar/quasar-app-extension-qpdfviewer/src/component/QPdfviewer'

export default ({ app }) => {
  app.component('q-pdfviewer', QPdfviewer)
}

index.js

//api.compatibleWith('@quasar/app', '^1.0.0 || ^2.0.0')
api.compatibleWith('@quasar/app', '^3.0.0')

No other changes were necessary.

Not quite sure if this should be a PR or should perhaps be a different repo/branch for Vue3/Quasar2.

For anyone that needs this ASAP, you can follow the procedure for Manually Testing App Extensions. For remote builds, you'll need to temporarily move the source under your source tree and point package.json to the file until the official package gets updated.

hawkeye64 commented 3 years ago

It'll need to be in a different branch. I won't have any time to do this for a while.

CharlieDigital commented 3 years ago

@hawkeye64 if you provide some high level guidance and whatever access is necessary, I can probably manage.

Let me know if you want to coordinate.

hawkeye64 commented 3 years ago

@CharlieDigital DM me on Quasar Discord and I'll give you a link to my personal Discord where we can discuss it.

hawkeye64 commented 3 years ago

Version 2.0.0-alpha.1 is almost complete, thanks to @CharlieDigital for his gracious help. Expect a release sometime next week that works with Quasar v3/Vue v3.

hawkeye64 commented 3 years ago

Released! https://github.com/quasarframework/app-extension-qpdfviewer/releases/tag/v2.0.0-alpha.1