├── .node-version ├── .husky ├── pre-push └── pre-commit ├── .prettierignore ├── .lintstagedrc ├── src ├── images │ ├── icon128.png │ ├── icon16.png │ ├── icon32.png │ ├── icon48.png │ ├── icon64.png │ └── icon.svg ├── js │ ├── helper.ts │ ├── localizer.ts │ ├── popup.ts │ ├── options.ts │ └── background.ts ├── html │ ├── popup.html │ └── options.html ├── css │ ├── root.css │ ├── popup.css │ └── style.css ├── manifest.json └── _locales │ ├── en │ └── messages.json │ └── de │ └── messages.json ├── .prettierrc ├── Quick JIRA ├── Shared (App) │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── icon16.png │ │ │ ├── icon32.png │ │ │ ├── icon64.png │ │ │ ├── icon128.png │ │ │ ├── icon32 1.png │ │ │ ├── image(1).png │ │ │ ├── image(2).png │ │ │ ├── image(3).png │ │ │ ├── image(1) 1.png │ │ │ ├── image(2) 1.png │ │ │ ├── ItunesArtwork@2x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ │ ├── LargeIcon.imageset │ │ │ ├── image(3).png │ │ │ ├── image(3) 1.png │ │ │ ├── image(3) 2.png │ │ │ └── Contents.json │ │ └── AccentColor.colorset │ │ │ └── Contents.json │ ├── Resources │ │ ├── Icon.png │ │ ├── Style.css │ │ ├── Base.lproj │ │ │ └── Main.html │ │ └── Script.js │ └── ViewController.swift ├── macOS (App) │ ├── Info.plist │ ├── Quick JIRA.entitlements │ ├── AppDelegate.swift │ └── Base.lproj │ │ └── Main.storyboard ├── macOS (Extension) │ ├── Quick JIRA.entitlements │ └── Info.plist ├── iOS (App) │ ├── SceneDelegate.swift │ ├── AppDelegate.swift │ ├── Info.plist │ └── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard ├── iOS (Extension) │ └── Info.plist ├── Shared (Extension) │ └── SafariWebExtensionHandler.swift └── Quick JIRA.xcodeproj │ └── project.pbxproj ├── stylelint.config.mjs ├── .gitignore ├── .github ├── dependabot.yml ├── workflows │ ├── npm-audit-fix.yml │ ├── npm-audit.yml │ └── linting.yml └── FUNDING.yml ├── .vscode └── settings.json ├── scripts ├── patch-version.ts └── postbuild.ts ├── .editorconfig ├── tsconfig.json ├── LICENSE ├── eslint.config.mjs ├── package.json ├── CHANGELOG.md └── README.md /.node-version: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | npm test 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.{ts,json,css,md,yml}": ["prettier --write"] 3 | } 4 | -------------------------------------------------------------------------------- /src/images/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/src/images/icon128.png -------------------------------------------------------------------------------- /src/images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/src/images/icon16.png -------------------------------------------------------------------------------- /src/images/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/src/images/icon32.png -------------------------------------------------------------------------------- /src/images/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/src/images/icon48.png -------------------------------------------------------------------------------- /src/images/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/src/images/icon64.png -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 140, 3 | "useTabs": false, 4 | "singleQuote": true, 5 | "tabWidth": 2 6 | } 7 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "author": "xcode", 4 | "version": 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Resources/Icon.png -------------------------------------------------------------------------------- /stylelint.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('stylelint').Config} */ 2 | export default { 3 | extends: ['stylelint-config-recommended'], 4 | }; 5 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon16.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon32.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon64.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon128.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon32 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/icon32 1.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(1).png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(2).png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(3).png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/image(3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/image(3).png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(1) 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(1) 1.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(2) 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/image(2) 1.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/image(3) 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/image(3) 1.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/image(3) 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/image(3) 2.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timbru31/quickjira/HEAD/Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | release_* 3 | node_modules/ 4 | *.zip 5 | dist/ 6 | DerivedData/ 7 | xcuserdata/ 8 | *.xcscmblueprint 9 | *.xccheckout 10 | *.xcuserstate 11 | *.xcworkspace 12 | .build/ 13 | Package.resolved 14 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": [ 3 | { 4 | "idiom": "universal" 5 | } 6 | ], 7 | "info": { 8 | "author": "xcode", 9 | "version": 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: '/' 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: 'github-actions' 8 | directory: '/' 9 | schedule: 10 | interval: 'daily' 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "prettier.tabWidth": 4, 4 | "prettier.printWidth": 140, 5 | "prettier.singleQuote": true, 6 | "editor.renderWhitespace": "all", 7 | "prettier.useTabs": true, 8 | "editor.insertSpaces": false 9 | } 10 | -------------------------------------------------------------------------------- /Quick JIRA/macOS (App)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SFSafariWebExtensionConverterVersion 6 | 16.2 7 | 8 | 9 | -------------------------------------------------------------------------------- /scripts/patch-version.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync, writeFileSync } from 'fs'; 2 | import { version } from '../package.json'; 3 | 4 | const manifest = JSON.parse(readFileSync('./src/manifest.json', { encoding: 'utf-8' })); 5 | manifest.version = version; 6 | writeFileSync('./src/manifest.json', JSON.stringify(manifest, null, '\t')); 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | charset = utf-8 11 | indent_style = tab 12 | indent_size = 4 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.github/workflows/npm-audit-fix.yml: -------------------------------------------------------------------------------- 1 | name: npm audit fix 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | npm-audit-fix: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | steps: 15 | - uses: actions/checkout@v6.0.1 16 | 17 | - uses: ybiquitous/npm-audit-fix-action@v7.3.3 18 | -------------------------------------------------------------------------------- /.github/workflows/npm-audit.yml: -------------------------------------------------------------------------------- 1 | name: Security 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v6.0.1 15 | 16 | - uses: actions/setup-node@v5.0.0 17 | with: 18 | node-version-file: '.node-version' 19 | 20 | - run: npm audit 21 | -------------------------------------------------------------------------------- /Quick JIRA/macOS (Extension)/Quick JIRA.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Quick JIRA/macOS (App)/Quick JIRA.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.network.client 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/js/helper.ts: -------------------------------------------------------------------------------- 1 | const isFirefox = typeof browser !== 'undefined'; 2 | type BrowserType = typeof browser | typeof chrome; 3 | 4 | export const _browser: BrowserType = isFirefox ? browser : chrome; 5 | 6 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 7 | export const storage = _browser.storage.sync || _browser.storage.local; 8 | 9 | export interface Options { 10 | jiraURL: string; 11 | defaultOption: number; 12 | trimSpaces: number; 13 | } 14 | -------------------------------------------------------------------------------- /src/images/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [timbru31] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | custom: https://paypal.me/timbru/ 10 | -------------------------------------------------------------------------------- /Quick JIRA/iOS (App)/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // iOS (App) 4 | // 5 | // Created by tim.brust on 19.01.25. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 15 | guard (scene as? UIWindowScene) != nil else { return } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Quick JIRA/iOS (Extension)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.Safari.web-extension 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Quick JIRA/macOS (Extension)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.Safari.web-extension 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "image(3) 2.png", 5 | "idiom": "universal", 6 | "scale": "1x" 7 | }, 8 | { 9 | "filename": "image(3) 1.png", 10 | "idiom": "universal", 11 | "scale": "2x" 12 | }, 13 | { 14 | "filename": "image(3).png", 15 | "idiom": "universal", 16 | "scale": "3x" 17 | } 18 | ], 19 | "info": { 20 | "author": "xcode", 21 | "version": 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "target": "ES2023", 5 | "module": "ES2022", 6 | "moduleResolution": "node", 7 | "noImplicitAny": true, 8 | "noImplicitReturns": false, 9 | "strictNullChecks": true, 10 | "experimentalDecorators": true, 11 | "strictFunctionTypes": true, 12 | "noImplicitThis": true, 13 | "outDir": "dist/js", 14 | "removeComments": true, 15 | "esModuleInterop": true, 16 | "lib": ["dom", "ES2023"] 17 | }, 18 | "include": ["src/js/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /Quick JIRA/macOS (App)/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // macOS (App) 4 | // 5 | // Created by tim.brust on 19.01.25. 6 | // 7 | 8 | import Cocoa 9 | 10 | @main 11 | class AppDelegate: NSObject, NSApplicationDelegate { 12 | 13 | func applicationDidFinishLaunching(_ notification: Notification) { 14 | // Override point for customization after application launch. 15 | } 16 | 17 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 18 | return true 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /scripts/postbuild.ts: -------------------------------------------------------------------------------- 1 | import { copy } from 'fs-extra'; 2 | import { join, resolve } from 'node:path'; 3 | 4 | const copyFiles = async () => { 5 | const srcDir = resolve(__dirname, '../src'); 6 | const distDir = resolve(__dirname, '../dist'); 7 | 8 | try { 9 | await copy(srcDir, distDir, { 10 | filter: (src) => { 11 | const jsDir = join(srcDir, 'js'); 12 | return !src.startsWith(jsDir); 13 | }, 14 | }); 15 | console.log('Files copied successfully!'); 16 | } catch (err) { 17 | console.error('Error copying files:', err); 18 | process.exit(1); 19 | } 20 | }; 21 | 22 | copyFiles(); 23 | -------------------------------------------------------------------------------- /Quick JIRA/iOS (App)/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // iOS (App) 4 | // 5 | // Created by tim.brust on 19.01.25. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 21 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Quick JIRA/iOS (App)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SFSafariWebExtensionConverterVersion 6 | 16.2 7 | UIApplicationSceneManifest 8 | 9 | UIApplicationSupportsMultipleScenes 10 | 11 | UISceneConfigurations 12 | 13 | UIWindowSceneSessionRoleApplication 14 | 15 | 16 | UISceneConfigurationName 17 | Default Configuration 18 | UISceneDelegateClassName 19 | $(PRODUCT_MODULE_NAME).SceneDelegate 20 | UISceneStoryboardFile 21 | Main 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | name: Linting 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | runs-on: macos-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v6.0.1 15 | 16 | - uses: actions/setup-node@v5.0.0 17 | with: 18 | node-version-file: '.node-version' 19 | 20 | - name: Setup 21 | run: | 22 | brew install swiftlint 23 | swiftlint version 24 | npm ci 25 | 26 | - name: Linting 27 | run: | 28 | npm test 29 | npm run lint:swift 30 | 31 | auto-merge: 32 | runs-on: ubuntu-latest 33 | needs: build 34 | 35 | permissions: 36 | pull-requests: write 37 | contents: write 38 | 39 | steps: 40 | - name: Automatically merge dependabot upgrades 41 | uses: fastify/github-action-merge-dependabot@v3.11.2 42 | with: 43 | target: minor 44 | -------------------------------------------------------------------------------- /src/js/localizer.ts: -------------------------------------------------------------------------------- 1 | import { _browser } from './helper.js'; 2 | 3 | const translate = (messageID: string | undefined) => { 4 | if (!messageID) { 5 | return ''; 6 | } 7 | return _browser.i18n.getMessage(messageID); 8 | }; 9 | 10 | const localizePage = () => { 11 | const elements = Array.from(document.querySelectorAll('[data-i18n]')); 12 | for (const element of elements) { 13 | const i18nAttr = element.getAttribute('data-i18n'); 14 | if (i18nAttr) { 15 | const match = /\[(.*?)\](.*)/.exec(i18nAttr); 16 | if (match) { 17 | // Case 1: Attribute-specific translation 18 | const [attr, key] = match.slice(1); 19 | const translatedText = translate(key); 20 | if (attr === 'textContent') { 21 | element.textContent = translatedText; 22 | } else { 23 | element.setAttribute(attr, translatedText); 24 | } 25 | } else { 26 | // Case 2: Simple textContent replacement 27 | element.textContent = translate(i18nAttr); 28 | } 29 | } 30 | } 31 | }; 32 | 33 | document.addEventListener('DOMContentLoaded', localizePage); 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Tim Brust 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Resources/Style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-user-select: none; 3 | -webkit-user-drag: none; 4 | cursor: default; 5 | } 6 | 7 | :root { 8 | color-scheme: light dark; 9 | 10 | --spacing: 20px; 11 | } 12 | 13 | html { 14 | height: 100%; 15 | } 16 | 17 | body { 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | flex-direction: column; 22 | 23 | gap: var(--spacing); 24 | margin: 0 calc(var(--spacing) * 2); 25 | height: 100%; 26 | 27 | font: -apple-system-short-body; 28 | text-align: center; 29 | } 30 | 31 | body:not(.platform-mac, .platform-ios) :is(.platform-mac, .platform-ios) { 32 | display: none; 33 | } 34 | 35 | body.platform-ios .platform-mac { 36 | display: none; 37 | } 38 | 39 | body.platform-mac .platform-ios { 40 | display: none; 41 | } 42 | 43 | body.platform-ios .platform-mac { 44 | display: none; 45 | } 46 | 47 | body:not(.state-on, .state-off) :is(.state-on, .state-off) { 48 | display: none; 49 | } 50 | 51 | body.state-on :is(.state-off, .state-unknown) { 52 | display: none; 53 | } 54 | 55 | body.state-off :is(.state-on, .state-unknown) { 56 | display: none; 57 | } 58 | 59 | button { 60 | font-size: 1em; 61 | } 62 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Resources/Base.lproj/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Quick JIRA Icon 14 |

You can turn on Quick JIRA’s Safari extension in Settings.

15 |

You can turn on Quick JIRA’s extension in Safari Extensions preferences.

16 |

Quick JIRA’s extension is currently on. You can turn it off in Safari Extensions preferences.

17 |

Quick JIRA’s extension is currently off. You can turn it on in Safari Extensions preferences.

