diff --git a/system_files/bluefin/etc/bazaar/bazaar.yaml b/system_files/bluefin/etc/bazaar/bazaar.yaml
index a3f6aa9..dd6d842 100644
--- a/system_files/bluefin/etc/bazaar/bazaar.yaml
+++ b/system_files/bluefin/etc/bazaar/bazaar.yaml
@@ -3,3 +3,57 @@ yaml-blocklist-paths:
curated-config-paths:
- /run/host/etc/bazaar/curated.yaml
+
+
+hooks:
+ - id: jetbrains-toolbox
+ when: before-transaction
+ dialogs:
+ - id: jetbrains-warning
+ title: >-
+ JetBrains IDEs are not supported in this format
+ # If true, render inline markup commands in body; see
+ # https://docs.gtk.org/Pango/pango_markup.html
+ body-use-markup: true
+ body: >-
+ This is a JetBrains
+ application and is not officially supported on Flatpak. We
+ recommend using the Toolbox app to manage JetBrains IDEs.
+ # Determines which option will be assumed if the user hits the
+ # escape key or otherwise cancels the dialog
+ default-response-id: cancel
+ options:
+ - id: cancel
+ string: "Cancel"
+ - id: run-ujust
+ string: "Download JetBrains Toolbox"
+ # can be "destructive" or "suggested" or omit for no
+ # styling
+ style: suggested
+ shell: exec python3 /run/host/etc/bazaar/hooks.py
+
+ - id: code
+ when: before-transaction
+ dialogs:
+ - id: code-warning
+ title: >-
+ VS Code like IDEs are not supported in this format
+ # If true, render inline markup commands in body; see
+ # https://docs.gtk.org/Pango/pango_markup.html
+ body-use-markup: true
+ body: >-
+ This is an app based on Visual Studio Code
+ and is not officially supported on Flatpak. We
+ recommend using the Homebrew version of the app instead.
+ # Determines which option will be assumed if the user hits the
+ # escape key or otherwise cancels the dialog
+ default-response-id: cancel
+ options:
+ - id: cancel
+ string: "Cancel"
+ - id: download
+ string: "Download from Homebrew"
+ # can be "destructive" or "suggested" or omit for no
+ # styling
+ style: suggested
+ shell: exec python3 /run/host/etc/bazaar/hooks.py
diff --git a/system_files/bluefin/etc/bazaar/blocklist.yaml b/system_files/bluefin/etc/bazaar/blocklist.yaml
index 0a9d23f..3019d2f 100644
--- a/system_files/bluefin/etc/bazaar/blocklist.yaml
+++ b/system_files/bluefin/etc/bazaar/blocklist.yaml
@@ -1,22 +1,7 @@
blocklists:
- block:
- - com.visualstudio.code
- com.visualstudio.code-oss
- - com.vscodium.codium
- com.vscodium.codium-insiders
- - com.jetbrains.CLion
- - com.jetbrains.DataGrip
- - com.jetbrains.GoLand
- - com.jetbrains.IntelliJ-IDEA-Community
- - com.jetbrains.IntelliJ-IDEA-Ultimate
- - com.jetbrains.PyCharm-Professional
- - com.jetbrains.WebStorm
- - com.jetbrains.PhpStorm
- - com.jetbrains.PyCharm-Community
- - com.jetbrains.Rider
- - com.jetbrains.RubyMine
- - com.jetbrains.RustRover
- - com.google.AndroidStudio
- io.neovim.nvim
- org.vim.Vim
- io.github.zyedidia.micro
diff --git a/system_files/bluefin/etc/bazaar/hooks.py b/system_files/bluefin/etc/bazaar/hooks.py
new file mode 100644
index 0000000..890a116
--- /dev/null
+++ b/system_files/bluefin/etc/bazaar/hooks.py
@@ -0,0 +1,119 @@
+# See https://github.com/kolunmi/bazaar/blob/main/docs/overview.md#hooks
+
+import os, subprocess, sys
+
+unix_timestamp = os.getenv('BAZAAR_HOOK_INITIATED_UNIX_STAMP')
+unix_timestamp_usec = os.getenv('BAZAAR_HOOK_INITIATED_UNIX_STAMP_USEC')
+
+hook_id = os.getenv('BAZAAR_HOOK_ID')
+hook_type = os.getenv('BAZAAR_HOOK_TYPE')
+was_aborted = os.getenv('BAZAAR_HOOK_WAS_ABORTED')
+dialog_id = os.getenv('BAZAAR_HOOK_DIALOG_ID')
+dialog_response_id = os.getenv('BAZAAR_HOOK_DIALOG_RESPONSE_ID')
+
+non_transaction_appid = os.getenv('BAZAAR_APPID')
+transaction_appid = os.getenv('BAZAAR_TS_APPID')
+transaction_type = os.getenv('BAZAAR_TS_TYPE')
+
+stage = os.getenv('BAZAAR_HOOK_STAGE')
+stage_idx = os.getenv('BAZAAR_HOOK_STAGE_IDX')
+
+# ---
+
+def spawn_and_detach(args):
+ subprocess.Popen(args, start_new_session=True, stdout=subprocess.DEVNULL)
+
+def spawn_ujust(id):
+ spawn_and_detach(['flatpak-spawn', '--host', 'xdg-terminal-exec', '-x', f'ujust {id}'])
+
+def spawn_brew(app):
+ brew = '/home/linuxbrew/.linuxbrew/bin/brew'
+ spawn_and_detach([
+ 'flatpak-spawn', '--host', 'xdg-terminal-exec', '-x',
+ 'bash', '-c', f'{brew} install --cask {app}'
+ ])
+
+def handle_jetbrains():
+
+ def appid_is_jetbrains(appid):
+ return appid.startswith('com.jetbrains.') or appid == ('com.google.AndroidStudio')
+
+ match stage:
+ case 'setup':
+ if transaction_type == 'install' and appid_is_jetbrains(transaction_appid):
+ return 'ok'
+ else:
+ return 'pass'
+
+ case 'setup-dialog':
+ return 'ok'
+
+ case 'teardown-dialog':
+ if dialog_response_id == 'run-ujust':
+ return 'ok'
+ else:
+ return 'abort'
+
+ case 'catch':
+ return 'abort'
+
+ case 'action':
+ try:
+ spawn_ujust('install-jetbrains-toolbox')
+ except:
+ pass
+ return ''
+
+ case 'teardown':
+ # always prevent installation of JetBrains flatpaks
+ return 'deny'
+
+def handle_code():
+
+ def appid_is_code(appid):
+ return appid == ('com.visualstudio.code') or appid == ('com.vscodium.codium')
+
+ match stage:
+ case 'setup':
+ if transaction_type == 'install' and appid_is_code(transaction_appid):
+ return 'ok'
+ else:
+ return 'pass'
+
+ case 'setup-dialog':
+ return 'ok'
+
+ case 'teardown-dialog':
+ if dialog_response_id == 'download':
+ return 'ok'
+ else:
+ return 'abort'
+
+ case 'catch':
+ return 'abort'
+
+ case 'action':
+ try:
+ if transaction_appid == ('com.vscodium.codium'):
+ spawn_brew('ublue/tap/vscodium-linux')
+ else:
+ spawn_brew('ublue/tap/visual-studio-code-linux')
+ except:
+ pass
+ return ''
+
+ case 'teardown':
+ return 'deny'
+
+# ---
+
+response = 'pass'
+match hook_id:
+ case 'jetbrains-toolbox':
+ response = handle_jetbrains()
+ case 'code':
+ response = handle_code()
+
+print(response)
+sys.exit(0)
+