Merge pull request 'Fix #11: Remove vim swap file, harden .gitignore' (#14) from fix/gitignore-swap into main
Reviewed-on: https://git.example.com/jarianc/MovieMapper/pulls/14
This commit is contained in:
commit
b8e9d9dc08
3
.gitignore
vendored
3
.gitignore
vendored
@ -34,6 +34,9 @@ jspm_packages/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
*.js-e
|
||||
.*.swp
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
@ -1,257 +0,0 @@
|
||||
const { ipcRenderer } = require('electron');
|
||||
|
||||
/**
|
||||
* TagManager - Manages file tagging functionality
|
||||
*/
|
||||
class TagManager {
|
||||
constructor() {
|
||||
this.tagColors = {
|
||||
extra: '#28a745', // Green
|
||||
behindTheScenes: '#17a2b8', // Teal
|
||||
delete: '#dc3545' // Red
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag a file with a specific tag type
|
||||
* @param {string} filePath - File path
|
||||
* @param {string} tagType - Tag type (extra, behindTheScenes, delete)
|
||||
* @param {Function} callback - Callback function
|
||||
*/
|
||||
tagFile(filePath, tagType, callback) {
|
||||
console.log(`Tagging file ${filePath} as ${tagType}`);
|
||||
|
||||
// Find the file item in the UI
|
||||
const fileItems = document.querySelectorAll('.file-item');
|
||||
fileItems.forEach(item => {
|
||||
const fileNameElement = item.querySelector('.file-name');
|
||||
if (fileNameElement && fileNameElement.dataset.filePath === filePath) {
|
||||
this._applyTagVisuals(item, tagType);
|
||||
item.setAttribute('data-tagged-' + tagType, 'true');
|
||||
this._enablePlayButton(item);
|
||||
}
|
||||
});
|
||||
|
||||
// Update the tagged count display
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
|
||||
console.log(`File ${filePath} tagged as ${tagType}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply visual styling for a tag
|
||||
* @param {HTMLElement} fileItem - File item element
|
||||
* @param {string} tagType - Tag type
|
||||
* @private
|
||||
*/
|
||||
_applyTagVisuals(fileItem, tagType) {
|
||||
const tagIcon = fileItem.querySelector(`.${tagType}-tag`);
|
||||
if (tagIcon) {
|
||||
const tagColor = this.tagColors[tagType];
|
||||
|
||||
// Make the icon fully saturated and highlight
|
||||
tagIcon.style.opacity = '1';
|
||||
tagIcon.style.filter = 'none';
|
||||
tagIcon.style.color = tagColor;
|
||||
tagIcon.style.textShadow = `0 0 15px ${tagColor}`;
|
||||
tagIcon.style.transform = 'scale(1.3)';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable play button for a file
|
||||
* @param {HTMLElement} fileItem - File item element
|
||||
* @private
|
||||
*/
|
||||
_enablePlayButton(fileItem) {
|
||||
const playButton = fileItem.querySelector('.play-button');
|
||||
if (playButton) {
|
||||
playButton.style.opacity = '1';
|
||||
playButton.style.cursor = 'pointer';
|
||||
playButton.disabled = false;
|
||||
playButton.style.pointerEvents = 'auto';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Untag a file
|
||||
* @param {string} filePath - File path
|
||||
* @param {string} tagType - Tag type
|
||||
*/
|
||||
untagFile(filePath, tagType) {
|
||||
console.log(`Untagging file ${filePath} from ${tagType}`);
|
||||
|
||||
// Find the file item in the UI
|
||||
const fileItems = document.querySelectorAll('.file-item');
|
||||
fileItems.forEach(item => {
|
||||
const fileNameElement = item.querySelector('.file-name');
|
||||
if (fileNameElement && fileNameElement.dataset.filePath === filePath) {
|
||||
this._removeTagVisuals(item, tagType);
|
||||
item.removeAttribute('data-tagged-' + tagType);
|
||||
this._checkAndDisablePlayButton(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove tag visuals
|
||||
* @param {HTMLElement} fileItem - File item element
|
||||
* @param {string} tagType - Tag type
|
||||
* @private
|
||||
*/
|
||||
_removeTagVisuals(fileItem, tagType) {
|
||||
const tagIcon = fileItem.querySelector(`.${tagType}-tag`);
|
||||
if (tagIcon) {
|
||||
// Reset to original appearance
|
||||
tagIcon.style.opacity = '0.7';
|
||||
tagIcon.style.filter = 'none';
|
||||
tagIcon.style.color = '';
|
||||
tagIcon.style.textShadow = 'none';
|
||||
tagIcon.style.transform = 'scale(1)';
|
||||
tagIcon.style.boxShadow = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and disable play button if no tags remain
|
||||
* @param {HTMLElement} fileItem - File item element
|
||||
* @private
|
||||
*/
|
||||
_checkAndDisablePlayButton(fileItem) {
|
||||
const hasOtherTags = fileItem.hasAttribute('data-tagged-extra') ||
|
||||
fileItem.hasAttribute('data-tagged-behind-the-scenes') ||
|
||||
fileItem.hasAttribute('data-tagged-delete');
|
||||
|
||||
if (!hasOtherTags) {
|
||||
const playButton = fileItem.querySelector('.play-button');
|
||||
if (playButton) {
|
||||
playButton.style.opacity = '0.3';
|
||||
playButton.style.cursor = 'default';
|
||||
playButton.disabled = true;
|
||||
playButton.style.pointerEvents = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a tagged file
|
||||
* @param {string} filePath - File path
|
||||
* @param {string} tagType - Tag type
|
||||
* @returns {Promise<Object>} Move result
|
||||
*/
|
||||
async moveTaggedFile(filePath, tagType) {
|
||||
console.log(`Moving file ${filePath} to ${tagType} folder`);
|
||||
|
||||
// Send request to main process to move the file
|
||||
const result = await ipcRenderer.invoke('move-file-to-folder', {
|
||||
filePath: filePath,
|
||||
folderName: tagType
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
console.log(`File moved successfully to ${tagType} folder`);
|
||||
return { success: true, filePath };
|
||||
} else {
|
||||
console.error(`Failed to move file: ${result.error}`);
|
||||
return { success: false, error: result.error, filePath };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move all tagged files
|
||||
* @param {Function} onUpdateCount - Callback to update count
|
||||
* @param {Function} onEpisodesUpdated - Callback to update episodes
|
||||
* @param {Function} onMatchCheck - Callback to check episode match
|
||||
* @returns {Promise<Object>} Results summary
|
||||
*/
|
||||
async moveAllTaggedFiles(onUpdateCount, onEpisodesUpdated, onMatchCheck) {
|
||||
const taggedItems = document.querySelectorAll('.file-item[data-tagged-extra], .file-item[data-tagged-behind-the-scenes], .file-item[data-tagged-delete]');
|
||||
|
||||
if (taggedItems.length === 0) {
|
||||
console.log('No tagged files to move');
|
||||
return { success: true, successful: 0, failed: 0 };
|
||||
}
|
||||
|
||||
console.log(`Moving ${taggedItems.length} tagged files`);
|
||||
|
||||
// Visual feedback - change circle color while processing
|
||||
const taggedCircle = document.getElementById('tagged-circle');
|
||||
if (taggedCircle) {
|
||||
taggedCircle.style.backgroundColor = '#ffc107';
|
||||
taggedCircle.style.pointerEvents = 'none';
|
||||
}
|
||||
|
||||
const results = [];
|
||||
for (const item of taggedItems) {
|
||||
const filePath = item.querySelector('.file-name').dataset.filePath;
|
||||
let tagType;
|
||||
if (item.hasAttribute('data-tagged-extra')) {
|
||||
tagType = 'extra';
|
||||
} else if (item.hasAttribute('data-tagged-behind-the-scenes')) {
|
||||
tagType = 'behindTheScenes';
|
||||
} else if (item.hasAttribute('data-tagged-delete')) {
|
||||
tagType = 'delete';
|
||||
}
|
||||
|
||||
const result = await this.moveTaggedFile(filePath, tagType);
|
||||
results.push(result);
|
||||
|
||||
if (result.success) {
|
||||
// Remove the item from the file list after successful move
|
||||
item.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset circle appearance
|
||||
if (taggedCircle) {
|
||||
taggedCircle.style.backgroundColor = '';
|
||||
taggedCircle.style.pointerEvents = '';
|
||||
}
|
||||
|
||||
// Update the tagged count after all moves
|
||||
if (onUpdateCount) onUpdateCount();
|
||||
if (onEpisodesUpdated) onEpisodesUpdated();
|
||||
if (onMatchCheck) onMatchCheck();
|
||||
|
||||
// Summary of results
|
||||
const successful = results.filter(r => r.success).length;
|
||||
const failed = results.filter(r => !r.success).length;
|
||||
|
||||
if (failed > 0) {
|
||||
alert(`Moved ${successful} files. ${failed} files failed to move.`);
|
||||
} else if (successful > 0) {
|
||||
console.log(`Successfully moved all ${successful} files`);
|
||||
}
|
||||
|
||||
return { success: true, successful, failed };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all tagged files
|
||||
* @returns {Array} Array of tagged file objects
|
||||
*/
|
||||
getTaggedFiles() {
|
||||
const taggedItems = document.querySelectorAll('.file-item[data-tagged-extra], .file-item[data-tagged-behind-the-scenes], .file-item[data-tagged-delete]');
|
||||
const taggedFiles = [];
|
||||
|
||||
taggedItems.forEach(item => {
|
||||
const filePath = item.querySelector('.file-name').dataset.filePath;
|
||||
let tagType;
|
||||
if (item.hasAttribute('data-tagged-extra')) {
|
||||
tagType = 'extra';
|
||||
} else if (item.hasAttribute('data-tagged-behind-the-scenes')) {
|
||||
tagType = 'behindTheScenes';
|
||||
} else if (item.hasAttribute('data-tagged-delete')) {
|
||||
tagType = 'delete';
|
||||
}
|
||||
|
||||
taggedFiles.push({ filePath, tagType });
|
||||
});
|
||||
|
||||
return taggedFiles;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TagManager;
|
||||
Loading…
x
Reference in New Issue
Block a user