ronaldoussoren / py2app

py2app is a Python setuptools command which will allow you to make standalone Mac OS X application bundles and plugins from Python scripts.
Other
340 stars 36 forks source link

Capture deeplink arguments after launch? #499

Closed alvinwan closed 1 year ago

alvinwan commented 1 year ago

While the app is currently running, is it possible to capture deeplink arguments?

Here's a minimal app with deeplink support to reproduce what I mean.

app.py

# write captured arguments to a file
import sys
with open('/Users/test.txt', 'w') as f:
    f.write(sys.argv)
while True:  # run forever to simulate a GUI of some kind
    pass

setup.py

# regular setup for a deeplink + passing args at launch
from setuptools import setup

OPTIONS = {
    'argv_emulation': True,
    'plist': {
        'CFBundleURLTypes': [
            {
                'CFBundleURLName': 'MyApplication',
                'CFBundleURLSchemes': ['myapp'],
            },
        ],
    },
    'strip': True,
}

setup(
    app=['app.py'],
    options={'py2app': OPTIONS},
    setup_requires=['py2app']
)

With this setup, I run the usual packaging.

python setup.py py2app -A
mv dist/app.app /Applications
open dist/app.app
# then close the app

Now I can try the deeplink for "page1".

open myapp://page1

The app opens, and it remains open. At this point, /Users/test.txt contains the deeplink "page1".

['app.py', 'myapp://page1']

Still with the application open, I try a new deeplink for "page2". This focuses the existing application.

open myapp://page2

However, this time, the script isn't rerun as it's already running. If I check /Users/test.txt, it will still be "page1":

['app.py', 'myapp://page1']

Is there a way to setup the deeplink so that the script is rerun (even if the app is already open), making the file above say "page2"?

alvinwan commented 1 year ago

My understanding is that other deeplinking utilities like electron-deeplink handle deeplinking by capturing file open events (index.ts#L85-L86) according to SO.

Then, judging by SO and maybe https://github.com/ronaldoussoren/py2app/issues/490, the above would be achieved by listening for events either (a) using a GUI library handler or (b) by implementing it manually in pyobjc.

In my particular case, I was using pywebview, which I didn't realize could be configured to use qt as an engine. Once that was done, I was able to hack on pywebview to use qtpy's event handler.