18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import eslint from '@eslint/js'; 4 | import tseslint from 'typescript-eslint'; 5 | import eslintPluginPrettier from 'eslint-plugin-prettier/recommended'; 6 | 7 | export default tseslint.config({ 8 | files: ['**/*.ts'], 9 | extends: [ 10 | eslint.configs.recommended, 11 | ...tseslint.configs.strictTypeChecked, 12 | ...tseslint.configs.stylisticTypeChecked, 13 | eslintPluginPrettier, 14 | ], 15 | rules: { 16 | '@typescript-eslint/no-unused-vars': [ 17 | 'error', 18 | { 19 | args: 'all', 20 | argsIgnorePattern: '^_', 21 | caughtErrors: 'all', 22 | caughtErrorsIgnorePattern: '^_', 23 | destructuredArrayIgnorePattern: '^_', 24 | varsIgnorePattern: '^_', 25 | ignoreRestSiblings: true, 26 | }, 27 | ], 28 | '@typescript-eslint/restrict-template-expressions': [ 29 | 'error', 30 | { 31 | allowNumber: true, 32 | }, 33 | ], 34 | 'prettier/prettier': [ 35 | 'error', 36 | { 37 | endOfLine: 'auto', 38 | }, 39 | ], 40 | }, 41 | languageOptions: { 42 | parserOptions: { 43 | projectService: true, 44 | tsconfigDirName: import.meta.dirname, 45 | }, 46 | }, 47 | }); 48 | -------------------------------------------------------------------------------- /src/html/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Quick JIRA (quiji) 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 | 18 |
19 |
20 | 21 | 22 |
23 | 24 |
25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /src/css/root.css: -------------------------------------------------------------------------------- 1 | /* Root Variables for Colors, Spacing, and Font */ 2 | :root { 3 | /* Light mode colors */ 4 | --primary-color: #0052cc; 5 | --primary-hover-color: #0747a6; 6 | --background-color: #ffffff; 7 | --text-color: #172b4d; 8 | --secondary-text-color: #6b778c; 9 | --border-color: #dfe1e6; 10 | --form-background: #ffffff; 11 | --shadow-color: rgba(9, 30, 66, 0.13); 12 | --url-highlight: #0052cc; 13 | --input-background: #ffffff; 14 | --teal-color: #008da6; 15 | --purple-color: #6554c0; 16 | --disabled-color: #c1c7d0; 17 | 18 | /* Common variables */ 19 | --spacing: 16px; 20 | --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 21 | sans-serif; 22 | } 23 | 24 | /* Dark mode */ 25 | @media (prefers-color-scheme: dark) { 26 | :root { 27 | --primary-color: #2684ff; 28 | --primary-hover-color: #4c9aff; 29 | --background-color: #1d2125; 30 | --text-color: #ffffff; 31 | --secondary-text-color: #a6b5c9; 32 | --border-color: #2e3338; 33 | --form-background: #2e3338; 34 | --shadow-color: rgba(0, 0, 0, 0.2); 35 | --url-highlight: #4c9aff; 36 | --input-background: #1d2125; 37 | --teal-color: #00b8d9; 38 | --purple-color: #8777d9; 39 | --disabled-color: #505f79; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (Extension)/SafariWebExtensionHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SafariWebExtensionHandler.swift 3 | // Shared (Extension) 4 | // 5 | // Created by tim.brust on 19.01.25. 6 | // 7 | 8 | import SafariServices 9 | import os.log 10 | 11 | class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { 12 | 13 | func beginRequest(with context: NSExtensionContext) { 14 | let request = context.inputItems.first as? NSExtensionItem 15 | 16 | let profile: UUID? 17 | if #available(iOS 17.0, macOS 14.0, *) { 18 | profile = request?.userInfo?[SFExtensionProfileKey] as? UUID 19 | } else { 20 | profile = request?.userInfo?["profile"] as? UUID 21 | } 22 | 23 | let message: Any? 24 | if #available(iOS 15.0, macOS 11.0, *) { 25 | message = request?.userInfo?[SFExtensionMessageKey] 26 | } else { 27 | message = request?.userInfo?["message"] 28 | } 29 | 30 | os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", String(describing: message), profile?.uuidString ?? "none") 31 | 32 | let response = NSExtensionItem() 33 | if #available(iOS 15.0, macOS 11.0, *) { 34 | response.userInfo = [ SFExtensionMessageKey: [ "echo": message ] ] 35 | } else { 36 | response.userInfo = [ "message": [ "echo": message ] ] 37 | } 38 | 39 | context.completeRequest(returningItems: [ response ], completionHandler: nil) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Resources/Script.js: -------------------------------------------------------------------------------- 1 | function show(platform, enabled, useSettingsInsteadOfPreferences) { 2 | document.body.classList.add(`platform-${platform}`); 3 | 4 | if (useSettingsInsteadOfPreferences) { 5 | document.getElementsByClassName('platform-mac state-on')[0].innerText = 6 | 'Quick JIRA’s extension is currently on. You can turn it off in the Extensions section of Safari Settings.'; 7 | document.getElementsByClassName('platform-mac state-off')[0].innerText = 8 | 'Quick JIRA’s extension is currently off. You can turn it on in the Extensions section of Safari Settings.'; 9 | document.getElementsByClassName('platform-mac state-unknown')[0].innerText = 10 | 'You can turn on Quick JIRA’s extension in the Extensions section of Safari Settings.'; 11 | document.getElementsByClassName('platform-mac open-preferences')[0].innerText = 'Quit and Open Safari Settings…'; 12 | } 13 | 14 | if (typeof enabled === 'boolean') { 15 | document.body.classList.toggle(`state-on`, enabled); 16 | document.body.classList.toggle(`state-off`, !enabled); 17 | } else { 18 | document.body.classList.remove(`state-on`); 19 | document.body.classList.remove(`state-off`); 20 | } 21 | } 22 | 23 | function openPreferences() { 24 | webkit.messageHandlers.controller.postMessage('open-preferences'); 25 | } 26 | 27 | document.querySelector('button.platform-mac.open-preferences').addEventListener('click', openPreferences); 28 | document.querySelector('button.platform-ios.open-preferences').addEventListener('click', openPreferences); 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quickjira", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "WebExtension for Chrome, Firefox, Edge, Opera and Safari to quickly open JIRA with the corresponding ticket", 6 | "scripts": { 7 | "prepare": "husky", 8 | "prebuild": "rm -rf dist", 9 | "build": "tsc", 10 | "postbuild": "tsx scripts/postbuild.ts", 11 | "eslint": "eslint src/js", 12 | "stylelint": "stylelint 'src/**/*.css'", 13 | "lint": "npm run eslint && npm run stylelint", 14 | "lint:swift": "swiftlint", 15 | "prerelease": "npm run test", 16 | "release": "commit-and-tag-version -s -a", 17 | "postrelease": "npm run build", 18 | "pretest": "npm run lint", 19 | "test": "echo soon!" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/timbru31/quickjira.git" 24 | }, 25 | "author": "Tim Brust ", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/timbru31/quickjira/issues" 29 | }, 30 | "homepage": "https://github.com/timbru31/quickjira#readme", 31 | "devDependencies": { 32 | "@eslint/js": "^9.39.2", 33 | "@types/chrome": "^0.1.32", 34 | "@types/eslint__js": "^9.14.0", 35 | "@types/firefox-webext-browser": "^120.0.4", 36 | "@types/fs-extra": "^11.0.4", 37 | "addons-linter": "^7.20.0", 38 | "commit-and-tag-version": "^12.6.1", 39 | "eslint-config-prettier": "^10.1.8", 40 | "eslint-plugin-prettier": "^5.5.4", 41 | "fs-extra": "^11.3.3", 42 | "husky": "^9.1.7", 43 | "lint-staged": "^16.2.7", 44 | "prettier": "^3.7.4", 45 | "stylelint": "^16.26.1", 46 | "stylelint-config-recommended": "^14.0.1", 47 | "tsx": "^4.21.0", 48 | "typescript": "^5.9.3", 49 | "typescript-eslint": "^8.50.0" 50 | }, 51 | "commit-and-tag-version": { 52 | "scripts": { 53 | "postbump": "tsx scripts/patch-versions.ts && prettier --write src/manifest.json && git add src/manifest.json", 54 | "postchangelog": "prettier --write CHANGELOG.md" 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Quick JIRA", 3 | "short_name": "quiji", 4 | "version": "1.0.0", 5 | "manifest_version": 3, 6 | "author": "Tim 'timbru31' Brust", 7 | "description": "__MSG_appDesc__", 8 | "action": { 9 | "default_icon": { 10 | "16": "images/icon16.png", 11 | "32": "images/icon32.png", 12 | "48": "images/icon48.png", 13 | "64": "images/icon64.png", 14 | "128": "images/icon128.png" 15 | }, 16 | "default_popup": "html/popup.html", 17 | "default_title": "__MSG_defaultTitle__" 18 | }, 19 | "default_locale": "en", 20 | "options_page": "html/options.html", 21 | "permissions": ["activeTab", "contextMenus", "storage", "commands", "scripting"], 22 | "icons": { 23 | "16": "images/icon16.png", 24 | "32": "images/icon32.png", 25 | "48": "images/icon48.png", 26 | "64": "images/icon64.png", 27 | "128": "images/icon128.png" 28 | }, 29 | "commands": { 30 | "open-ticket-in-current-tab": { 31 | "description": "__MSG_openInCurrentTab__", 32 | "suggested_key": { 33 | "default": "Alt+K", 34 | "windows": "Alt+K", 35 | "mac": "Alt+K", 36 | "chromeos": "Alt+K", 37 | "linux": "Alt+K" 38 | } 39 | }, 40 | "open-ticket-in-new-tab": { 41 | "description": "__MSG_openInNewTab__", 42 | "suggested_key": { 43 | "default": "Alt+Shift+K", 44 | "windows": "Alt+Shift+K", 45 | "mac": "Alt+Shift+K", 46 | "chromeos": "Alt+Shift+K", 47 | "linux": "Alt+Shift+K" 48 | } 49 | }, 50 | "_execute_action": { 51 | "suggested_key": { 52 | "default": "Ctrl+Shift+K", 53 | "windows": "Ctrl+Shift+K", 54 | "mac": "Command+Shift+K", 55 | "chromeos": "Ctrl+Shift+K", 56 | "linux": "Ctrl+Shift+K" 57 | } 58 | } 59 | }, 60 | "omnibox": { 61 | "keyword": "quiji" 62 | }, 63 | "background": { 64 | "service_worker": "js/background.js", 65 | "type": "module" 66 | }, 67 | "minimum_chrome_version": "125", 68 | "browser_specific_settings": { 69 | "gecko": { 70 | "id": "{25e741fe-a00f-4568-9197-f5a591f1b56d}" 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | #### v1.0.0 4 | 5 | - Updated extension to manifest v3 6 | 7 | #### v0.11.2 8 | 9 | - Make space trimming configurable 10 | 11 | #### v0.11.1 12 | 13 | - Remove spaces from tickets (by [Jesús Roldán](https://github.com/xeBuz)) 14 | 15 | #### v0.11.0 16 | 17 | - Added Spanish translation (by [Jesús Roldán](https://github.com/xeBuz)) 18 | 19 | #### v0.10.2 (Firefox only) 20 | 21 | - Fix issue that prevented the extension to load when commands are unsupported 22 | 23 | #### v0.10.0 24 | 25 | - Display currently assigned shortcuts on the options page 26 | - Updated logo to reflect the new JIRA logo 27 | 28 | #### v0.9.1 29 | 30 | - Fix omnibox for Firefox when no URL was configured 31 | - Guard Firefox issue when runtime.onInstalled is not available 32 | - Use textContent over innerHTML for localization 33 | 34 | #### v0.9.0 35 | 36 | - Update icons displayed in navigation bar 37 | - Various code refactorings to allow usage on Edge and Firefox 38 | - Fallback to local storage if sync is not available 39 | 40 | #### v0.8.0 41 | 42 | - Add button to open the re-open the last ticket (synced via storage) 43 | - Don't close or submit the popup form when no input is entered 44 | - Fixed omnibox not respecting default setting 45 | 46 | #### v0.7.0 47 | 48 | - Fixed permission for selected text shortcut 49 | 50 | #### v0.6.1 51 | 52 | - Removed deprecated API call 53 | - Added shortcuts to open the selected text as a ticket in the current (Alt + K) or a new tab (Alt + Shift + K) 54 | - Changelog is no longer localized 55 | 56 | #### v0.6 57 | 58 | - Updated to Chrome's new options dialog 59 | - CSS and JS (ES6) updates 60 | - use newer Chrome APIs like runtime.openOptionsPage() 61 | - Minimum Chrome version is now 45 62 | 63 | #### v0.5.1 64 | 65 | - Added support for the QuickSearch URL of JIRA, please refer to the options page for more information. Thanks [@jantimon](https://twitter.com/jantimon) for the hint. 66 | 67 | #### v0.5 68 | 69 | - fixed shortcut (sadly changed to CTRL + SHIFT +K) 70 | - if you experience problems with the new shortcut, please re-install quickjira 71 | - localization updated 72 | 73 | #### v0.4 74 | 75 | - added donation info 76 | - added right click (context menu) options 77 | 78 | #### v0.3.1 79 | 80 | - added link to changelog and options in footer 81 | - new buttons, input fields, overall improved style! 82 | 83 | #### v0.3 84 | 85 | - use Chrome API to close options page 86 | - added welcome page and changelog page 87 | - added footer 88 | 89 | #### v0.2 90 | 91 | - added URL validation 92 | - added omnibox "jira" keyword 93 | 94 | #### v0.1 95 | 96 | - initial release 97 | -------------------------------------------------------------------------------- /Quick JIRA/iOS (App)/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Quick JIRA/iOS (App)/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/html/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

17 |
18 |
19 | 20 |
21 |
22 | 23 |

24 |

25 |

26 | 27 | https://jira.atlassian.com/secure/QuickSearch.jspa?searchString= 28 |

29 | 36 | 37 | 38 |

39 |

40 | 44 | 45 | 46 |

47 |
48 | 49 | 50 |
51 | 52 | 53 |

54 |

55 |
    56 | 57 | 58 |
    59 | 60 |
    61 |
    62 |
    63 |
    64 | 65 |
    66 | • 67 | • 68 | • 69 | 74 | • 75 |
    76 |
    77 | 78 | 79 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Shared (App) 4 | // 5 | // Created by tim.brust on 19.01.25. 6 | // 7 | 8 | import WebKit 9 | 10 | #if os(iOS) 11 | import UIKit 12 | typealias PlatformViewController = UIViewController 13 | #elseif os(macOS) 14 | import Cocoa 15 | import SafariServices 16 | typealias PlatformViewController = NSViewController 17 | #endif 18 | 19 | let extensionBundleIdentifier = "com.yourCompany.Quick-JIRA.Extension" 20 | 21 | class ViewController: PlatformViewController, WKNavigationDelegate, WKScriptMessageHandler { 22 | 23 | @IBOutlet var webView: WKWebView! 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | 28 | self.webView.navigationDelegate = self 29 | 30 | #if os(iOS) 31 | self.webView.scrollView.isScrollEnabled = false 32 | #endif 33 | 34 | self.webView.configuration.userContentController.add(self, name: "controller") 35 | 36 | self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!) 37 | } 38 | 39 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 40 | #if os(iOS) 41 | webView.evaluateJavaScript("show('ios')") 42 | #elseif os(macOS) 43 | webView.evaluateJavaScript("show('mac')") 44 | 45 | SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in 46 | guard let state = state, error == nil else { 47 | // Insert code to inform the user that something went wrong. 48 | return 49 | } 50 | 51 | DispatchQueue.main.async { 52 | if #available(macOS 13, *) { 53 | webView.evaluateJavaScript("show('mac', \(state.isEnabled), true)") 54 | } else { 55 | webView.evaluateJavaScript("show('mac', \(state.isEnabled), false)") 56 | } 57 | } 58 | } 59 | #endif 60 | } 61 | 62 | func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { 63 | guard let body = message.body as? String, body == "open-preferences" else { 64 | return 65 | } 66 | 67 | #if os(iOS) 68 | let urlString: String 69 | let systemVersion = ProcessInfo.processInfo.operatingSystemVersion 70 | 71 | if systemVersion.majorVersion >= 18 { 72 | // iOS 18 and above 73 | urlString = "App-Prefs:com.apple.mobilesafari" 74 | } else if systemVersion.majorVersion == 17 { 75 | // iOS 17 76 | urlString = "Prefs:com.apple.mobilesafari&path=WEB_EXTENSIONS" 77 | } else { 78 | // Fallback for unsupported versions 79 | urlString = "App-prefs:Safari" 80 | } 81 | 82 | if let url = URL(string: urlString) { 83 | UIApplication.shared.open(url, options: [:]) { success in 84 | if !success { 85 | // Optionally handle failure 86 | print("Failed to open Safari settings.") 87 | } 88 | } 89 | } 90 | #elseif os(macOS) 91 | SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in 92 | guard error == nil else { 93 | // Insert code to inform the user that something went wrong. 94 | return 95 | } 96 | 97 | DispatchQueue.main.async { 98 | NSApp.terminate(self) 99 | } 100 | } 101 | #endif 102 | 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/css/popup.css: -------------------------------------------------------------------------------- 1 | /* Popup specific styles */ 2 | body.quiji-popup { 3 | width: 300px; 4 | padding: 16px; 5 | font-family: var(--font-family); 6 | background-color: var(--background-color); 7 | color: var(--text-color); 8 | margin: 0; 9 | } 10 | 11 | .quiji-popup-form h1 { 12 | font-size: 1.5rem; 13 | margin-bottom: 16px; 14 | color: var(--primary-color); 15 | } 16 | 17 | .quiji-input-container { 18 | margin-bottom: 16px; 19 | } 20 | 21 | .quiji-popup-label { 22 | display: block; 23 | margin-bottom: 8px; 24 | font-weight: bold; 25 | } 26 | 27 | .quiji-ticket-id { 28 | width: 100%; 29 | padding: 8px; 30 | border: 1px solid var(--border-color); 31 | border-radius: 6px; 32 | font-size: 1rem; 33 | box-sizing: border-box; 34 | background-color: var(--background-color); 35 | color: var(--text-color); 36 | transition: all 0.2s ease; 37 | } 38 | 39 | .quiji-ticket-id:focus { 40 | outline: none; 41 | border-color: var(--primary-color); 42 | box-shadow: 0 0 0 2px var(--primary-color); 43 | } 44 | 45 | .quiji-buttons { 46 | display: flex; 47 | flex-direction: column; 48 | gap: 8px; 49 | margin-top: 16px; 50 | } 51 | 52 | .quiji-button { 53 | width: 100%; 54 | padding: 10px 12px; 55 | border: none; 56 | border-radius: 6px; 57 | cursor: pointer; 58 | transition: all 0.3s ease; 59 | font-size: 0.9rem; 60 | color: var(--background-color); 61 | font-weight: bold; 62 | } 63 | 64 | .quiji-current-tab { 65 | background-color: var(--primary-color); 66 | } 67 | 68 | .quiji-new-tab { 69 | background-color: #008da6; /* Teal T300 */ 70 | } 71 | 72 | .quiji-spacer { 73 | width: 100%; 74 | border: none; 75 | border-top: 1px solid var(--border-color); 76 | margin: 8px 0; 77 | } 78 | 79 | .quiji-last-ticket { 80 | background-color: #6554c0; /* Purple P300 */ 81 | padding-top: 16px; 82 | } 83 | 84 | .quiji-last-ticket:disabled { 85 | background-color: #c1c7d0; /* Atlassian neutral N40 */ 86 | cursor: not-allowed; 87 | opacity: 0.7; 88 | } 89 | 90 | .quiji-button:hover:not(:disabled), 91 | .quiji-button:focus-visible:not(:disabled) { 92 | filter: brightness(110%); 93 | transform: translateY(-1px); 94 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); 95 | } 96 | 97 | .quiji-button:focus:not(:disabled) { 98 | outline: none; 99 | box-shadow: 100 | 0 0 0 2px var(--background-color), 101 | 0 0 0 4px var(--primary-color); 102 | } 103 | 104 | .quiji-new-tab:focus:not(:disabled) { 105 | box-shadow: 106 | 0 0 0 2px var(--background-color), 107 | 0 0 0 4px #008da6; 108 | } 109 | 110 | .quiji-last-ticket:focus:not(:disabled) { 111 | box-shadow: 112 | 0 0 0 2px var(--background-color), 113 | 0 0 0 4px #6554c0; 114 | } 115 | 116 | .quiji-button:active:not(:disabled) { 117 | transform: translateY(1px); 118 | box-shadow: none; 119 | } 120 | 121 | /* Dark mode */ 122 | @media (prefers-color-scheme: dark) { 123 | .quiji-ticket-id { 124 | background-color: #2e3338; 125 | color: #ffffff; 126 | border-color: #505f79; 127 | } 128 | 129 | .quiji-current-tab { 130 | background-color: var(--primary-color); 131 | } 132 | 133 | .quiji-new-tab { 134 | background-color: var(--teal-color); 135 | } 136 | 137 | .quiji-last-ticket { 138 | background-color: var(--purple-color); 139 | } 140 | 141 | .quiji-spacer { 142 | border-top-color: #505f79; 143 | } 144 | 145 | .quiji-last-ticket:disabled { 146 | background-color: var(--disabled-color); 147 | } 148 | 149 | ::selection { 150 | background-color: var(--primary-hover-color); 151 | color: var(--background-color); 152 | } 153 | } 154 | 155 | /* Light mode selection */ 156 | ::selection { 157 | background-color: var(--primary-color); 158 | color: var(--background-color); 159 | } 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quick JIRA (quiji) 2 | 3 |

    4 | 5 | 6 | 7 | Chrome Web Store 9 | 10 | 11 | 12 | Firefox add-ons 14 | 15 | 16 | 17 | Microsoft Store 19 | 20 | 21 | 22 | Opera add-ons 24 |

    25 |

    26 | 27 | 28 | 29 | TestFlight beta for macOS and iOS 31 |

    32 | 33 | [![Security](https://github.com/timbru31/quickjira/workflows/Security/badge.svg)](https://github.com/timbru31/quickjira/actions?query=workflow%3ASecurity) 34 | [![Linting](https://github.com/timbru31/quickjira/workflows/Linting/badge.svg)](https://github.com/timbru31/quickjira/actions?query=workflow%3ALinting) 35 | 36 | [![Known Vulnerabilities](https://snyk.io/test/github/timbru31/quickjira/badge.svg)](https://snyk.io/test/github/timbru31/quickjira) 37 | 38 | [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) 39 | [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) 40 | 41 | ## Info 42 | 43 | Ever wanted to open a JIRA issue really fast in your browser? 44 | Tired of typing the whole address over and over again? 45 | And even more tired of the awesome omnisearch but the need to delete the old ticket id? 46 | 47 | If you can answer yes, then this extension is for you! 48 | You can now open up a JIRA issue within a second - in your current or a new tab. 49 | 50 | Just configure the "base url" and you are ready to go! 51 | The settings are synced via your browser's account (if signed in) across other browsers. 52 | 53 | ## Features 54 | 55 | - open issue in current or new tab 56 | - re-open last viewed ticket 57 | - shortcuts 58 | - Popup (default is CTRL/CMD + Shift + K) 59 | - Open selected text in the current tab (Alt + K) 60 | - Open selected text in a new tab (Alt + Shift + K) 61 | - omnibox keyword "jira" 62 | - configure default action 63 | - right click (context menu) integration 64 | 65 | ## Changelog 66 | 67 | See [CHANGELOG.md](CHANGELOG.md) for a complete changelog. 68 | 69 | ## Support 70 | 71 | For support please create an issue here at GitHub 72 | 73 | ## Pull Requests 74 | 75 | We welcome pull requests from the community! If you have a feature, bug fix, or improvement, please feel free to contribute. Before submitting your pull request, ensure that you have thoroughly tested your code. Additionally, perform linting using ESLint to maintain code quality and consistency. Your contributions are greatly appreciated and help make this project better for everyone. 76 | 77 | --- 78 | 79 | Built by (c) Tim Brust and contributors. Released under the MIT license. 80 | -------------------------------------------------------------------------------- /src/js/popup.ts: -------------------------------------------------------------------------------- 1 | import { _browser, storage } from './helper.js'; 2 | 3 | // Define an interface for the expected structure of the options object 4 | interface Options { 5 | defaultOption: number; 6 | lastTicket: string; 7 | } 8 | 9 | interface CustomHTMLElement extends HTMLInputElement { 10 | newTab?: boolean; // Use optional chaining if you want it to be optional 11 | } 12 | 13 | interface Message { 14 | action: string; 15 | ticket: string; 16 | newTab: boolean; 17 | } 18 | 19 | const handleSubmit = (event?: Event) => { 20 | if (event) { 21 | event.preventDefault(); 22 | } 23 | 24 | const ticketInput = document.querySelector('.quiji-ticket-id'); 25 | const ticket = ticketInput ? encodeURIComponent(ticketInput.value) : ''; 26 | 27 | if (ticket) { 28 | window.setTimeout(() => { 29 | window.close(); 30 | }, 1000); 31 | 32 | // Use a type assertion to ensure event.target is an HTMLElement 33 | const newTab: boolean = (event?.target as CustomHTMLElement).newTab ?? false; 34 | 35 | // eslint-disable-next-line @typescript-eslint/no-invalid-void-type 36 | void (_browser.runtime as typeof chrome.runtime).sendMessage({ 37 | action: 'openTicket', 38 | ticket: ticket, 39 | newTab: newTab, 40 | }); 41 | } 42 | }; 43 | 44 | const handleLastTicket = (event?: Event, defaultOption?: number, lastTicket?: string) => { 45 | if (event) { 46 | event.preventDefault(); 47 | } 48 | 49 | window.setTimeout(() => { 50 | window.close(); 51 | }, 1000); 52 | 53 | if (lastTicket) { 54 | void (_browser.runtime as typeof chrome.runtime).sendMessage({ 55 | action: 'openTicket', 56 | ticket: lastTicket, 57 | newTab: defaultOption !== 0, 58 | }); 59 | } 60 | }; 61 | 62 | const renderDialog = async () => { 63 | await storage.get( 64 | { 65 | defaultOption: 0, 66 | lastTicket: '', 67 | }, 68 | (options) => { 69 | // Type the options parameter 70 | const form = document.querySelector('.quiji-popup-form'); 71 | const newButton = document.querySelector('.quiji-new-tab'); 72 | const currentButton = document.querySelector('.quiji-current-tab'); 73 | const lastTicketButton = createLastTicketButton(options as Options); 74 | 75 | if (newButton && currentButton && form) { 76 | newButton.newTab = true; 77 | currentButton.newTab = false; 78 | 79 | form.addEventListener('submit', handleSubmit); 80 | newButton.addEventListener('click', handleSubmit); 81 | currentButton.addEventListener('click', handleSubmit); 82 | 83 | // Depending on the option, attach newTab true or false to submit handler 84 | form.newTab = options.defaultOption === 0 ? false : true; 85 | 86 | newButton.value = _browser.i18n.getMessage('newTab'); 87 | currentButton.value = _browser.i18n.getMessage('currentTab'); 88 | lastTicketButton.value = _browser.i18n.getMessage('lastTicket'); 89 | 90 | setTimeout(() => { 91 | document.querySelector('#quiji-ticket-id')?.focus(); 92 | }, 0); 93 | } 94 | }, 95 | ); 96 | }; 97 | 98 | document.addEventListener('DOMContentLoaded', () => { 99 | void renderDialog(); 100 | }); 101 | 102 | function createLastTicketButton(options?: Options) { 103 | const lastTicketButton = document.querySelector('.quiji-last-ticket'); 104 | 105 | if (options && lastTicketButton) { 106 | if (!options.lastTicket) { 107 | lastTicketButton.disabled = true; 108 | } else { 109 | lastTicketButton.addEventListener('click', (e) => { 110 | handleLastTicket(e, options.defaultOption, options.lastTicket); 111 | }); 112 | } 113 | } 114 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 115 | return lastTicketButton!; 116 | } 117 | -------------------------------------------------------------------------------- /src/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": { 3 | "message": "Quick JIRA v2.0.0", 4 | "description": "Please do not alter this value" 5 | }, 6 | "options": { 7 | "message": "Options", 8 | "description": "Link in footer" 9 | }, 10 | "changelog": { 11 | "message": "Changelog", 12 | "description": "Link in footer" 13 | }, 14 | "support": { 15 | "message": "Support", 16 | "description": "Link in footer" 17 | }, 18 | "feedback": { 19 | "message": "Feedback", 20 | "description": "Link in footer" 21 | }, 22 | "handmade": { 23 | "message": "Made with ❤️️ and ☕ by timbru31", 24 | "description": "Text in footer" 25 | }, 26 | "appDesc": { 27 | "message": "Quickly opens the JIRA with the corresponding ticket", 28 | "description": "The description of the application, displayed in the web store." 29 | }, 30 | "currentTab": { 31 | "message": "current tab", 32 | "description": "Button for opening in the current tab" 33 | }, 34 | "newTab": { 35 | "message": "new tab", 36 | "description": "Button for opening in a new tab" 37 | }, 38 | "lastTicket": { 39 | "message": "last ticket", 40 | "description": "Button for opening the last ticket again" 41 | }, 42 | "openInNewTab": { 43 | "message": "Open in a new tab", 44 | "description": "Message display on right click" 45 | }, 46 | "openInCurrentTab": { 47 | "message": "Open in the current tab", 48 | "description": "Message display on right click" 49 | }, 50 | "defaultTitle": { 51 | "message": "Open JIRA tickets fast", 52 | "description": "Message displayed on the settings page of Chrome" 53 | }, 54 | "optionsTitle": { 55 | "message": "Quick JIRA (quiji) Options", 56 | "description": "Title in tab" 57 | }, 58 | "baseURL": { 59 | "message": "JIRA base URL", 60 | "description": "base URL you need to enter for a valid ticket URL" 61 | }, 62 | "baseURLDescription": { 63 | "message": "Please enter here the JIRA URL for the Quick Search. Please keep in mind that the URL should end with an equals sign.", 64 | "description": "Description text of the base URL" 65 | }, 66 | "baseURLExample": { 67 | "message": "For example:", 68 | "description": "Info text with an example JIRA URL. URL is followed after the sentence" 69 | }, 70 | "baseURLMoreInfo": { 71 | "message": " More information regarding the JIRA Quick Search can be found here:", 72 | "description": "Info text for the JIRA QuickSearch function. URL is followed after the sentence" 73 | }, 74 | "defaultAction": { 75 | "message": "Default action", 76 | "description": "Default action (new tab or current tab) for opening a ticket" 77 | }, 78 | "defaultActionDescription": { 79 | "message": "Choose between the default action when the form is submitted via the enter key. Either open the ticket in the current or a new tab.", 80 | "description": "Description text for the default action" 81 | }, 82 | "shortcuts": { 83 | "message": "Keyboard shortcuts", 84 | "description": "Headline for shortcuts" 85 | }, 86 | "shortcutsDescription": { 87 | "message": "List of currently assigned shortcuts", 88 | "description": "Info text for current shortcuts" 89 | }, 90 | "trimSpaces": { 91 | "message": "Trim spaces", 92 | "description": "Headline for trim spaces" 93 | }, 94 | "trimSpacesDescription": { 95 | "message": "Trim spaces from entered tickets. Disable if you plan to use the JIRA Quick Search.", 96 | "description": "Info text for trim spaces" 97 | }, 98 | "saveOptions": { 99 | "message": "Save options", 100 | "description": "Text for button" 101 | }, 102 | "changelogTitle": { 103 | "message": "Quick JIRA (quiji) was updated", 104 | "description": "Title in tab" 105 | }, 106 | "changelogHeader": { 107 | "message": "Changelog of Quick JIRA (quiji)", 108 | "description": "Header of changelog" 109 | }, 110 | "placeholder": { 111 | "message": "Enter ticket ID", 112 | "description": "Placeholder text for the input field" 113 | }, 114 | "unassigned": { 115 | "message": "Unassigned", 116 | "description": "Text for unassigned shortcut" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/_locales/de/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": { 3 | "message": "Quick JIRA v2.0.0", 4 | "description": "Please do not alter this value" 5 | }, 6 | "options": { 7 | "message": "Optionen", 8 | "description": "Link in footer" 9 | }, 10 | "changelog": { 11 | "message": "Changelog", 12 | "description": "Link in footer" 13 | }, 14 | "support": { 15 | "message": "Support", 16 | "description": "Link in footer" 17 | }, 18 | "feedback": { 19 | "message": "Feedback", 20 | "description": "Link in footer" 21 | }, 22 | "handmade": { 23 | "message": "Entwickelt mit ❤️️ und ☕ von timbru31", 24 | "description": "Text in footer" 25 | }, 26 | "appDesc": { 27 | "message": "Öffnet das JIRA mit dem angegebenen Ticket", 28 | "description": "The description of the application, displayed in the web store." 29 | }, 30 | "currentTab": { 31 | "message": "aktueller Tab", 32 | "description": "Button for opening in the current tab" 33 | }, 34 | "newTab": { 35 | "message": "neuer Tab", 36 | "description": "Button for opening in a new tab" 37 | }, 38 | "lastTicket": { 39 | "message": "letztes Ticket", 40 | "description": "Button for opening the last ticket again" 41 | }, 42 | "openInNewTab": { 43 | "message": "In neuem Tab öffnen", 44 | "description": "Message display on right click" 45 | }, 46 | "openInCurrentTab": { 47 | "message": "In aktuellem Tab öffnen", 48 | "description": "Message display on right click" 49 | }, 50 | "defaultTitle": { 51 | "message": "Öffne schnell JIRA Tickets", 52 | "description": "Message displayed on the settings page of Chrome" 53 | }, 54 | "optionsTitle": { 55 | "message": "Quick JIRA (quiji) Optionen", 56 | "description": "Title in tab" 57 | }, 58 | "baseURL": { 59 | "message": "JIRA URL", 60 | "description": "base URL you need to enter for a valid ticket URL" 61 | }, 62 | "baseURLDescription": { 63 | "message": "Bitte gib hier deine JIRA URL zur QuickSearch ein. Beachte, dass die URL mit einem Gleichheitszeichen enden sollte.", 64 | "description": "Description text of the base URL" 65 | }, 66 | "baseURLExample": { 67 | "message": "Zum Beispiel:", 68 | "description": "Info text with an example JIRA URL. URL is followed after the sentence" 69 | }, 70 | "baseURLMoreInfo": { 71 | "message": " Mehr Information zur JIRA QuickSearch findest Du hier:", 72 | "description": "Info text for the JIRA QuickSearch function. URL is followed after the sentence" 73 | }, 74 | "defaultAction": { 75 | "message": "Standard Aktion", 76 | "description": "Default action (new tab or current tab) for opening a ticket" 77 | }, 78 | "defaultActionDescription": { 79 | "message": "Wähle den Standard, was geschehen soll, wenn du das Ticket mit der Enter Taste öffnest. Öffne das Ticket entweder im aktuellen Tab oder in einem neuen Tab.", 80 | "description": "Description text for the default action" 81 | }, 82 | "shortcuts": { 83 | "message": "Tastaturkürzel", 84 | "description": "Headline for shortcuts" 85 | }, 86 | "shortcutsDescription": { 87 | "message": "Aktuell belegete Tastaturkürzel", 88 | "description": "Info text for current shortcuts" 89 | }, 90 | "trimSpaces": { 91 | "message": "Leerzeichen entfernen", 92 | "description": "Headline for trim spaces" 93 | }, 94 | "trimSpacesDescription": { 95 | "message": "Entfernt Leerzeichen von Tickets. Schalte dises Feature aus, wenn du die JIRA Quick Search nutzt.", 96 | "description": "Info text for trim spaces" 97 | }, 98 | "saveOptions": { 99 | "message": "Speichern", 100 | "description": "Text for button" 101 | }, 102 | "changelogTitle": { 103 | "message": "Quick JIRA (quiji) wurde aktualisiert", 104 | "description": "Title in tab" 105 | }, 106 | "changelogHeader": { 107 | "message": "Änderungen von Quick JIRA (quiji)", 108 | "description": "Header of changelog" 109 | }, 110 | "placeholder": { 111 | "message": "Gib die Ticket ID ein", 112 | "description": "Placeholder text for the input field" 113 | }, 114 | "unassigned": { 115 | "message": "Nicht zugewiesen", 116 | "description": "Text for unassigned shortcut" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Quick JIRA/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "Icon-App-20x20@2x.png", 5 | "idiom": "iphone", 6 | "scale": "2x", 7 | "size": "20x20" 8 | }, 9 | { 10 | "filename": "Icon-App-20x20@3x.png", 11 | "idiom": "iphone", 12 | "scale": "3x", 13 | "size": "20x20" 14 | }, 15 | { 16 | "filename": "Icon-App-29x29@1x.png", 17 | "idiom": "iphone", 18 | "scale": "1x", 19 | "size": "29x29" 20 | }, 21 | { 22 | "filename": "Icon-App-29x29@2x.png", 23 | "idiom": "iphone", 24 | "scale": "2x", 25 | "size": "29x29" 26 | }, 27 | { 28 | "filename": "Icon-App-29x29@3x.png", 29 | "idiom": "iphone", 30 | "scale": "3x", 31 | "size": "29x29" 32 | }, 33 | { 34 | "filename": "Icon-App-40x40@2x.png", 35 | "idiom": "iphone", 36 | "scale": "2x", 37 | "size": "40x40" 38 | }, 39 | { 40 | "filename": "Icon-App-40x40@3x.png", 41 | "idiom": "iphone", 42 | "scale": "3x", 43 | "size": "40x40" 44 | }, 45 | { 46 | "filename": "Icon-App-60x60@2x.png", 47 | "idiom": "iphone", 48 | "scale": "2x", 49 | "size": "60x60" 50 | }, 51 | { 52 | "filename": "Icon-App-60x60@3x.png", 53 | "idiom": "iphone", 54 | "scale": "3x", 55 | "size": "60x60" 56 | }, 57 | { 58 | "filename": "Icon-App-20x20@1x.png", 59 | "idiom": "ipad", 60 | "scale": "1x", 61 | "size": "20x20" 62 | }, 63 | { 64 | "filename": "Icon-App-20x20@2x.png", 65 | "idiom": "ipad", 66 | "scale": "2x", 67 | "size": "20x20" 68 | }, 69 | { 70 | "filename": "Icon-App-29x29@1x.png", 71 | "idiom": "ipad", 72 | "scale": "1x", 73 | "size": "29x29" 74 | }, 75 | { 76 | "filename": "Icon-App-29x29@2x.png", 77 | "idiom": "ipad", 78 | "scale": "2x", 79 | "size": "29x29" 80 | }, 81 | { 82 | "filename": "Icon-App-40x40@1x.png", 83 | "idiom": "ipad", 84 | "scale": "1x", 85 | "size": "40x40" 86 | }, 87 | { 88 | "filename": "Icon-App-40x40@2x.png", 89 | "idiom": "ipad", 90 | "scale": "2x", 91 | "size": "40x40" 92 | }, 93 | { 94 | "filename": "Icon-App-76x76@1x.png", 95 | "idiom": "ipad", 96 | "scale": "1x", 97 | "size": "76x76" 98 | }, 99 | { 100 | "filename": "Icon-App-76x76@2x.png", 101 | "idiom": "ipad", 102 | "scale": "2x", 103 | "size": "76x76" 104 | }, 105 | { 106 | "filename": "Icon-App-83.5x83.5@2x.png", 107 | "idiom": "ipad", 108 | "scale": "2x", 109 | "size": "83.5x83.5" 110 | }, 111 | { 112 | "filename": "ItunesArtwork@2x.png", 113 | "idiom": "ios-marketing", 114 | "scale": "1x", 115 | "size": "1024x1024" 116 | }, 117 | { 118 | "filename": "icon16.png", 119 | "idiom": "mac", 120 | "scale": "1x", 121 | "size": "16x16" 122 | }, 123 | { 124 | "filename": "icon32 1.png", 125 | "idiom": "mac", 126 | "scale": "2x", 127 | "size": "16x16" 128 | }, 129 | { 130 | "filename": "icon32.png", 131 | "idiom": "mac", 132 | "scale": "1x", 133 | "size": "32x32" 134 | }, 135 | { 136 | "filename": "icon64.png", 137 | "idiom": "mac", 138 | "scale": "2x", 139 | "size": "32x32" 140 | }, 141 | { 142 | "filename": "icon128.png", 143 | "idiom": "mac", 144 | "scale": "1x", 145 | "size": "128x128" 146 | }, 147 | { 148 | "filename": "image(1).png", 149 | "idiom": "mac", 150 | "scale": "2x", 151 | "size": "128x128" 152 | }, 153 | { 154 | "filename": "image(1) 1.png", 155 | "idiom": "mac", 156 | "scale": "1x", 157 | "size": "256x256" 158 | }, 159 | { 160 | "filename": "image(2) 1.png", 161 | "idiom": "mac", 162 | "scale": "2x", 163 | "size": "256x256" 164 | }, 165 | { 166 | "filename": "image(2).png", 167 | "idiom": "mac", 168 | "scale": "1x", 169 | "size": "512x512" 170 | }, 171 | { 172 | "filename": "image(3).png", 173 | "idiom": "mac", 174 | "scale": "2x", 175 | "size": "512x512" 176 | } 177 | ], 178 | "info": { 179 | "author": "xcode", 180 | "version": 1 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/css/style.css: -------------------------------------------------------------------------------- 1 | /* Global Reset and Styles */ 2 | body, 3 | h1, 4 | h2, 5 | h3, 6 | p, 7 | ul, 8 | li { 9 | margin: 0; 10 | padding: 0; 11 | list-style: none; 12 | } 13 | 14 | body { 15 | background-color: var(--background-color); 16 | font-family: var(--font-family); 17 | color: var(--text-color); 18 | line-height: 1.6; 19 | } 20 | 21 | a { 22 | color: var(--primary-color); 23 | text-decoration: none; 24 | } 25 | 26 | footer a { 27 | color: var(--primary-color); 28 | margin: 0 4px; 29 | } 30 | 31 | a:hover { 32 | color: var(--primary-hover-color); 33 | } 34 | 35 | input, 36 | select, 37 | button { 38 | font-family: var(--font-family); 39 | } 40 | 41 | label { 42 | font-size: 1rem; 43 | } 44 | 45 | /* List Styling */ 46 | ul { 47 | padding-bottom: var(--spacing); 48 | } 49 | 50 | li { 51 | margin-bottom: 8px; 52 | } 53 | 54 | /* Layout and Structure */ 55 | main { 56 | padding: var(--spacing); 57 | max-width: 800px; 58 | margin: auto; 59 | } 60 | 61 | footer { 62 | background-color: var(--background-color); 63 | border-top: 1px solid var(--border-color); 64 | text-align: center; 65 | padding: var(--spacing); 66 | font-size: 0.9rem; 67 | color: var(--secondary-text-color); 68 | } 69 | 70 | footer a:hover { 71 | text-decoration: underline; 72 | } 73 | 74 | header { 75 | text-align: center; 76 | } 77 | 78 | header h1 { 79 | font-size: 2rem; 80 | margin-bottom: 8px; 81 | } 82 | 83 | hr { 84 | border: none; 85 | height: 2px; 86 | background-color: var(--border-color); 87 | margin: 16px 0; 88 | } 89 | 90 | /* Form Styles */ 91 | form { 92 | background-color: var(--form-background); 93 | border: 1px solid var(--border-color); 94 | border-radius: 8px; 95 | box-shadow: 0 2px 8px var(--shadow-color); 96 | padding: 0 var(--spacing); 97 | margin-bottom: var(--spacing); 98 | } 99 | 100 | form h2, 101 | form p { 102 | margin: 10px 0; 103 | } 104 | 105 | form p { 106 | font-size: 1rem; 107 | color: var(--secondary-text-color); 108 | } 109 | 110 | input[type='text'], 111 | select { 112 | width: 100%; 113 | padding: 8px; 114 | margin-bottom: var(--spacing); 115 | border: 1px solid var(--border-color); 116 | border-radius: 4px; 117 | font-size: 1rem; 118 | background-color: var(--input-background); 119 | color: var(--text-color); 120 | box-shadow: inset 0 1px 2px var(--shadow-color); 121 | } 122 | 123 | /* Limit Width for Specific Inputs */ 124 | input[type='text'].quiji-options-jira-url { 125 | max-width: 600px; 126 | } 127 | 128 | select { 129 | max-width: 250px; 130 | } 131 | 132 | /* Trim Spaces - Checkbox */ 133 | div { 134 | display: flex; 135 | align-items: center; 136 | margin-bottom: var(--spacing); 137 | } 138 | 139 | input[type='checkbox'] { 140 | margin-right: 8px; 141 | transform: scale(1.2); 142 | accent-color: var(--primary-color); 143 | } 144 | 145 | /* Shortcuts Styles */ 146 | .quiji-shortcuts li { 147 | font-size: 1rem; 148 | margin-bottom: 8px; 149 | } 150 | 151 | h3.quiji-shortcuts-title { 152 | font-size: 1.2rem; 153 | margin-bottom: 16px; 154 | } 155 | 156 | /* Save Button */ 157 | .quiji-options-save { 158 | background-color: var(--primary-color); 159 | color: #ffffff; 160 | padding: 10px 20px; 161 | border: none; 162 | border-radius: 4px; 163 | cursor: pointer; 164 | font-size: 1.1rem; 165 | display: inline-block; 166 | margin-top: var(--spacing); 167 | transition: all 0.3s ease; 168 | opacity: 1; 169 | transform: scale(1); 170 | } 171 | 172 | .quiji-url-highlight { 173 | color: var(--url-highlight); 174 | font-weight: bold; 175 | text-decoration: underline; 176 | } 177 | 178 | /* Button Container and Checkmark */ 179 | .button-container { 180 | position: relative; 181 | height: 40px; 182 | width: 100%; 183 | } 184 | 185 | .quiji-options-save, 186 | .checkmark { 187 | position: absolute; 188 | top: 0; 189 | left: 0; 190 | right: 0; 191 | bottom: 0; 192 | margin: auto; 193 | transition: all 0.3s ease; 194 | } 195 | 196 | .quiji-options-save.hidden { 197 | opacity: 0; 198 | transform: scale(0.5); 199 | } 200 | 201 | .quiji-options-save:hover { 202 | background-color: var(--primary-hover-color); 203 | } 204 | 205 | .checkmark { 206 | display: flex; 207 | align-items: center; 208 | justify-content: center; 209 | width: 40px; 210 | height: 40px; 211 | border-radius: 50%; 212 | background-color: var(--primary-color); 213 | color: #ffffff; 214 | font-size: 24px; 215 | opacity: 0; 216 | transform: scale(0.5); 217 | } 218 | 219 | .checkmark.visible { 220 | opacity: 1; 221 | transform: scale(1); 222 | } 223 | -------------------------------------------------------------------------------- /src/js/options.ts: -------------------------------------------------------------------------------- 1 | import { _browser, Options, storage } from './helper.js'; 2 | 3 | // Save options function 4 | const saveOptions = async (event: Event) => { 5 | event.preventDefault(); 6 | 7 | const jiraInput = document.querySelector('.quiji-options-jira-url'); 8 | 9 | if (jiraInput) { 10 | // Check for null before accessing properties 11 | const jira = jiraInput.value; 12 | 13 | const selectElement = document.querySelector('select'); 14 | 15 | if (selectElement) { 16 | let defaultOption = selectElement.value; 17 | 18 | // Map currentTab to 0 and newTab to 1 19 | if (_browser.i18n.getMessage('currentTab') === defaultOption) { 20 | defaultOption = '0'; 21 | } else { 22 | defaultOption = '1'; 23 | } 24 | 25 | const trimSpacesCheckbox = document.querySelector('#trim-spaces'); 26 | const trimSpaces = trimSpacesCheckbox?.checked ? 1 : 0; // Check for null 27 | 28 | await storage.set( 29 | { 30 | jiraURL: jira, 31 | defaultOption: parseInt(defaultOption), // Ensure defaultOption is a number 32 | trimSpaces, 33 | }, 34 | () => { 35 | window.setTimeout(() => { 36 | window.close(); 37 | }, 1000); 38 | }, 39 | ); 40 | } 41 | } 42 | }; 43 | 44 | // Restore options function 45 | const restoreOptions = async () => { 46 | const saveButton = document.querySelector('.quiji-options-save'); 47 | if (saveButton) { 48 | saveButton.value = _browser.i18n.getMessage('saveOptions'); 49 | } 50 | 51 | await storage.get( 52 | { 53 | jiraURL: '', 54 | defaultOption: 0, 55 | trimSpaces: 0, 56 | } as Options, 57 | (options) => { 58 | // Type the options parameter 59 | const jiraInput = document.querySelector('.quiji-options-jira-url'); 60 | if (jiraInput) { 61 | jiraInput.value = (options as Options).jiraURL || ''; 62 | } 63 | 64 | // Map 0 to currentTab and 1 to newTab 65 | const selectElement = document.querySelector('select'); 66 | if (selectElement) { 67 | let defaultOption = _browser.i18n.getMessage('currentTab'); 68 | if (options.defaultOption === 1) { 69 | defaultOption = _browser.i18n.getMessage('newTab'); 70 | } 71 | selectElement.value = defaultOption; 72 | } 73 | 74 | const trimSpacesCheckbox = document.querySelector('#trim-spaces'); 75 | if (trimSpacesCheckbox) { 76 | trimSpacesCheckbox.checked = options.trimSpaces === 1; // Check for null 77 | } 78 | }, 79 | ); 80 | }; 81 | 82 | // Create default shortcuts function 83 | const createDefaultShortcuts = (shortcutList: HTMLElement) => { 84 | let listItem = document.createElement('li'); 85 | listItem.textContent = 'Popup: Ctrl+Shift+K'; 86 | shortcutList.appendChild(listItem); 87 | 88 | listItem = document.createElement('li'); 89 | listItem.textContent = `${_browser.i18n.getMessage('openInNewTab')}: Alt+Shift+K`; 90 | shortcutList.appendChild(listItem); 91 | 92 | listItem = document.createElement('li'); 93 | listItem.textContent = `${_browser.i18n.getMessage('openInCurrentTab')}: Alt+K`; 94 | shortcutList.appendChild(listItem); 95 | }; 96 | 97 | // Load shortcuts function 98 | const loadShortcuts = async () => { 99 | const shortcutList = document.querySelector('.quiji-shortcuts'); 100 | if (shortcutList) { 101 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 102 | if (!_browser.commands) { 103 | createDefaultShortcuts(shortcutList); 104 | } else { 105 | await _browser.commands.getAll((commands: chrome.commands.Command[]) => { 106 | commands.forEach((command) => { 107 | const listItem = document.createElement('li'); 108 | switch (command.name) { 109 | case '_execute_action': 110 | case '_execute_browser_action': 111 | listItem.textContent = `Popup: ${command.shortcut === '' ? _browser.i18n.getMessage('unassigned') : (command.shortcut ?? 'Ctrl+Shift+K')}`; 112 | break; 113 | case 'open-ticket-in-new-tab': 114 | listItem.textContent = `${_browser.i18n.getMessage('openInNewTab')}: ${command.shortcut === '' ? _browser.i18n.getMessage('unassigned') : (command.shortcut ?? 'Alt+Shift+K')}`; 115 | break; 116 | case 'open-ticket-in-current-tab': 117 | listItem.textContent = `${_browser.i18n.getMessage('openInCurrentTab')}: ${command.shortcut === '' ? _browser.i18n.getMessage('unassigned') : (command.shortcut ?? 'Alt+K')}`; 118 | break; 119 | } 120 | shortcutList.appendChild(listItem); 121 | }); 122 | }); 123 | } 124 | } 125 | }; 126 | 127 | // Document ready event 128 | document.addEventListener('DOMContentLoaded', () => { 129 | void restoreOptions(); 130 | void loadShortcuts(); 131 | const optionsForm = document.querySelector('.quiji-options'); 132 | if (optionsForm) { 133 | optionsForm.addEventListener('submit', (e) => { 134 | void saveOptions(e); 135 | }); 136 | } 137 | }); 138 | -------------------------------------------------------------------------------- /src/js/background.ts: -------------------------------------------------------------------------------- 1 | import { _browser, Options, storage } from './helper.js'; 2 | 3 | interface Message { 4 | action: string; 5 | ticket: string; 6 | newTab: boolean; 7 | } 8 | 9 | // Listen for messages from popup 10 | _browser.runtime.onMessage.addListener((message: Message, _sender, _sendResponse) => { 11 | if (message.action === 'openTicket') { 12 | const { ticket, newTab } = message; 13 | void openTicket(ticket, newTab); 14 | } 15 | }); 16 | 17 | async function openTicket(ticket: string, newTab: boolean) { 18 | await storage.get( 19 | { 20 | jiraURL: '', 21 | trimSpaces: 0, 22 | }, 23 | (options) => { 24 | const jiraURL = (options as Options).jiraURL; 25 | const trimSpaces = options.trimSpaces !== 0; 26 | let newURL: string; 27 | 28 | if (trimSpaces) { 29 | ticket = decodeURIComponent(ticket).replace(/\s/g, ''); 30 | } 31 | void storage.set({ 32 | lastTicket: ticket, 33 | }); 34 | 35 | if (!jiraURL) { 36 | void _browser.runtime.openOptionsPage(); 37 | } else { 38 | newURL = jiraURL + ticket; 39 | void openURLInTab(newTab, newURL); 40 | } 41 | }, 42 | ); 43 | } 44 | 45 | const handleSelectionCurrent = async (selection: chrome.contextMenus.OnClickData | browser.contextMenus.OnClickData) => { 46 | if (selection.selectionText) { 47 | await openTicket(selection.selectionText, false); 48 | } 49 | }; 50 | 51 | const handleSelectionNew = async (selection: chrome.contextMenus.OnClickData | browser.contextMenus.OnClickData) => { 52 | if (selection.selectionText) { 53 | await openTicket(selection.selectionText, true); 54 | } 55 | }; 56 | 57 | // Create the parent context menu item with an explicit id 58 | const parentId = _browser.contextMenus.create({ 59 | id: 'quick-jira-parent', 60 | title: 'Quick JIRA', 61 | contexts: ['selection'], 62 | }); 63 | 64 | const currentTabString = _browser.i18n.getMessage('openInCurrentTab'); 65 | _browser.contextMenus.create({ 66 | id: 'quick-jira-current-tab', 67 | title: currentTabString, 68 | parentId: parentId, 69 | contexts: ['selection'], 70 | }); 71 | 72 | const newTabString = _browser.i18n.getMessage('openInNewTab'); 73 | _browser.contextMenus.create({ 74 | id: 'quick-jira-new-tab', 75 | title: newTabString, 76 | parentId: parentId, 77 | contexts: ['selection'], 78 | }); 79 | 80 | _browser.contextMenus.onClicked.addListener((info, _tab) => { 81 | if (info.menuItemId === 'quick-jira-current-tab') { 82 | void handleSelectionCurrent(info); 83 | } 84 | if (info.menuItemId === 'quick-jira-new-tab') { 85 | void handleSelectionNew(info); 86 | } 87 | }); 88 | 89 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition 90 | if (_browser.omnibox) { 91 | _browser.omnibox.onInputEntered.addListener((text) => { 92 | void storage.get( 93 | { 94 | defaultOption: 0, 95 | }, 96 | (options) => { 97 | const newTab = options.defaultOption !== 0 || false; 98 | void openTicket(text, newTab); 99 | }, 100 | ); 101 | }); 102 | } 103 | 104 | _browser.commands.onCommand.addListener((cmd) => { 105 | // Get the currently active tab 106 | void _browser.tabs.query({ active: true, currentWindow: true }, (tabs) => { 107 | if (tabs.length > 0) { 108 | const tabId = tabs[0].id; 109 | if (tabId) { 110 | _browser.scripting 111 | .executeScript({ 112 | target: { tabId: tabId, allFrames: true }, 113 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-explicit-any 114 | func: () => window.getSelection()?.toString() as any, 115 | }) 116 | .then((selectedTextPerFrame) => { 117 | if (selectedTextPerFrame.length > 0 && typeof selectedTextPerFrame[0].result === 'string') { 118 | const selectedText = selectedTextPerFrame[0].result; 119 | if (cmd === 'open-ticket-in-current-tab') { 120 | void openTicket(selectedText, false); 121 | } else if (cmd === 'open-ticket-in-new-tab') { 122 | void openTicket(selectedText, true); 123 | } 124 | } 125 | }) 126 | .catch((error: unknown) => { 127 | console.error('Error executing script:', error); 128 | }); 129 | } 130 | } 131 | }); 132 | }); 133 | 134 | _browser.runtime.onInstalled.addListener((details) => { 135 | if (details.reason === 'install') { 136 | try { 137 | void _browser.runtime.openOptionsPage(); 138 | } catch { 139 | const optionsPage = (_browser.runtime.getManifest() as chrome.runtime.Manifest).options_page; 140 | if (optionsPage) { 141 | const optionsPageUrl = _browser.runtime.getURL(optionsPage); 142 | void _browser.tabs.query({ active: true, currentWindow: true }, () => { 143 | void _browser.tabs.create({ url: optionsPageUrl }); 144 | }); 145 | } 146 | } 147 | } 148 | }); 149 | 150 | async function openURLInTab(newTab: boolean, newURL: string) { 151 | await _browser.tabs.query({ active: true, currentWindow: true }, (tabs) => { 152 | if (newTab) { 153 | void _browser.tabs.create({ url: newURL }); 154 | } else if (tabs.length > 0 && tabs[0].id) { 155 | void (_browser.tabs as typeof chrome.tabs).update(tabs[0].id, { 156 | url: newURL, 157 | }); 158 | } 159 | }); 160 | } 161 | -------------------------------------------------------------------------------- /Quick JIRA/macOS (App)/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Quick JIRA/Quick JIRA.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 19F93B142D3D9740009CB6B0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B132D3D9740009CB6B0 /* AppDelegate.swift */; }; 11 | 19F93B162D3D9740009CB6B0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B152D3D9740009CB6B0 /* SceneDelegate.swift */; }; 12 | 19F93B192D3D9740009CB6B0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B172D3D9740009CB6B0 /* LaunchScreen.storyboard */; }; 13 | 19F93B1C2D3D9740009CB6B0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B1A2D3D9740009CB6B0 /* Main.storyboard */; }; 14 | 19F93B252D3D9740009CB6B0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B242D3D9740009CB6B0 /* AppDelegate.swift */; }; 15 | 19F93B282D3D9740009CB6B0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B262D3D9740009CB6B0 /* Main.storyboard */; }; 16 | 19F93B302D3D9740009CB6B0 /* Quick JIRA Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 19F93B2F2D3D9740009CB6B0 /* Quick JIRA Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 17 | 19F93B3A2D3D9740009CB6B0 /* Quick JIRA Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 19F93B392D3D9740009CB6B0 /* Quick JIRA Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 18 | 19F93B402D3D9740009CB6B0 /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B032D3D973D009CB6B0 /* Main.html */; }; 19 | 19F93B412D3D9740009CB6B0 /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B032D3D973D009CB6B0 /* Main.html */; }; 20 | 19F93B422D3D9740009CB6B0 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B052D3D973D009CB6B0 /* Icon.png */; }; 21 | 19F93B432D3D9740009CB6B0 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B052D3D973D009CB6B0 /* Icon.png */; }; 22 | 19F93B442D3D9740009CB6B0 /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B062D3D973D009CB6B0 /* Style.css */; }; 23 | 19F93B452D3D9740009CB6B0 /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B062D3D973D009CB6B0 /* Style.css */; }; 24 | 19F93B462D3D9740009CB6B0 /* Script.js in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B072D3D973D009CB6B0 /* Script.js */; }; 25 | 19F93B472D3D9740009CB6B0 /* Script.js in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B072D3D973D009CB6B0 /* Script.js */; }; 26 | 19F93B482D3D9740009CB6B0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B082D3D973D009CB6B0 /* ViewController.swift */; }; 27 | 19F93B492D3D9740009CB6B0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B082D3D973D009CB6B0 /* ViewController.swift */; }; 28 | 19F93B4A2D3D9740009CB6B0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B092D3D973F009CB6B0 /* Assets.xcassets */; }; 29 | 19F93B4B2D3D9740009CB6B0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B092D3D973F009CB6B0 /* Assets.xcassets */; }; 30 | 19F93B4C2D3D9740009CB6B0 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B0B2D3D973F009CB6B0 /* SafariWebExtensionHandler.swift */; }; 31 | 19F93B4D2D3D9740009CB6B0 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F93B0B2D3D973F009CB6B0 /* SafariWebExtensionHandler.swift */; }; 32 | 19F93B652D3D9740009CB6B0 /* css in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B5F2D3D9740009CB6B0 /* css */; }; 33 | 19F93B662D3D9740009CB6B0 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B602D3D9740009CB6B0 /* images */; }; 34 | 19F93B672D3D9740009CB6B0 /* js in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B612D3D9740009CB6B0 /* js */; }; 35 | 19F93B682D3D9740009CB6B0 /* html in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B622D3D9740009CB6B0 /* html */; }; 36 | 19F93B692D3D9740009CB6B0 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B632D3D9740009CB6B0 /* manifest.json */; }; 37 | 19F93B6A2D3D9740009CB6B0 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B642D3D9740009CB6B0 /* _locales */; }; 38 | 19F93B6B2D3D9740009CB6B0 /* css in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B5F2D3D9740009CB6B0 /* css */; }; 39 | 19F93B6C2D3D9740009CB6B0 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B602D3D9740009CB6B0 /* images */; }; 40 | 19F93B6D2D3D9740009CB6B0 /* js in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B612D3D9740009CB6B0 /* js */; }; 41 | 19F93B6E2D3D9740009CB6B0 /* html in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B622D3D9740009CB6B0 /* html */; }; 42 | 19F93B6F2D3D9740009CB6B0 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B632D3D9740009CB6B0 /* manifest.json */; }; 43 | 19F93B702D3D9740009CB6B0 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 19F93B642D3D9740009CB6B0 /* _locales */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXContainerItemProxy section */ 47 | 19F93B312D3D9740009CB6B0 /* PBXContainerItemProxy */ = { 48 | isa = PBXContainerItemProxy; 49 | containerPortal = 19F93AFD2D3D973D009CB6B0 /* Project object */; 50 | proxyType = 1; 51 | remoteGlobalIDString = 19F93B2E2D3D9740009CB6B0; 52 | remoteInfo = "Quick JIRA Extension (iOS)"; 53 | }; 54 | 19F93B3B2D3D9740009CB6B0 /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = 19F93AFD2D3D973D009CB6B0 /* Project object */; 57 | proxyType = 1; 58 | remoteGlobalIDString = 19F93B382D3D9740009CB6B0; 59 | remoteInfo = "Quick JIRA Extension (macOS)"; 60 | }; 61 | /* End PBXContainerItemProxy section */ 62 | 63 | /* Begin PBXCopyFilesBuildPhase section */ 64 | 19F93B532D3D9740009CB6B0 /* Embed Foundation Extensions */ = { 65 | isa = PBXCopyFilesBuildPhase; 66 | buildActionMask = 2147483647; 67 | dstPath = ""; 68 | dstSubfolderSpec = 13; 69 | files = ( 70 | 19F93B302D3D9740009CB6B0 /* Quick JIRA Extension.appex in Embed Foundation Extensions */, 71 | ); 72 | name = "Embed Foundation Extensions"; 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 19F93B5A2D3D9740009CB6B0 /* Embed Foundation Extensions */ = { 76 | isa = PBXCopyFilesBuildPhase; 77 | buildActionMask = 2147483647; 78 | dstPath = ""; 79 | dstSubfolderSpec = 13; 80 | files = ( 81 | 19F93B3A2D3D9740009CB6B0 /* Quick JIRA Extension.appex in Embed Foundation Extensions */, 82 | ); 83 | name = "Embed Foundation Extensions"; 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXCopyFilesBuildPhase section */ 87 | 88 | /* Begin PBXFileReference section */ 89 | 19F93B042D3D973D009CB6B0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = Base.lproj/Main.html; sourceTree = ""; }; 90 | 19F93B052D3D973D009CB6B0 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; 91 | 19F93B062D3D973D009CB6B0 /* Style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = Style.css; sourceTree = ""; }; 92 | 19F93B072D3D973D009CB6B0 /* Script.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Script.js; sourceTree = ""; }; 93 | 19F93B082D3D973D009CB6B0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 94 | 19F93B092D3D973F009CB6B0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 95 | 19F93B0B2D3D973F009CB6B0 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; 96 | 19F93B102D3D9740009CB6B0 /* Quick JIRA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Quick JIRA.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 97 | 19F93B132D3D9740009CB6B0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 98 | 19F93B152D3D9740009CB6B0 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 99 | 19F93B182D3D9740009CB6B0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 100 | 19F93B1B2D3D9740009CB6B0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 101 | 19F93B1D2D3D9740009CB6B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 102 | 19F93B222D3D9740009CB6B0 /* Quick JIRA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Quick JIRA.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 103 | 19F93B242D3D9740009CB6B0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 104 | 19F93B272D3D9740009CB6B0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 105 | 19F93B292D3D9740009CB6B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 106 | 19F93B2A2D3D9740009CB6B0 /* Quick JIRA.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Quick JIRA.entitlements"; sourceTree = ""; }; 107 | 19F93B2F2D3D9740009CB6B0 /* Quick JIRA Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Quick JIRA Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 108 | 19F93B342D3D9740009CB6B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 109 | 19F93B392D3D9740009CB6B0 /* Quick JIRA Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Quick JIRA Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 110 | 19F93B3E2D3D9740009CB6B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 111 | 19F93B3F2D3D9740009CB6B0 /* Quick JIRA.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Quick JIRA.entitlements"; sourceTree = ""; }; 112 | 19F93B5F2D3D9740009CB6B0 /* css */ = {isa = PBXFileReference; lastKnownFileType = folder; name = css; path = ../../dist/css; sourceTree = ""; }; 113 | 19F93B602D3D9740009CB6B0 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../../dist/images; sourceTree = ""; }; 114 | 19F93B612D3D9740009CB6B0 /* js */ = {isa = PBXFileReference; lastKnownFileType = folder; name = js; path = ../../dist/js; sourceTree = ""; }; 115 | 19F93B622D3D9740009CB6B0 /* html */ = {isa = PBXFileReference; lastKnownFileType = folder; name = html; path = ../../dist/html; sourceTree = ""; }; 116 | 19F93B632D3D9740009CB6B0 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = manifest.json; path = ../../dist/manifest.json; sourceTree = ""; }; 117 | 19F93B642D3D9740009CB6B0 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; name = _locales; path = ../../dist/_locales; sourceTree = ""; }; 118 | /* End PBXFileReference section */ 119 | 120 | /* Begin PBXFrameworksBuildPhase section */ 121 | 19F93B0D2D3D973F009CB6B0 /* Frameworks */ = { 122 | isa = PBXFrameworksBuildPhase; 123 | buildActionMask = 2147483647; 124 | files = ( 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | 19F93B1F2D3D9740009CB6B0 /* Frameworks */ = { 129 | isa = PBXFrameworksBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | 19F93B2C2D3D9740009CB6B0 /* Frameworks */ = { 136 | isa = PBXFrameworksBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | 19F93B362D3D9740009CB6B0 /* Frameworks */ = { 143 | isa = PBXFrameworksBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | ); 147 | runOnlyForDeploymentPostprocessing = 0; 148 | }; 149 | /* End PBXFrameworksBuildPhase section */ 150 | 151 | /* Begin PBXGroup section */ 152 | 19F93AFC2D3D973D009CB6B0 = { 153 | isa = PBXGroup; 154 | children = ( 155 | 19F93B012D3D973D009CB6B0 /* Shared (App) */, 156 | 19F93B0A2D3D973F009CB6B0 /* Shared (Extension) */, 157 | 19F93B122D3D9740009CB6B0 /* iOS (App) */, 158 | 19F93B232D3D9740009CB6B0 /* macOS (App) */, 159 | 19F93B332D3D9740009CB6B0 /* iOS (Extension) */, 160 | 19F93B3D2D3D9740009CB6B0 /* macOS (Extension) */, 161 | 19F93B112D3D9740009CB6B0 /* Products */, 162 | ); 163 | sourceTree = ""; 164 | }; 165 | 19F93B012D3D973D009CB6B0 /* Shared (App) */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 19F93B082D3D973D009CB6B0 /* ViewController.swift */, 169 | 19F93B092D3D973F009CB6B0 /* Assets.xcassets */, 170 | 19F93B022D3D973D009CB6B0 /* Resources */, 171 | ); 172 | path = "Shared (App)"; 173 | sourceTree = ""; 174 | }; 175 | 19F93B022D3D973D009CB6B0 /* Resources */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | 19F93B032D3D973D009CB6B0 /* Main.html */, 179 | 19F93B052D3D973D009CB6B0 /* Icon.png */, 180 | 19F93B062D3D973D009CB6B0 /* Style.css */, 181 | 19F93B072D3D973D009CB6B0 /* Script.js */, 182 | ); 183 | path = Resources; 184 | sourceTree = ""; 185 | }; 186 | 19F93B0A2D3D973F009CB6B0 /* Shared (Extension) */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | 19F93B5E2D3D9740009CB6B0 /* Resources */, 190 | 19F93B0B2D3D973F009CB6B0 /* SafariWebExtensionHandler.swift */, 191 | ); 192 | path = "Shared (Extension)"; 193 | sourceTree = ""; 194 | }; 195 | 19F93B112D3D9740009CB6B0 /* Products */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 19F93B102D3D9740009CB6B0 /* Quick JIRA.app */, 199 | 19F93B222D3D9740009CB6B0 /* Quick JIRA.app */, 200 | 19F93B2F2D3D9740009CB6B0 /* Quick JIRA Extension.appex */, 201 | 19F93B392D3D9740009CB6B0 /* Quick JIRA Extension.appex */, 202 | ); 203 | name = Products; 204 | sourceTree = ""; 205 | }; 206 | 19F93B122D3D9740009CB6B0 /* iOS (App) */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | 19F93B132D3D9740009CB6B0 /* AppDelegate.swift */, 210 | 19F93B152D3D9740009CB6B0 /* SceneDelegate.swift */, 211 | 19F93B172D3D9740009CB6B0 /* LaunchScreen.storyboard */, 212 | 19F93B1A2D3D9740009CB6B0 /* Main.storyboard */, 213 | 19F93B1D2D3D9740009CB6B0 /* Info.plist */, 214 | ); 215 | path = "iOS (App)"; 216 | sourceTree = ""; 217 | }; 218 | 19F93B232D3D9740009CB6B0 /* macOS (App) */ = { 219 | isa = PBXGroup; 220 | children = ( 221 | 19F93B242D3D9740009CB6B0 /* AppDelegate.swift */, 222 | 19F93B262D3D9740009CB6B0 /* Main.storyboard */, 223 | 19F93B292D3D9740009CB6B0 /* Info.plist */, 224 | 19F93B2A2D3D9740009CB6B0 /* Quick JIRA.entitlements */, 225 | ); 226 | path = "macOS (App)"; 227 | sourceTree = ""; 228 | }; 229 | 19F93B332D3D9740009CB6B0 /* iOS (Extension) */ = { 230 | isa = PBXGroup; 231 | children = ( 232 | 19F93B342D3D9740009CB6B0 /* Info.plist */, 233 | ); 234 | path = "iOS (Extension)"; 235 | sourceTree = ""; 236 | }; 237 | 19F93B3D2D3D9740009CB6B0 /* macOS (Extension) */ = { 238 | isa = PBXGroup; 239 | children = ( 240 | 19F93B3E2D3D9740009CB6B0 /* Info.plist */, 241 | 19F93B3F2D3D9740009CB6B0 /* Quick JIRA.entitlements */, 242 | ); 243 | path = "macOS (Extension)"; 244 | sourceTree = ""; 245 | }; 246 | 19F93B5E2D3D9740009CB6B0 /* Resources */ = { 247 | isa = PBXGroup; 248 | children = ( 249 | 19F93B5F2D3D9740009CB6B0 /* css */, 250 | 19F93B602D3D9740009CB6B0 /* images */, 251 | 19F93B612D3D9740009CB6B0 /* js */, 252 | 19F93B622D3D9740009CB6B0 /* html */, 253 | 19F93B632D3D9740009CB6B0 /* manifest.json */, 254 | 19F93B642D3D9740009CB6B0 /* _locales */, 255 | ); 256 | name = Resources; 257 | path = "Shared (Extension)"; 258 | sourceTree = SOURCE_ROOT; 259 | }; 260 | /* End PBXGroup section */ 261 | 262 | /* Begin PBXNativeTarget section */ 263 | 19F93B0F2D3D973F009CB6B0 /* Quick JIRA (iOS) */ = { 264 | isa = PBXNativeTarget; 265 | buildConfigurationList = 19F93B542D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA (iOS)" */; 266 | buildPhases = ( 267 | 19F93B0C2D3D973F009CB6B0 /* Sources */, 268 | 19F93B0D2D3D973F009CB6B0 /* Frameworks */, 269 | 19F93B0E2D3D973F009CB6B0 /* Resources */, 270 | 19F93B532D3D9740009CB6B0 /* Embed Foundation Extensions */, 271 | ); 272 | buildRules = ( 273 | ); 274 | dependencies = ( 275 | 19F93B322D3D9740009CB6B0 /* PBXTargetDependency */, 276 | ); 277 | name = "Quick JIRA (iOS)"; 278 | packageProductDependencies = ( 279 | ); 280 | productName = "Quick JIRA (iOS)"; 281 | productReference = 19F93B102D3D9740009CB6B0 /* Quick JIRA.app */; 282 | productType = "com.apple.product-type.application"; 283 | }; 284 | 19F93B212D3D9740009CB6B0 /* Quick JIRA (macOS) */ = { 285 | isa = PBXNativeTarget; 286 | buildConfigurationList = 19F93B5B2D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA (macOS)" */; 287 | buildPhases = ( 288 | 19F93B1E2D3D9740009CB6B0 /* Sources */, 289 | 19F93B1F2D3D9740009CB6B0 /* Frameworks */, 290 | 19F93B202D3D9740009CB6B0 /* Resources */, 291 | 19F93B5A2D3D9740009CB6B0 /* Embed Foundation Extensions */, 292 | ); 293 | buildRules = ( 294 | ); 295 | dependencies = ( 296 | 19F93B3C2D3D9740009CB6B0 /* PBXTargetDependency */, 297 | ); 298 | name = "Quick JIRA (macOS)"; 299 | packageProductDependencies = ( 300 | ); 301 | productName = "Quick JIRA (macOS)"; 302 | productReference = 19F93B222D3D9740009CB6B0 /* Quick JIRA.app */; 303 | productType = "com.apple.product-type.application"; 304 | }; 305 | 19F93B2E2D3D9740009CB6B0 /* Quick JIRA Extension (iOS) */ = { 306 | isa = PBXNativeTarget; 307 | buildConfigurationList = 19F93B502D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA Extension (iOS)" */; 308 | buildPhases = ( 309 | 19F93B2B2D3D9740009CB6B0 /* Sources */, 310 | 19F93B2C2D3D9740009CB6B0 /* Frameworks */, 311 | 19F93B2D2D3D9740009CB6B0 /* Resources */, 312 | ); 313 | buildRules = ( 314 | ); 315 | dependencies = ( 316 | ); 317 | name = "Quick JIRA Extension (iOS)"; 318 | packageProductDependencies = ( 319 | ); 320 | productName = "Quick JIRA Extension (iOS)"; 321 | productReference = 19F93B2F2D3D9740009CB6B0 /* Quick JIRA Extension.appex */; 322 | productType = "com.apple.product-type.app-extension"; 323 | }; 324 | 19F93B382D3D9740009CB6B0 /* Quick JIRA Extension (macOS) */ = { 325 | isa = PBXNativeTarget; 326 | buildConfigurationList = 19F93B572D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA Extension (macOS)" */; 327 | buildPhases = ( 328 | 19F93B352D3D9740009CB6B0 /* Sources */, 329 | 19F93B362D3D9740009CB6B0 /* Frameworks */, 330 | 19F93B372D3D9740009CB6B0 /* Resources */, 331 | ); 332 | buildRules = ( 333 | ); 334 | dependencies = ( 335 | ); 336 | name = "Quick JIRA Extension (macOS)"; 337 | packageProductDependencies = ( 338 | ); 339 | productName = "Quick JIRA Extension (macOS)"; 340 | productReference = 19F93B392D3D9740009CB6B0 /* Quick JIRA Extension.appex */; 341 | productType = "com.apple.product-type.app-extension"; 342 | }; 343 | /* End PBXNativeTarget section */ 344 | 345 | /* Begin PBXProject section */ 346 | 19F93AFD2D3D973D009CB6B0 /* Project object */ = { 347 | isa = PBXProject; 348 | attributes = { 349 | BuildIndependentTargetsInParallel = 1; 350 | LastSwiftUpdateCheck = 1620; 351 | LastUpgradeCheck = 1620; 352 | TargetAttributes = { 353 | 19F93B0F2D3D973F009CB6B0 = { 354 | CreatedOnToolsVersion = 16.2; 355 | }; 356 | 19F93B212D3D9740009CB6B0 = { 357 | CreatedOnToolsVersion = 16.2; 358 | }; 359 | 19F93B2E2D3D9740009CB6B0 = { 360 | CreatedOnToolsVersion = 16.2; 361 | }; 362 | 19F93B382D3D9740009CB6B0 = { 363 | CreatedOnToolsVersion = 16.2; 364 | }; 365 | }; 366 | }; 367 | buildConfigurationList = 19F93B002D3D973D009CB6B0 /* Build configuration list for PBXProject "Quick JIRA" */; 368 | developmentRegion = en; 369 | hasScannedForEncodings = 0; 370 | knownRegions = ( 371 | en, 372 | Base, 373 | ); 374 | mainGroup = 19F93AFC2D3D973D009CB6B0; 375 | minimizedProjectReferenceProxies = 1; 376 | preferredProjectObjectVersion = 77; 377 | productRefGroup = 19F93B112D3D9740009CB6B0 /* Products */; 378 | projectDirPath = ""; 379 | projectRoot = ""; 380 | targets = ( 381 | 19F93B0F2D3D973F009CB6B0 /* Quick JIRA (iOS) */, 382 | 19F93B212D3D9740009CB6B0 /* Quick JIRA (macOS) */, 383 | 19F93B2E2D3D9740009CB6B0 /* Quick JIRA Extension (iOS) */, 384 | 19F93B382D3D9740009CB6B0 /* Quick JIRA Extension (macOS) */, 385 | ); 386 | }; 387 | /* End PBXProject section */ 388 | 389 | /* Begin PBXResourcesBuildPhase section */ 390 | 19F93B0E2D3D973F009CB6B0 /* Resources */ = { 391 | isa = PBXResourcesBuildPhase; 392 | buildActionMask = 2147483647; 393 | files = ( 394 | 19F93B422D3D9740009CB6B0 /* Icon.png in Resources */, 395 | 19F93B192D3D9740009CB6B0 /* LaunchScreen.storyboard in Resources */, 396 | 19F93B402D3D9740009CB6B0 /* Main.html in Resources */, 397 | 19F93B462D3D9740009CB6B0 /* Script.js in Resources */, 398 | 19F93B4A2D3D9740009CB6B0 /* Assets.xcassets in Resources */, 399 | 19F93B1C2D3D9740009CB6B0 /* Main.storyboard in Resources */, 400 | 19F93B442D3D9740009CB6B0 /* Style.css in Resources */, 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | 19F93B202D3D9740009CB6B0 /* Resources */ = { 405 | isa = PBXResourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | 19F93B432D3D9740009CB6B0 /* Icon.png in Resources */, 409 | 19F93B452D3D9740009CB6B0 /* Style.css in Resources */, 410 | 19F93B282D3D9740009CB6B0 /* Main.storyboard in Resources */, 411 | 19F93B472D3D9740009CB6B0 /* Script.js in Resources */, 412 | 19F93B4B2D3D9740009CB6B0 /* Assets.xcassets in Resources */, 413 | 19F93B412D3D9740009CB6B0 /* Main.html in Resources */, 414 | ); 415 | runOnlyForDeploymentPostprocessing = 0; 416 | }; 417 | 19F93B2D2D3D9740009CB6B0 /* Resources */ = { 418 | isa = PBXResourcesBuildPhase; 419 | buildActionMask = 2147483647; 420 | files = ( 421 | 19F93B702D3D9740009CB6B0 /* _locales in Resources */, 422 | 19F93B6C2D3D9740009CB6B0 /* images in Resources */, 423 | 19F93B6E2D3D9740009CB6B0 /* html in Resources */, 424 | 19F93B6F2D3D9740009CB6B0 /* manifest.json in Resources */, 425 | 19F93B6D2D3D9740009CB6B0 /* js in Resources */, 426 | 19F93B6B2D3D9740009CB6B0 /* css in Resources */, 427 | ); 428 | runOnlyForDeploymentPostprocessing = 0; 429 | }; 430 | 19F93B372D3D9740009CB6B0 /* Resources */ = { 431 | isa = PBXResourcesBuildPhase; 432 | buildActionMask = 2147483647; 433 | files = ( 434 | 19F93B6A2D3D9740009CB6B0 /* _locales in Resources */, 435 | 19F93B662D3D9740009CB6B0 /* images in Resources */, 436 | 19F93B682D3D9740009CB6B0 /* html in Resources */, 437 | 19F93B692D3D9740009CB6B0 /* manifest.json in Resources */, 438 | 19F93B672D3D9740009CB6B0 /* js in Resources */, 439 | 19F93B652D3D9740009CB6B0 /* css in Resources */, 440 | ); 441 | runOnlyForDeploymentPostprocessing = 0; 442 | }; 443 | /* End PBXResourcesBuildPhase section */ 444 | 445 | /* Begin PBXSourcesBuildPhase section */ 446 | 19F93B0C2D3D973F009CB6B0 /* Sources */ = { 447 | isa = PBXSourcesBuildPhase; 448 | buildActionMask = 2147483647; 449 | files = ( 450 | 19F93B482D3D9740009CB6B0 /* ViewController.swift in Sources */, 451 | 19F93B142D3D9740009CB6B0 /* AppDelegate.swift in Sources */, 452 | 19F93B162D3D9740009CB6B0 /* SceneDelegate.swift in Sources */, 453 | ); 454 | runOnlyForDeploymentPostprocessing = 0; 455 | }; 456 | 19F93B1E2D3D9740009CB6B0 /* Sources */ = { 457 | isa = PBXSourcesBuildPhase; 458 | buildActionMask = 2147483647; 459 | files = ( 460 | 19F93B492D3D9740009CB6B0 /* ViewController.swift in Sources */, 461 | 19F93B252D3D9740009CB6B0 /* AppDelegate.swift in Sources */, 462 | ); 463 | runOnlyForDeploymentPostprocessing = 0; 464 | }; 465 | 19F93B2B2D3D9740009CB6B0 /* Sources */ = { 466 | isa = PBXSourcesBuildPhase; 467 | buildActionMask = 2147483647; 468 | files = ( 469 | 19F93B4C2D3D9740009CB6B0 /* SafariWebExtensionHandler.swift in Sources */, 470 | ); 471 | runOnlyForDeploymentPostprocessing = 0; 472 | }; 473 | 19F93B352D3D9740009CB6B0 /* Sources */ = { 474 | isa = PBXSourcesBuildPhase; 475 | buildActionMask = 2147483647; 476 | files = ( 477 | 19F93B4D2D3D9740009CB6B0 /* SafariWebExtensionHandler.swift in Sources */, 478 | ); 479 | runOnlyForDeploymentPostprocessing = 0; 480 | }; 481 | /* End PBXSourcesBuildPhase section */ 482 | 483 | /* Begin PBXTargetDependency section */ 484 | 19F93B322D3D9740009CB6B0 /* PBXTargetDependency */ = { 485 | isa = PBXTargetDependency; 486 | target = 19F93B2E2D3D9740009CB6B0 /* Quick JIRA Extension (iOS) */; 487 | targetProxy = 19F93B312D3D9740009CB6B0 /* PBXContainerItemProxy */; 488 | }; 489 | 19F93B3C2D3D9740009CB6B0 /* PBXTargetDependency */ = { 490 | isa = PBXTargetDependency; 491 | target = 19F93B382D3D9740009CB6B0 /* Quick JIRA Extension (macOS) */; 492 | targetProxy = 19F93B3B2D3D9740009CB6B0 /* PBXContainerItemProxy */; 493 | }; 494 | /* End PBXTargetDependency section */ 495 | 496 | /* Begin PBXVariantGroup section */ 497 | 19F93B032D3D973D009CB6B0 /* Main.html */ = { 498 | isa = PBXVariantGroup; 499 | children = ( 500 | 19F93B042D3D973D009CB6B0 /* Base */, 501 | ); 502 | name = Main.html; 503 | sourceTree = ""; 504 | }; 505 | 19F93B172D3D9740009CB6B0 /* LaunchScreen.storyboard */ = { 506 | isa = PBXVariantGroup; 507 | children = ( 508 | 19F93B182D3D9740009CB6B0 /* Base */, 509 | ); 510 | name = LaunchScreen.storyboard; 511 | sourceTree = ""; 512 | }; 513 | 19F93B1A2D3D9740009CB6B0 /* Main.storyboard */ = { 514 | isa = PBXVariantGroup; 515 | children = ( 516 | 19F93B1B2D3D9740009CB6B0 /* Base */, 517 | ); 518 | name = Main.storyboard; 519 | sourceTree = ""; 520 | }; 521 | 19F93B262D3D9740009CB6B0 /* Main.storyboard */ = { 522 | isa = PBXVariantGroup; 523 | children = ( 524 | 19F93B272D3D9740009CB6B0 /* Base */, 525 | ); 526 | name = Main.storyboard; 527 | sourceTree = ""; 528 | }; 529 | /* End PBXVariantGroup section */ 530 | 531 | /* Begin XCBuildConfiguration section */ 532 | 19F93B4E2D3D9740009CB6B0 /* Debug */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | ALWAYS_SEARCH_USER_PATHS = NO; 536 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 537 | CLANG_ANALYZER_NONNULL = YES; 538 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 539 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 540 | CLANG_ENABLE_MODULES = YES; 541 | CLANG_ENABLE_OBJC_ARC = YES; 542 | CLANG_ENABLE_OBJC_WEAK = YES; 543 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 544 | CLANG_WARN_BOOL_CONVERSION = YES; 545 | CLANG_WARN_COMMA = YES; 546 | CLANG_WARN_CONSTANT_CONVERSION = YES; 547 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 548 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 549 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 550 | CLANG_WARN_EMPTY_BODY = YES; 551 | CLANG_WARN_ENUM_CONVERSION = YES; 552 | CLANG_WARN_INFINITE_RECURSION = YES; 553 | CLANG_WARN_INT_CONVERSION = YES; 554 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 555 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 556 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 557 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 558 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 559 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 560 | CLANG_WARN_STRICT_PROTOTYPES = YES; 561 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 562 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 563 | CLANG_WARN_UNREACHABLE_CODE = YES; 564 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 565 | COPY_PHASE_STRIP = NO; 566 | DEBUG_INFORMATION_FORMAT = dwarf; 567 | ENABLE_STRICT_OBJC_MSGSEND = YES; 568 | ENABLE_TESTABILITY = YES; 569 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 570 | GCC_C_LANGUAGE_STANDARD = gnu17; 571 | GCC_DYNAMIC_NO_PIC = NO; 572 | GCC_NO_COMMON_BLOCKS = YES; 573 | GCC_OPTIMIZATION_LEVEL = 0; 574 | GCC_PREPROCESSOR_DEFINITIONS = ( 575 | "DEBUG=1", 576 | "$(inherited)", 577 | ); 578 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 579 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 580 | GCC_WARN_UNDECLARED_SELECTOR = YES; 581 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 582 | GCC_WARN_UNUSED_FUNCTION = YES; 583 | GCC_WARN_UNUSED_VARIABLE = YES; 584 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 585 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 586 | MTL_FAST_MATH = YES; 587 | ONLY_ACTIVE_ARCH = YES; 588 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 589 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 590 | }; 591 | name = Debug; 592 | }; 593 | 19F93B4F2D3D9740009CB6B0 /* Release */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ALWAYS_SEARCH_USER_PATHS = NO; 597 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 598 | CLANG_ANALYZER_NONNULL = YES; 599 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 600 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 601 | CLANG_ENABLE_MODULES = YES; 602 | CLANG_ENABLE_OBJC_ARC = YES; 603 | CLANG_ENABLE_OBJC_WEAK = YES; 604 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 605 | CLANG_WARN_BOOL_CONVERSION = YES; 606 | CLANG_WARN_COMMA = YES; 607 | CLANG_WARN_CONSTANT_CONVERSION = YES; 608 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 609 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 610 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 611 | CLANG_WARN_EMPTY_BODY = YES; 612 | CLANG_WARN_ENUM_CONVERSION = YES; 613 | CLANG_WARN_INFINITE_RECURSION = YES; 614 | CLANG_WARN_INT_CONVERSION = YES; 615 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 616 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 617 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 618 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 619 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 620 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 621 | CLANG_WARN_STRICT_PROTOTYPES = YES; 622 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 623 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 624 | CLANG_WARN_UNREACHABLE_CODE = YES; 625 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 626 | COPY_PHASE_STRIP = NO; 627 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 628 | ENABLE_NS_ASSERTIONS = NO; 629 | ENABLE_STRICT_OBJC_MSGSEND = YES; 630 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 631 | GCC_C_LANGUAGE_STANDARD = gnu17; 632 | GCC_NO_COMMON_BLOCKS = YES; 633 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 634 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 635 | GCC_WARN_UNDECLARED_SELECTOR = YES; 636 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 637 | GCC_WARN_UNUSED_FUNCTION = YES; 638 | GCC_WARN_UNUSED_VARIABLE = YES; 639 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 640 | MTL_ENABLE_DEBUG_INFO = NO; 641 | MTL_FAST_MATH = YES; 642 | SWIFT_COMPILATION_MODE = wholemodule; 643 | }; 644 | name = Release; 645 | }; 646 | 19F93B512D3D9740009CB6B0 /* Debug */ = { 647 | isa = XCBuildConfiguration; 648 | buildSettings = { 649 | CODE_SIGN_STYLE = Automatic; 650 | CURRENT_PROJECT_VERSION = 1; 651 | DEVELOPMENT_TEAM = JR7SKSGWZH; 652 | GENERATE_INFOPLIST_FILE = YES; 653 | INFOPLIST_FILE = "iOS (Extension)/Info.plist"; 654 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA Extension"; 655 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 656 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 657 | LD_RUNPATH_SEARCH_PATHS = ( 658 | "$(inherited)", 659 | "@executable_path/Frameworks", 660 | "@executable_path/../../Frameworks", 661 | ); 662 | MARKETING_VERSION = 2.0.0; 663 | OTHER_LDFLAGS = ( 664 | "-framework", 665 | SafariServices, 666 | ); 667 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA.Extension"; 668 | PRODUCT_NAME = "Quick JIRA Extension"; 669 | SDKROOT = iphoneos; 670 | SKIP_INSTALL = YES; 671 | SWIFT_EMIT_LOC_STRINGS = YES; 672 | SWIFT_VERSION = 5.0; 673 | TARGETED_DEVICE_FAMILY = "1,2"; 674 | }; 675 | name = Debug; 676 | }; 677 | 19F93B522D3D9740009CB6B0 /* Release */ = { 678 | isa = XCBuildConfiguration; 679 | buildSettings = { 680 | CODE_SIGN_STYLE = Automatic; 681 | CURRENT_PROJECT_VERSION = 1; 682 | DEVELOPMENT_TEAM = JR7SKSGWZH; 683 | GENERATE_INFOPLIST_FILE = YES; 684 | INFOPLIST_FILE = "iOS (Extension)/Info.plist"; 685 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA Extension"; 686 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 687 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 688 | LD_RUNPATH_SEARCH_PATHS = ( 689 | "$(inherited)", 690 | "@executable_path/Frameworks", 691 | "@executable_path/../../Frameworks", 692 | ); 693 | MARKETING_VERSION = 2.0.0; 694 | OTHER_LDFLAGS = ( 695 | "-framework", 696 | SafariServices, 697 | ); 698 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA.Extension"; 699 | PRODUCT_NAME = "Quick JIRA Extension"; 700 | SDKROOT = iphoneos; 701 | SKIP_INSTALL = YES; 702 | SWIFT_EMIT_LOC_STRINGS = YES; 703 | SWIFT_VERSION = 5.0; 704 | TARGETED_DEVICE_FAMILY = "1,2"; 705 | VALIDATE_PRODUCT = YES; 706 | }; 707 | name = Release; 708 | }; 709 | 19F93B552D3D9740009CB6B0 /* Debug */ = { 710 | isa = XCBuildConfiguration; 711 | buildSettings = { 712 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 713 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 714 | CODE_SIGN_STYLE = Automatic; 715 | CURRENT_PROJECT_VERSION = 1; 716 | DEVELOPMENT_TEAM = JR7SKSGWZH; 717 | GENERATE_INFOPLIST_FILE = YES; 718 | INFOPLIST_FILE = "iOS (App)/Info.plist"; 719 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA"; 720 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business"; 721 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 722 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 723 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 724 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 725 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 726 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 727 | LD_RUNPATH_SEARCH_PATHS = ( 728 | "$(inherited)", 729 | "@executable_path/Frameworks", 730 | ); 731 | MARKETING_VERSION = 2.0.0; 732 | OTHER_LDFLAGS = ( 733 | "-framework", 734 | SafariServices, 735 | "-framework", 736 | WebKit, 737 | ); 738 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA"; 739 | PRODUCT_NAME = "Quick JIRA"; 740 | SDKROOT = iphoneos; 741 | SWIFT_EMIT_LOC_STRINGS = YES; 742 | SWIFT_VERSION = 5.0; 743 | TARGETED_DEVICE_FAMILY = "1,2"; 744 | }; 745 | name = Debug; 746 | }; 747 | 19F93B562D3D9740009CB6B0 /* Release */ = { 748 | isa = XCBuildConfiguration; 749 | buildSettings = { 750 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 751 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 752 | CODE_SIGN_STYLE = Automatic; 753 | CURRENT_PROJECT_VERSION = 1; 754 | DEVELOPMENT_TEAM = JR7SKSGWZH; 755 | GENERATE_INFOPLIST_FILE = YES; 756 | INFOPLIST_FILE = "iOS (App)/Info.plist"; 757 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA"; 758 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business"; 759 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 760 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 761 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 762 | INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 763 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 764 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 765 | LD_RUNPATH_SEARCH_PATHS = ( 766 | "$(inherited)", 767 | "@executable_path/Frameworks", 768 | ); 769 | MARKETING_VERSION = 2.0.0; 770 | OTHER_LDFLAGS = ( 771 | "-framework", 772 | SafariServices, 773 | "-framework", 774 | WebKit, 775 | ); 776 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA"; 777 | PRODUCT_NAME = "Quick JIRA"; 778 | SDKROOT = iphoneos; 779 | SWIFT_EMIT_LOC_STRINGS = YES; 780 | SWIFT_VERSION = 5.0; 781 | TARGETED_DEVICE_FAMILY = "1,2"; 782 | VALIDATE_PRODUCT = YES; 783 | }; 784 | name = Release; 785 | }; 786 | 19F93B582D3D9740009CB6B0 /* Debug */ = { 787 | isa = XCBuildConfiguration; 788 | buildSettings = { 789 | CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/Quick JIRA.entitlements"; 790 | CODE_SIGN_STYLE = Automatic; 791 | CURRENT_PROJECT_VERSION = 1; 792 | DEVELOPMENT_TEAM = JR7SKSGWZH; 793 | ENABLE_HARDENED_RUNTIME = YES; 794 | GENERATE_INFOPLIST_FILE = YES; 795 | INFOPLIST_FILE = "macOS (Extension)/Info.plist"; 796 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA Extension"; 797 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 798 | LD_RUNPATH_SEARCH_PATHS = ( 799 | "$(inherited)", 800 | "@executable_path/../Frameworks", 801 | "@executable_path/../../../../Frameworks", 802 | ); 803 | MACOSX_DEPLOYMENT_TARGET = 10.14; 804 | MARKETING_VERSION = 2.0.0; 805 | OTHER_LDFLAGS = ( 806 | "-framework", 807 | SafariServices, 808 | ); 809 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA.Extension"; 810 | PRODUCT_NAME = "Quick JIRA Extension"; 811 | SDKROOT = macosx; 812 | SKIP_INSTALL = YES; 813 | SWIFT_EMIT_LOC_STRINGS = YES; 814 | SWIFT_VERSION = 5.0; 815 | }; 816 | name = Debug; 817 | }; 818 | 19F93B592D3D9740009CB6B0 /* Release */ = { 819 | isa = XCBuildConfiguration; 820 | buildSettings = { 821 | CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/Quick JIRA.entitlements"; 822 | CODE_SIGN_STYLE = Automatic; 823 | CURRENT_PROJECT_VERSION = 1; 824 | DEVELOPMENT_TEAM = JR7SKSGWZH; 825 | ENABLE_HARDENED_RUNTIME = YES; 826 | GENERATE_INFOPLIST_FILE = YES; 827 | INFOPLIST_FILE = "macOS (Extension)/Info.plist"; 828 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA Extension"; 829 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 830 | LD_RUNPATH_SEARCH_PATHS = ( 831 | "$(inherited)", 832 | "@executable_path/../Frameworks", 833 | "@executable_path/../../../../Frameworks", 834 | ); 835 | MACOSX_DEPLOYMENT_TARGET = 10.14; 836 | MARKETING_VERSION = 2.0.0; 837 | OTHER_LDFLAGS = ( 838 | "-framework", 839 | SafariServices, 840 | ); 841 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA.Extension"; 842 | PRODUCT_NAME = "Quick JIRA Extension"; 843 | SDKROOT = macosx; 844 | SKIP_INSTALL = YES; 845 | SWIFT_EMIT_LOC_STRINGS = YES; 846 | SWIFT_VERSION = 5.0; 847 | }; 848 | name = Release; 849 | }; 850 | 19F93B5C2D3D9740009CB6B0 /* Debug */ = { 851 | isa = XCBuildConfiguration; 852 | buildSettings = { 853 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 854 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 855 | CODE_SIGN_ENTITLEMENTS = "macOS (App)/Quick JIRA.entitlements"; 856 | CODE_SIGN_STYLE = Automatic; 857 | CURRENT_PROJECT_VERSION = 1; 858 | DEVELOPMENT_TEAM = JR7SKSGWZH; 859 | ENABLE_HARDENED_RUNTIME = YES; 860 | GENERATE_INFOPLIST_FILE = YES; 861 | INFOPLIST_FILE = "macOS (App)/Info.plist"; 862 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA"; 863 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business"; 864 | INFOPLIST_KEY_NSMainStoryboardFile = Main; 865 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 866 | LD_RUNPATH_SEARCH_PATHS = ( 867 | "$(inherited)", 868 | "@executable_path/../Frameworks", 869 | ); 870 | MACOSX_DEPLOYMENT_TARGET = 10.14; 871 | MARKETING_VERSION = 2.0.0; 872 | OTHER_LDFLAGS = ( 873 | "-framework", 874 | SafariServices, 875 | "-framework", 876 | WebKit, 877 | ); 878 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA"; 879 | PRODUCT_NAME = "Quick JIRA"; 880 | SDKROOT = macosx; 881 | SWIFT_EMIT_LOC_STRINGS = YES; 882 | SWIFT_VERSION = 5.0; 883 | }; 884 | name = Debug; 885 | }; 886 | 19F93B5D2D3D9740009CB6B0 /* Release */ = { 887 | isa = XCBuildConfiguration; 888 | buildSettings = { 889 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 890 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 891 | CODE_SIGN_ENTITLEMENTS = "macOS (App)/Quick JIRA.entitlements"; 892 | CODE_SIGN_STYLE = Automatic; 893 | CURRENT_PROJECT_VERSION = 1; 894 | DEVELOPMENT_TEAM = JR7SKSGWZH; 895 | ENABLE_HARDENED_RUNTIME = YES; 896 | GENERATE_INFOPLIST_FILE = YES; 897 | INFOPLIST_FILE = "macOS (App)/Info.plist"; 898 | INFOPLIST_KEY_CFBundleDisplayName = "Quick JIRA"; 899 | INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business"; 900 | INFOPLIST_KEY_NSMainStoryboardFile = Main; 901 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 902 | LD_RUNPATH_SEARCH_PATHS = ( 903 | "$(inherited)", 904 | "@executable_path/../Frameworks", 905 | ); 906 | MACOSX_DEPLOYMENT_TARGET = 10.14; 907 | MARKETING_VERSION = 2.0.0; 908 | OTHER_LDFLAGS = ( 909 | "-framework", 910 | SafariServices, 911 | "-framework", 912 | WebKit, 913 | ); 914 | PRODUCT_BUNDLE_IDENTIFIER = "de.dustplanet.Quick-JIRA"; 915 | PRODUCT_NAME = "Quick JIRA"; 916 | SDKROOT = macosx; 917 | SWIFT_EMIT_LOC_STRINGS = YES; 918 | SWIFT_VERSION = 5.0; 919 | }; 920 | name = Release; 921 | }; 922 | /* End XCBuildConfiguration section */ 923 | 924 | /* Begin XCConfigurationList section */ 925 | 19F93B002D3D973D009CB6B0 /* Build configuration list for PBXProject "Quick JIRA" */ = { 926 | isa = XCConfigurationList; 927 | buildConfigurations = ( 928 | 19F93B4E2D3D9740009CB6B0 /* Debug */, 929 | 19F93B4F2D3D9740009CB6B0 /* Release */, 930 | ); 931 | defaultConfigurationIsVisible = 0; 932 | defaultConfigurationName = Release; 933 | }; 934 | 19F93B502D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA Extension (iOS)" */ = { 935 | isa = XCConfigurationList; 936 | buildConfigurations = ( 937 | 19F93B512D3D9740009CB6B0 /* Debug */, 938 | 19F93B522D3D9740009CB6B0 /* Release */, 939 | ); 940 | defaultConfigurationIsVisible = 0; 941 | defaultConfigurationName = Release; 942 | }; 943 | 19F93B542D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA (iOS)" */ = { 944 | isa = XCConfigurationList; 945 | buildConfigurations = ( 946 | 19F93B552D3D9740009CB6B0 /* Debug */, 947 | 19F93B562D3D9740009CB6B0 /* Release */, 948 | ); 949 | defaultConfigurationIsVisible = 0; 950 | defaultConfigurationName = Release; 951 | }; 952 | 19F93B572D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA Extension (macOS)" */ = { 953 | isa = XCConfigurationList; 954 | buildConfigurations = ( 955 | 19F93B582D3D9740009CB6B0 /* Debug */, 956 | 19F93B592D3D9740009CB6B0 /* Release */, 957 | ); 958 | defaultConfigurationIsVisible = 0; 959 | defaultConfigurationName = Release; 960 | }; 961 | 19F93B5B2D3D9740009CB6B0 /* Build configuration list for PBXNativeTarget "Quick JIRA (macOS)" */ = { 962 | isa = XCConfigurationList; 963 | buildConfigurations = ( 964 | 19F93B5C2D3D9740009CB6B0 /* Debug */, 965 | 19F93B5D2D3D9740009CB6B0 /* Release */, 966 | ); 967 | defaultConfigurationIsVisible = 0; 968 | defaultConfigurationName = Release; 969 | }; 970 | /* End XCConfigurationList section */ 971 | }; 972 | rootObject = 19F93AFD2D3D973D009CB6B0 /* Project object */; 973 | } 974 | --------------------------------------------------------------------------------