-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Full Application Example #34
Open
bootsie123
wants to merge
3
commits into
AdobeDocs:main
Choose a base branch
from
MLH-Fellowship:plugin-info-vue-full-app
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
.DS_Store | ||
node_modules | ||
/dist | ||
|
||
|
||
# local env files | ||
.env.local | ||
.env.*.local | ||
|
||
# Log files | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
|
||
# Editor directories and files | ||
.idea | ||
.vscode | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Plugin Info (Vue) - Full Application | ||
|
||
This plugin is a good place to see a fully developed Adobe Photoshop plugin in practice. This example uses Vue JS and demonstrates working with the following: | ||
|
||
- Multiple entry points (`command` and `panel`) | ||
- Filesystems (using persistent tokens and reading files) | ||
- Persistent data (through localStorage) | ||
- Platform specific features (using UXP `os` module) | ||
- Application specific features (using `uxp.host`) | ||
- Theme Awareness (UXP CSS variables) | ||
|
||
As this is a Vue project, you'll need to do some initial configuration before this will be usable in Adobe Photoshop. | ||
|
||
(For more info on what this plugin does, how it's used, and an in-depth explanation of how it works, refer to the end of this README) | ||
|
||
## Install dependencies | ||
|
||
First ensure that your terminal is in the root of this project. Then: | ||
|
||
For `yarn` users, install all dependencies using: | ||
|
||
``` | ||
yarn install | ||
``` | ||
|
||
For `npm` users, install all dependencies using: | ||
|
||
``` | ||
npm install | ||
``` | ||
|
||
## Build Process | ||
|
||
There are two ways to build the plugin for use in Adobe Photoshop: | ||
|
||
- `yarn watch` or `npm run watch` will build a development version of the plugin, and recompile everytime you make a change to the source files. The result is placed in `dist`. | ||
- `yarn build` or `npm run build` will build a production version of the plugin and place it in `dist`. It will not update every time you make a change to the source files. | ||
|
||
> You **must** run either `watch` or `build` prior to trying to use within Photoshop! | ||
|
||
## Launching in Photoshop | ||
|
||
You can use the UXP Developer Tools to load the plugin into Photoshop. | ||
|
||
If the plugin hasn't already been added to your workspace in the UXP Developer Tools, you can add it by clicking "Add Plugin..." and selecting `dist/manifest.json`. **DO NOT** select the `manifest.json` file inside the `plugin` folder. | ||
|
||
Once added, you can load it into Photoshop by clicking the ••• button on the corresponding row, and clicking "Load". Switch to Photoshop and you should see the starter panel. | ||
|
||
## What this plugin does | ||
|
||
This plugin mainly provides information on any installed UXP or CEP plugins. For UXP plugins, all relevant store information is gathered and displayed. For CEP plugins, only the installed version and plugin type are shown (this is due to the limited information given in the plugin manifest). | ||
|
||
## How to use this plugin | ||
|
||
The usage of this plugin is fairly straightforward after the initial install. Once loaded through the UXP Developer Tool, click on `Load Plugins` to go through the first time configuration process. The setup will guide you through adding both your UXP and CEP plugin paths. For reference, they can usually be found in the following directories: | ||
|
||
#### Windows | ||
|
||
| Type | Plugin Path | | ||
| ----- | ----------------------------------------------------------- | | ||
| `UXP` | `%appdata%\Adobe\UXP\Plugins\External` | | ||
| `CEP` | `C:\\Program Files (x86)\Common Files\Adobe\CEP\extensions` | | ||
|
||
#### macOS | ||
|
||
| Type | Plugin Path | | ||
| ----- | --------------------------------------------------- | | ||
| `UXP` | `~/Library/Application Support/Adobe/UXP/Plugins` | | ||
| `CEP` | `/Library/Application Support/Adobe/CEP/extensions` | | ||
|
||
Once both directories have been selected, click `Finish Setup` to complete the setup process. Afterwards, both your UXP and CEP plugins will be automatically loaded. Simply click on the plugin name in the list to view more information about the plugin. | ||
|
||
At any point in time you can redo the setup process by either clicking on `Reload Plugins` in the home menu or using the plugin command called `Show Setup`. Any stored data can also be deleted by using the `Clear Data` plugin command. | ||
|
||
## The code explained | ||
|
||
This plugin may seem simple on the surface, however, under the hood it uses many built-in UXP provided features. In order to understand what's happening, we'll be taking a closer look at the code by going through a round trip of the user experience. | ||
|
||
### Home menu | ||
|
||
The home menu serves as the navigational hub of the plugin. | ||
|
||
On initial load, we make use of the built-in UXP [localStorage](https://www.adobe.io/photoshop/uxp/uxp/reference-js/Global%20Members/Data%20Storage/LocalStorage/). This works very similarly to `window.localStorage` on browsers and allows our plugin to store non-sensitive information that can persist across multiple sessions. | ||
|
||
Using this, we can see whether or not our user has completed the initial setup and adjust the UI accordingly. | ||
|
||
### Selecting plugin directories | ||
|
||
If a user has not completed the initial setup, or wishes to complete it again, they will be brought to the plugin selection screen. This process is vital to the functionality of the plugin because we need to gain read permissions from the user in order to interact with the plugin directories. | ||
|
||
Using the built-in UXP [os](https://www.adobe.io/photoshop/uxp/uxp/reference-js/Modules/os/OS/) module, we can determine the operating system of the current user and adjust the suggested plugin paths. | ||
|
||
From there, we can use `uxp.storage` to prompt the user to select each directory. This returns an [Entry](https://www.adobe.io/photoshop/uxp/uxp/reference-js/Modules/uxp/Persistent%20File%20Storage/Entry/) object which is then used to generate and save a persistent token. This token allows the plugin to read the corresponding directory across different sessions without needing to prompt the user for permission each time. | ||
|
||
_Note: This token can expire. Therefore it's a good idea to check it at the start of each session_ | ||
|
||
### Loading plugins | ||
|
||
Once permission is granted to each plugin directory, an object is created from the `manifest.json` file for UXP plugins and `manifest.xml` file for CEP plugins. | ||
|
||
JSON files can be easily be read by using [File.read()](https://www.adobe.io/photoshop/uxp/uxp/reference-js/Modules/uxp/Persistent%20File%20Storage/File/#readoptions) and then parsing the returning string into JSON using `JSON.parse(string)` | ||
|
||
For reading XML files it becomes a bit more tricky. Unfortunately, UXP does not currently support [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser) However, we can use an external NPM package, [xmldom](https://www.npmjs.com/package/xmldom), to act as a polyfill for `DOMParser`. | ||
|
||
After all plugins are loaded, the final array is sorted based on the current running application (Photoshop or XD). This can be determined by using [uxp.host](https://www.adobe.io/photoshop/uxp/uxp/reference-js/Modules/uxp/Host%20Information/Host/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
presets: [ | ||
'@vue/cli-plugin-babel/preset' | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"name": "plugin-info", | ||
"version": "1.0.0", | ||
"description": "A simple Adobe Photoshop plugin that shows you the store info for any installed plugins", | ||
"main": "./src/main.js", | ||
"private": true, | ||
"scripts": { | ||
"watch": "vue-cli-service build --watch", | ||
"build": "vue-cli-service build", | ||
"lint": "vue-cli-service lint" | ||
}, | ||
"dependencies": { | ||
"core-js": "^3.6.5", | ||
"filesize": "^6.3.0", | ||
"vue": "^2.6.11", | ||
"xmldom": "^0.6.0" | ||
}, | ||
"devDependencies": { | ||
"@vue/cli-plugin-babel": "~4.5.0", | ||
"@vue/cli-plugin-eslint": "~4.5.0", | ||
"@vue/cli-service": "~4.5.0", | ||
"babel-eslint": "^10.1.0", | ||
"copy-webpack-plugin": "^6", | ||
"eslint": "^6.7.2", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-plugin-vue": "^6.2.2", | ||
"prettier": "^2.3.1", | ||
"vue-template-compiler": "^2.6.11" | ||
}, | ||
"eslintConfig": { | ||
"root": true, | ||
"env": { | ||
"node": true | ||
}, | ||
"extends": [ | ||
"plugin:vue/essential", | ||
"eslint:recommended", | ||
"prettier" | ||
], | ||
"parserOptions": { | ||
"parser": "babel-eslint" | ||
}, | ||
"rules": {} | ||
}, | ||
"prettier": { | ||
"printWidth": 120, | ||
"semi": true, | ||
"quoteProps": "as-needed", | ||
"trailingComma": "none", | ||
"bracketSpacing": true, | ||
"jsxBracketSameLine": false, | ||
"arrowParens": "avoid", | ||
"vueIndentScriptAndStyle": true | ||
}, | ||
"browserslist": [ | ||
"> 1%", | ||
"last 2 versions", | ||
"not dead" | ||
] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
{ | ||
"id": "com.adobe.uxp.info.plugin", | ||
"name": "Plugin Info", | ||
"version": "1.0.0", | ||
"main": "index.html", | ||
"manifestVersion": 4, | ||
"host": { | ||
"app": "PS", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This plugin would definitely work well as a cross-compatible plugin with Adobe XD. Is there a way to indicate both |
||
"minVersion": "22.0.0" | ||
}, | ||
"entrypoints": [ | ||
{ | ||
"type": "command", | ||
"id": "showSetup", | ||
"label": "Show Setup" | ||
}, | ||
{ | ||
"type": "command", | ||
"id": "clearData", | ||
"label": "Clear Data" | ||
}, | ||
{ | ||
"type": "panel", | ||
"id": "pluginInfo", | ||
"label": "Plugin Info", | ||
"minimumSize": { "width": 230, "height": 200 }, | ||
"maximumSize": { "width": 2000, "height": 2000 }, | ||
"preferredDockedSize": { "width": 230, "height": 300 }, | ||
"preferredFloatingSize": { "width": 230, "height": 300 }, | ||
"icons": [ | ||
{ | ||
"width": 24, | ||
"height": 24, | ||
"path": "icons/dark.png", | ||
"scale": [1, 2, 3, 4, 5], | ||
"theme": ["darkest", "dark", "medium"] | ||
}, | ||
{ | ||
"width": 24, | ||
"height": 24, | ||
"path": "icons/light.png", | ||
"scale": [1, 2, 3, 4, 5], | ||
"theme": ["lightest", "light"] | ||
} | ||
] | ||
} | ||
], | ||
"icons": [ | ||
{ | ||
"width": 24, | ||
"height": 24, | ||
"path": "icons/dark.png", | ||
"scale": [1, 2, 3, 4, 5], | ||
"theme": ["darkest", "dark", "medium"] | ||
}, | ||
{ | ||
"width": 24, | ||
"height": 24, | ||
"path": "icons/light.png", | ||
"scale": [1, 2, 3, 4, 5], | ||
"theme": ["lightest", "light"] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html lang=""> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width,initial-scale=1.0" /> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
<!-- built files will be auto injected --> | ||
</body> | ||
</html> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know your thoughts on this. Since this is larger than a regular sample, I thought a section explaining some of the code would be pretty useful