-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ /* Misc Styling. */
+ paper-toolbar {
+ --paper-toolbar-color: var(--loot-primary-text-color);
+ --paper-toolbar-background: inherit;
+ }
+ #content {
+ overflow: hidden;
+ }
+ #title {
+ @apply(--layout-flex);
+ overflow: hidden;
+ white-space: nowrap;
+ }
+ #editMetadata,
+ #copyMetadata,
+ #clearMetadata {
+ cursor: pointer;
+ }
+ #showOnlyConflicts {
+ min-height: 48px;
+ padding: 0 16px;
+ font-weight: 500;
+ --paper-toggle-button-label-spacing: 16px;
+ white-space: nowrap;
+ }
+ [hidden] {
+ display: none;
+ }
+
+
+
+
+
+ Active Plugin
+
+
+
+
+
+
+ Master File
+
+ Empty Plugin
+
+ Loads Archive
+
+ Has User Metadata
+
+
+
+
+
+
-
-
-
+
+ Polymer({
+ is: 'loot-plugin-card',
+ properties: {
+ data: {
+ notify: true,
+ observer: '_dataChanged',
+ },
+ isActive: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ isMaster: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ isEmpty: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ loadsArchive: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ hasUserEdits: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ isSearchResult: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+ },
+
+ attached() {
+ this.$.showOnlyConflicts.addEventListener('change', this._onShowOnlyConflicts);
+ this.$.editMetadata.addEventListener('click', this.onShowEditor);
+ this.$.editor.addEventListener('loot-editor-close', this._onHideEditor);
+ this.$.copyMetadata.addEventListener('click', this._onCopyMetadata);
+ this.$.clearMetadata.addEventListener('click', this._onClearMetadata);
+
+ this.addEventListener('transitionend', this._onFlipEnd);
+ },
+
+ detached() {
+ this.$.showOnlyConflicts.removeEventListener('change', this._onShowOnlyConflicts);
+ this.$.editMetadata.removeEventListener('click', this.onShowEditor);
+ this.$.editor.removeEventListener('loot-editor-close', this._onHideEditor);
+ this.$.copyMetadata.removeEventListener('click', this._onCopyMetadata);
+ this.$.clearMetadata.removeEventListener('click', this._onClearMetadata);
+
+ this.removeEventListener('transitionend', this._onFlipEnd);
+ },
+
+ _dataChanged(newValue, oldValue) {
+ if (newValue) {
+ if (newValue.isEditorOpen) {
+ /* Record existing data. */
+ if (oldValue) {
+ oldValue.editor = this.readFromEditor(oldValue);
+ }
+ /* Share the data with the editor. */
+ this.$.editor.setEditorData(newValue);
+ }
+
+ /* Set the card flip state. */
+ if (this.classList.contains('flip') !== newValue.isEditorOpen) {
+ /* Temporarily speed up the flip effect, as otherwise fast
+ scrolling lets the user see the end of it. */
+ this.classList.add('fastflip');
+ this.classList.toggle('flip');
+ }
+
+ /* Initialise the card content data. */
+ this.updateContent();
+
+ /* Also set highlight if the conflict filter is active. */
+ this.classList.toggle('highlight', newValue.isConflictFilterChecked);
+
+ /* Set highlight if the plugin is a search result. */
+ this.classList.toggle('search-result', newValue.isSearchResult);
+ }
+ },
+
+ _setTagsContent(tags) {
+ if (tags) {
+ const tagsAdded = this.getElementsByClassName('tag add')[0];
+ tagsAdded.textContent = tags.added;
+ tagsAdded.hidden = tags.added.length === 0;
+
+ const tagsRemoved = this.getElementsByClassName('tag remove')[0];
+ tagsRemoved.textContent = tags.removed;
+ tagsRemoved.hidden = tags.removed.length === 0;
+ }
+ },
+
+ _setMessagesContent(messages) {
+ /* First clear any existing messages. */
+ const messageList = this.getElementsByTagName('ul')[0];
+ while (messageList.firstElementChild) {
+ messageList.removeChild(messageList.firstElementChild);
+ }
+
+ if (messages) {
+ /* Now add new messages. */
+ messages.forEach((message) => {
+ const messageListItem = document.createElement('li');
+ messageListItem.className = message.type;
+ // Use the Marked library for Markdown formatting support.
+ messageListItem.innerHTML = window.marked(message.content);
+ messageList.appendChild(messageListItem);
+ });
+ messageList.hidden = messages.length === 0;
+ }
+ },
+
+ updateContent() {
+ if (this.data) {
+ const cardContent = this.data.getCardContent(loot.filters);
+
+ this.getElementsByClassName('version')[0].textContent = cardContent.version;
+ this.$.editor.getElementsByClassName('version')[0].textContent = cardContent.version;
+
+ this.getElementsByClassName('crc')[0].textContent = cardContent.crc;
+ this.$.editor.getElementsByClassName('crc')[0].textContent = cardContent.crc;
+
+ this._setTagsContent(cardContent.tags);
+ this._setMessagesContent(cardContent.messages);
+
+ /* Update the conflict filter toggle state. */
+ this.$.showOnlyConflicts.checked = this.data.isConflictFilterChecked;
+
+ /* Notify that this card (may have) changed size. */
+ this.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true }));
+ }
+ },
+
+ getName() {
+ return this.getElementsByTagName('h1')[0].textContent;
+ },
+
+ _onFlipEnd() {
+ /* Remove fastflip class if present. This also fires when the menu is
+ opened or closed, but that isn't an issue. */
+ this.classList.remove('fastflip');
+ },
+
+ onShowEditor() {
+ let card;
+ if (this.tagName === 'LOOT-PLUGIN-CARD') {
+ card = this;
+ } else {
+ card = getMenuItemCard(this);
+ }
+
+ /* If the editor hasn't already been opened, its data is not yet set, so do that now. */
+ if (!card.data.isEditorOpen && !card.data.editor) {
+ card.$.editor.setEditorData(card.data);
+ }
+
+ card.data.isEditorOpen = true;
+
+ card.classList.toggle('flip');
+
+ /* Fire an open event, so that the UI can enter edit mode. */
+ card.dispatchEvent(new CustomEvent('loot-editor-open', {
+ bubbles: true,
+ }));
+
+ /* Notify that this card (may have) changed size. */
+ card.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true }));
+ },
+
+ _onHideEditor() {
+ let card;
+ if (this.tagName === 'LOOT-PLUGIN-CARD') {
+ card = this;
+ } else {
+ card = getMenuItemCard(this);
+ }
+
+ /* Now hide editor. */
+ card.classList.toggle('flip');
+ card.data.isEditorOpen = false;
+
+ /* Notify that this card (may have) changed size. */
+ card.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true }));
+ },
+
+ readFromEditor(oldData) {
+ return this.$.editor.readFromEditor(oldData);
+ },
+
+ _onShowOnlyConflicts(evt) {
+ evt.target.dispatchEvent(new CustomEvent('loot-filter-conflicts', {
+ detail: evt.currentTarget.checked,
+ bubbles: true,
+ }));
+ },
+
+ _onCopyMetadata(evt) {
+ evt.target.dispatchEvent(new CustomEvent('loot-copy-metadata', {
+ bubbles: true,
+ }));
+ },
+
+ _onClearMetadata(evt) {
+ evt.target.dispatchEvent(new CustomEvent('loot-clear-metadata', {
+ bubbles: true,
+ }));
+ },
+ });
+
+
diff --git a/src/gui/html/js/plugin.js b/src/gui/html/js/plugin.js
index 72a3f8b5..5a37d8c2 100644
--- a/src/gui/html/js/plugin.js
+++ b/src/gui/html/js/plugin.js
@@ -303,6 +303,10 @@
this._isDirty = dirty;
}
+ get hasUserEdits() {
+ return this.userlist && Object.keys(this.userlist).length > 1;
+ }
+
getCardContent(filters) {
return new PluginCardContent(this, filters);
}
diff --git a/src/tests/gui/html/elements/test_loot-plugin-card.html b/src/tests/gui/html/elements/test_loot-plugin-card.html
new file mode 100644
index 00000000..9831c540
--- /dev/null
+++ b/src/tests/gui/html/elements/test_loot-plugin-card.html
@@ -0,0 +1,86 @@
+
+
+
+ test_loot-plugin-card.html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[plugin.name]]
+
+
+
+
+
+
+
+
+
+
+
+