From 982550f3ca8d83f7002919fa14b28b9b38505c79 Mon Sep 17 00:00:00 2001 From: igormuba Date: Wed, 16 Aug 2023 20:01:04 -0300 Subject: [PATCH 1/2] Add ipfs move feature --- src/main/core/components/Pins.ts | 132 ++++++++++++------ src/main/ipcAdapter.ts | 3 + .../views/PinsView/PinsViewComponent.tsx | 1 + src/renderer/views/PinsView/pinningUtils.tsx | 11 ++ 4 files changed, 105 insertions(+), 42 deletions(-) diff --git a/src/main/core/components/Pins.ts b/src/main/core/components/Pins.ts index 188c832..e55f447 100644 --- a/src/main/core/components/Pins.ts +++ b/src/main/core/components/Pins.ts @@ -9,29 +9,31 @@ import { IpfsHandler } from './ipfsHandler' import tmp from 'tmp' import execa from 'execa' import waIpfs from 'wa-go-ipfs' +import Config from './Config' +import path from 'path' +import fsExtra from 'fs-extra' + const Path = require('path') const debug = require('debug')('3speak:pins') const Schedule = require('node-schedule') PouchDB.plugin(require('pouchdb-find')) PouchDB.plugin(require('pouchdb-upsert')) +const Utils = require('../utils') async function progressPin(ipfs: IPFSHTTPClient, pin: string, callback: Function) { - // ipfs.dag.exp - - const tmpPath = tmp.dirSync(); + + const tmpPath = tmp.dirSync() console.log(tmpPath) - const writer = fs.createWriteStream(Path.join(tmpPath.name, 'download.car')); + const writer = fs.createWriteStream(Path.join(tmpPath.name, 'download.car')) - const {data} = await Axios.get(`https://ipfs-3speak.b-cdn.net/api/v0/object/stat?arg=${pin}`) + const { data } = await Axios.get(`https://ipfs-3speak.b-cdn.net/api/v0/object/stat?arg=${pin}`) const CumulativeSize = data.CumulativeSize - let totalSizeSoFar = 0; + let totalSizeSoFar = 0 await Axios.get(`https://ipfs-3speak.b-cdn.net/api/v0/dag/export?arg=${pin}`, { responseType: 'stream', - }).then(response => { - - + }).then((response) => { response.data.on('data', (chunk) => { totalSizeSoFar = totalSizeSoFar + chunk.length const pct = Math.round((totalSizeSoFar / CumulativeSize) * 100) @@ -39,21 +41,21 @@ async function progressPin(ipfs: IPFSHTTPClient, pin: string, callback: Function // console.log(`${pct}%`) }) return new Promise((resolve, reject) => { - response.data.pipe(writer); - let error = null; - writer.on('error', err => { - error = err; - writer.close(); - reject(err); - }); + response.data.pipe(writer) + let error = null + writer.on('error', (err) => { + error = err + writer.close() + reject(err) + }) writer.on('close', () => { if (!error) { - resolve(true); + resolve(true) } - }); - }); + }) + }) }) - + // console.log('got here') // for await(let importBlock of ipfs.dag.import(fs.createReadStream(Path.join(tmpPath.name, 'download.car')))) { // console.log(importBlock) @@ -64,21 +66,16 @@ async function progressPin(ipfs: IPFSHTTPClient, pin: string, callback: Function waIpfs.getDefaultPath({ dev: process.env.NODE_ENV === 'development' }), ) - - const output = await execa(ipfsPath, [ - 'dag', - 'import', - Path.join(tmpPath.name, 'download.car') - ], { + const output = await execa(ipfsPath, ['dag', 'import', Path.join(tmpPath.name, 'download.car')], { env: { - IPFS_PATH: ipfsInfo.ipfsPath - } + IPFS_PATH: ipfsInfo.ipfsPath, + }, }) console.log(output) - + await fsPromises.rmdir(tmpPath.name, { recursive: true, - force: true + force: true, } as any) // const refs = ipfs.refs(pin, { @@ -116,6 +113,63 @@ class Pins { ) return out } + async mv(sender) { + try { + const { dialog, BrowserWindow } = require('electron') + + const focusedWindow = BrowserWindow.getFocusedWindow() + if (!focusedWindow) { + throw new Error('No focused window found.') + } + + // Open folder dialog to select new path + const result = await dialog.showOpenDialog(focusedWindow, { + properties: ['openDirectory'], + title: 'Select New IPFS Folder', + message: 'Please select a new folder for IPFS data:', + }) + + const selectedFolder = result.canceled ? null : result.filePaths[0] + + if (selectedFolder) { + // Implement logic to move the contents from the old folder to the new folder + const config = new Config(Utils.getRepoPath()) + await config.open() + const ipfsPath = config.get('ipfsPath') + + // Normalize paths to ensure consistent comparison + const normalizedIPFSPath = path.normalize(ipfsPath) + const normalizedSelectedFolder = path.normalize(selectedFolder) + + // Check if the selected folder is the same as or a parent of the current IPFS folder + if ( + normalizedIPFSPath === normalizedSelectedFolder || + normalizedIPFSPath.startsWith(normalizedSelectedFolder + path.sep) + ) { + console.error('Selected folder is the same as or a parent of the current IPFS folder.') + return + } + + // Move contents + const files = await fsExtra.readdir(ipfsPath) + for (const file of files) { + const sourcePath = path.join(ipfsPath, file) + const destPath = path.join(selectedFolder, file) + await fsExtra.move(sourcePath, destPath, { overwrite: true }) + } + + // Update IPFS configuration with the new folder path + config.set('ipfsPath', selectedFolder) + + console.log('IPFS folder path changed successfully') + } + + // Reply to the sender window with the selected folder path + sender.send('ipfs.handleFolderSelection', selectedFolder) + } catch (error) { + console.error('Error handling IPC request:', error) + } + } async add(doc) { debug(`received add with id of ${doc._id}`) if (typeof doc !== 'object') { @@ -139,28 +193,22 @@ class Pins { doc.size = 0 this.inProgressPins[doc._id] = doc - let totalSize = 0 - let totalPercent; + let totalPercent console.log(doc) - const progressTick = setInterval(async() => { - + const progressTick = setInterval(async () => { try { - const bDoc = await this.db.get("hive:cowboyzlegend27:qauvdrmx") + const bDoc = await this.db.get('hive:cowboyzlegend27:qauvdrmx') console.log(bDoc) - } catch { - - } + } catch {} try { const cDoc = await this.db.get(doc._id) console.log(cDoc) - } catch { - - } + } catch {} await this.db.upsert(doc._id, (oldDoc) => { - oldDoc.percent = totalPercent; + oldDoc.percent = totalPercent doc.percent = totalPercent return oldDoc }) diff --git a/src/main/ipcAdapter.ts b/src/main/ipcAdapter.ts index 9e1ddce..1c4493b 100644 --- a/src/main/ipcAdapter.ts +++ b/src/main/ipcAdapter.ts @@ -78,6 +78,9 @@ class IpcAdapter { PromiseIPC.on('pins.ls', async () => { return await this.core.pins.ls() }) + PromiseIPC.on('pins.mv', async (ref) => { + return await this.core.pins.mv(ref.sender) + }) //Accounts PromiseIPC.on('accounts.createProfile', async (doc) => { return await this.core.accounts.createProfile(doc) diff --git a/src/renderer/views/PinsView/PinsViewComponent.tsx b/src/renderer/views/PinsView/PinsViewComponent.tsx index 631f068..d0d9d6c 100644 --- a/src/renderer/views/PinsView/PinsViewComponent.tsx +++ b/src/renderer/views/PinsView/PinsViewComponent.tsx @@ -41,6 +41,7 @@ export const PinsViewComponent: React.FC = ({ Manual Pin Manual GC IPFS Folder + Change path diff --git a/src/renderer/views/PinsView/pinningUtils.tsx b/src/renderer/views/PinsView/pinningUtils.tsx index 1949a10..7255e5c 100644 --- a/src/renderer/views/PinsView/pinningUtils.tsx +++ b/src/renderer/views/PinsView/pinningUtils.tsx @@ -173,6 +173,14 @@ export const usePinningUtils = () => { shell.openPath(ipfsPath) } + const handleCase4 = async () => { + try { + await PromiseIpc.send('ipfs.changeFolderPath') + } catch (error) { + console.error('Error sending IPC message:', error) + } + } + const actionSelect = async (key) => { switch (key) { case '1': @@ -184,6 +192,9 @@ export const usePinningUtils = () => { case '3': await handleCase3() break + case '4': + await handleCase4() + break default: } } From 8a770b7731113c9939305812aec2cb4d93218971 Mon Sep 17 00:00:00 2001 From: igormuba Date: Tue, 22 Aug 2023 10:23:56 -0300 Subject: [PATCH 2/2] add confirmation for moving --- src/main/core/components/Pins.ts | 82 +++++++++++--------- src/renderer/views/PinsView/pinningUtils.tsx | 2 +- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/main/core/components/Pins.ts b/src/main/core/components/Pins.ts index e55f447..e863b09 100644 --- a/src/main/core/components/Pins.ts +++ b/src/main/core/components/Pins.ts @@ -122,50 +122,62 @@ class Pins { throw new Error('No focused window found.') } - // Open folder dialog to select new path - const result = await dialog.showOpenDialog(focusedWindow, { - properties: ['openDirectory'], - title: 'Select New IPFS Folder', - message: 'Please select a new folder for IPFS data:', + // Show a confirmation dialog to the user + const response = await dialog.showMessageBox(focusedWindow, { + type: 'question', + buttons: ['Cancel', 'Proceed'], + title: 'Confirm Folder Move', + message: 'Are you sure you want to move the IPFS folder contents?', + defaultId: 1, // Set the default button (0 for Cancel, 1 for Proceed) }) - const selectedFolder = result.canceled ? null : result.filePaths[0] + // Check user response + if (response.response === 1) { + // Open folder dialog to select new path + const result = await dialog.showOpenDialog(focusedWindow, { + properties: ['openDirectory'], + title: 'Select New IPFS Folder', + message: 'Please select a new folder for IPFS data:', + }) - if (selectedFolder) { - // Implement logic to move the contents from the old folder to the new folder - const config = new Config(Utils.getRepoPath()) - await config.open() - const ipfsPath = config.get('ipfsPath') + const selectedFolder = result.canceled ? null : result.filePaths[0] - // Normalize paths to ensure consistent comparison - const normalizedIPFSPath = path.normalize(ipfsPath) - const normalizedSelectedFolder = path.normalize(selectedFolder) + if (selectedFolder) { + // Implement logic to move the contents from the old folder to the new folder + const config = new Config(Utils.getRepoPath()) + await config.open() + const ipfsPath = config.get('ipfsPath') - // Check if the selected folder is the same as or a parent of the current IPFS folder - if ( - normalizedIPFSPath === normalizedSelectedFolder || - normalizedIPFSPath.startsWith(normalizedSelectedFolder + path.sep) - ) { - console.error('Selected folder is the same as or a parent of the current IPFS folder.') - return - } + // Normalize paths to ensure consistent comparison + const normalizedIPFSPath = path.normalize(ipfsPath) + const normalizedSelectedFolder = path.normalize(selectedFolder) - // Move contents - const files = await fsExtra.readdir(ipfsPath) - for (const file of files) { - const sourcePath = path.join(ipfsPath, file) - const destPath = path.join(selectedFolder, file) - await fsExtra.move(sourcePath, destPath, { overwrite: true }) - } + // Check if the selected folder is the same as or a parent of the current IPFS folder + if ( + normalizedIPFSPath === normalizedSelectedFolder || + normalizedIPFSPath.startsWith(normalizedSelectedFolder + path.sep) + ) { + console.error('Selected folder is the same as or a parent of the current IPFS folder.') + return + } - // Update IPFS configuration with the new folder path - config.set('ipfsPath', selectedFolder) + // Move contents + const files = await fsExtra.readdir(ipfsPath) + for (const file of files) { + const sourcePath = path.join(ipfsPath, file) + const destPath = path.join(selectedFolder, file) + await fsExtra.move(sourcePath, destPath, { overwrite: true }) + } - console.log('IPFS folder path changed successfully') - } + // Update IPFS configuration with the new folder path + config.set('ipfsPath', selectedFolder) - // Reply to the sender window with the selected folder path - sender.send('ipfs.handleFolderSelection', selectedFolder) + console.log('IPFS folder path changed successfully') + } + + // Reply to the sender window with the selected folder path + sender.send('ipfs.handleFolderSelection', selectedFolder) + } } catch (error) { console.error('Error handling IPC request:', error) } diff --git a/src/renderer/views/PinsView/pinningUtils.tsx b/src/renderer/views/PinsView/pinningUtils.tsx index 7255e5c..02ec3e6 100644 --- a/src/renderer/views/PinsView/pinningUtils.tsx +++ b/src/renderer/views/PinsView/pinningUtils.tsx @@ -175,7 +175,7 @@ export const usePinningUtils = () => { const handleCase4 = async () => { try { - await PromiseIpc.send('ipfs.changeFolderPath') + await PromiseIpc.send('pins.mv') } catch (error) { console.error('Error sending IPC message:', error) }