delete individual blob files for completed file downloads to save space #234
|
@ -27,6 +27,7 @@ import {
|
||||||
TextInput,
|
TextInput,
|
||||||
ToastAndroid
|
ToastAndroid
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
import { doDeleteCompleteBlobs } from '../redux/actions/file';
|
||||||
|
|||||||
import { SETTINGS, doHideNotification, doNotify, selectNotification } from 'lbry-redux';
|
import { SETTINGS, doHideNotification, doNotify, selectNotification } from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doUserEmailVerify,
|
doUserEmailVerify,
|
||||||
|
@ -227,6 +228,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleAppStateChange = (nextAppState) => {
|
_handleAppStateChange = (nextAppState) => {
|
||||||
|
const { dispatch } = this.props;
|
||||||
// Check if the app was suspended
|
// Check if the app was suspended
|
||||||
if (AppState.currentState && AppState.currentState.match(/inactive|background/)) {
|
if (AppState.currentState && AppState.currentState.match(/inactive|background/)) {
|
||||||
AsyncStorage.getItem('firstLaunchTime').then(start => {
|
AsyncStorage.getItem('firstLaunchTime').then(start => {
|
||||||
|
@ -237,6 +239,11 @@ class AppWithNavigationState extends React.Component {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AppState.currentState && AppState.currentState.match(/active/)) {
|
||||||
|
// Cleanup blobs for completed files upon app resume to save space
|
||||||
|
dispatch(doDeleteCompleteBlobs());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleUrl = (evt) => {
|
_handleUrl = (evt) => {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
const Constants = {
|
const Constants = {
|
||||||
KEY_FIRST_RUN_EMAIL: "firstRunEmail",
|
KEY_FIRST_RUN_EMAIL: "firstRunEmail",
|
||||||
KEY_SHOULD_VERIFY_EMAIL: "shouldVerifyEmail",
|
KEY_SHOULD_VERIFY_EMAIL: "shouldVerifyEmail",
|
||||||
|
|
||||||
SETTING_ALPHA_UNDERSTANDS_RISKS: "alphaUnderstandRisks",
|
SETTING_ALPHA_UNDERSTANDS_RISKS: "alphaUnderstandRisks",
|
||||||
|
|
||||||
ACTION_FIRST_RUN_PAGE_CHANGED: "FIRST_RUN_PAGE_CHANGED",
|
ACTION_DELETE_COMPLETED_BLOBS: "DELETE_COMPLETED_BLOBS",
|
||||||
|
ACTION_FIRST_RUN_PAGE_CHANGED: "FIRST_RUN_PAGE_CHANGED",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Constants;
|
export default Constants;
|
||||||
![]() Why are some still mixed formatted? (camel vs underscores) Why are some still mixed formatted? (camel vs underscores)
![]() Following convention with the constants defined in Following convention with the constants defined in `lbry-desktop` and `lbry-redux`. The settings and keys are mixed case. The redux actions are uppercase with underscores.
https://github.com/lbryio/lbry-redux/blob/master/src/constants/action_types.js
https://github.com/lbryio/lbry-redux/blob/master/src/constants/settings.js
|
|||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
|
|||||||
selectUser,
|
selectUser,
|
||||||
selectEmailToVerify
|
selectEmailToVerify
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
|
import { doDeleteCompleteBlobs } from '../../redux/actions/file';
|
||||||
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
|
|||||||
import SplashScreen from './view';
|
import SplashScreen from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -17,6 +18,7 @@ const select = state => ({
|
||||||
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
|
|||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
authenticate: (appVersion, deviceId) => dispatch(doAuthenticate(appVersion, deviceId)),
|
authenticate: (appVersion, deviceId) => dispatch(doAuthenticate(appVersion, deviceId)),
|
||||||
|
deleteCompleteBlobs: () => dispatch(doDeleteCompleteBlobs()),
|
||||||
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
|
|||||||
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
balanceSubscribe: () => dispatch(doBalanceSubscribe()),
|
||||||
notify: data => dispatch(doNotify(data)),
|
notify: data => dispatch(doNotify(data)),
|
||||||
setEmailToVerify: email => dispatch(doUserEmailToVerify(email)),
|
setEmailToVerify: email => dispatch(doUserEmailToVerify(email)),
|
||||||
|
|
||||||
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
|
|
@ -117,10 +117,13 @@ class SplashScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateStatusCallback(status) {
|
_updateStatusCallback(status) {
|
||||||
|
const { deleteCompleteBlobs } = this.props;
|
||||||
const startupStatus = status.startup_status;
|
const startupStatus = status.startup_status;
|
||||||
// At the minimum, wallet should be started and blocks_behind equal to 0 before calling resolve
|
// At the minimum, wallet should be started and blocks_behind equal to 0 before calling resolve
|
||||||
const hasStarted = startupStatus.wallet && status.wallet.blocks_behind <= 0;
|
const hasStarted = startupStatus.wallet && status.wallet.blocks_behind <= 0;
|
||||||
if (hasStarted) {
|
if (hasStarted) {
|
||||||
|
deleteCompleteBlobs();
|
||||||
|
|
||||||
// Wait until we are able to resolve a name before declaring
|
// Wait until we are able to resolve a name before declaring
|
||||||
// that we are done.
|
// that we are done.
|
||||||
// TODO: This is a hack, and the logic should live in the daemon
|
// TODO: This is a hack, and the logic should live in the daemon
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
selectDownloadingByOutpoint,
|
selectDownloadingByOutpoint,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { Alert, NativeModules } from 'react-native';
|
import { Alert, NativeModules } from 'react-native';
|
||||||
|
import Constants from '../../constants';
|
||||||
![]() Replace the relative path with an alias or a build resolve Replace the relative path with an alias or a build resolve
|
|||||||
|
|
||||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||||
|
|
||||||
|
@ -40,14 +41,18 @@ export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
if (NativeModules.LbryDownloadManager) {
|
if (NativeModules.LbryDownloadManager) {
|
||||||
NativeModules.LbryDownloadManager.updateDownload(uri, fileInfo.file_name, 100, writtenBytes, totalBytes);
|
NativeModules.LbryDownloadManager.updateDownload(uri, fileInfo.file_name, 100, writtenBytes, totalBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once a download has been completed, delete the individual blob files to save space
|
||||||
|
Lbry.blob_list({ sd_hash: fileInfo.sd_hash }).then(hashes => {
|
||||||
|
hashes.forEach(hash => {
|
||||||
|
Lbry.blob_delete({ blob_hash: hash });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/*const notif = new window.Notification('LBRY Download Complete', {
|
/*const notif = new window.Notification('LBRY Download Complete', {
|
||||||
body: fileInfo.metadata.stream.metadata.title,
|
body: fileInfo.metadata.stream.metadata.title,
|
||||||
silent: false,
|
silent: false,
|
||||||
});
|
});*/
|
||||||
notif.onclick = () => {
|
|
||||||
ipcRenderer.send('focusWindow', 'main');
|
|
||||||
};*/
|
|
||||||
} else {
|
} else {
|
||||||
// ready to play
|
// ready to play
|
||||||
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
||||||
|
@ -66,7 +71,7 @@ export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
if (NativeModules.LbryDownloadManager) {
|
if (NativeModules.LbryDownloadManager) {
|
||||||
NativeModules.LbryDownloadManager.updateDownload(uri, fileInfo.file_name, progress, writtenBytes, totalBytes);
|
NativeModules.LbryDownloadManager.updateDownload(uri, fileInfo.file_name, progress, writtenBytes, totalBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||||
}, DOWNLOAD_POLL_INTERVAL);
|
}, DOWNLOAD_POLL_INTERVAL);
|
||||||
|
@ -96,7 +101,7 @@ export function doStartDownload(uri, outpoint) {
|
||||||
fileInfo,
|
fileInfo,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (NativeModules.LbryDownloadManager) {
|
if (NativeModules.LbryDownloadManager) {
|
||||||
NativeModules.LbryDownloadManager.startDownload(uri, fileInfo.file_name);
|
NativeModules.LbryDownloadManager.startDownload(uri, fileInfo.file_name);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +115,7 @@ export function doStopDownloadingFile(uri, fileInfo) {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
let params = { status: 'stop' };
|
let params = { status: 'stop' };
|
||||||
if (fileInfo.sd_hash) {
|
if (fileInfo.sd_hash) {
|
||||||
params.sd_hash = fileInfo.sd_hash;
|
params.sd_hash = fileInfo.sd_hash;
|
||||||
}
|
}
|
||||||
if (fileInfo.stream_hash) {
|
if (fileInfo.stream_hash) {
|
||||||
params.stream_hash = fileInfo.stream_hash;
|
params.stream_hash = fileInfo.stream_hash;
|
||||||
|
@ -122,11 +127,11 @@ export function doStopDownloadingFile(uri, fileInfo) {
|
||||||
data: {}
|
data: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (NativeModules.LbryDownloadManager) {
|
if (NativeModules.LbryDownloadManager) {
|
||||||
NativeModules.LbryDownloadManager.stopDownload(uri, fileInfo.file_name);
|
NativeModules.LbryDownloadManager.stopDownload(uri, fileInfo.file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should also delete the file after the user stops downloading
|
// Should also delete the file after the user stops downloading
|
||||||
dispatch(doDeleteFile(fileInfo.outpoint, uri));
|
dispatch(doDeleteFile(fileInfo.outpoint, uri));
|
||||||
};
|
};
|
||||||
|
@ -159,7 +164,7 @@ export function doLoadVideo(uri) {
|
||||||
uri,
|
uri,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Lbry.get({ uri })
|
Lbry.get({ uri })
|
||||||
.then(streamInfo => {
|
.then(streamInfo => {
|
||||||
const timeout =
|
const timeout =
|
||||||
|
@ -186,7 +191,7 @@ export function doLoadVideo(uri) {
|
||||||
type: ACTIONS.LOADING_VIDEO_FAILED,
|
type: ACTIONS.LOADING_VIDEO_FAILED,
|
||||||
data: { uri },
|
data: { uri },
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(doNotify({
|
dispatch(doNotify({
|
||||||
message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.`,
|
message: `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.`,
|
||||||
displayType: ['toast']
|
displayType: ['toast']
|
||||||
|
@ -301,3 +306,24 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
|
||||||
//setProgressBar(totalProgress);
|
//setProgressBar(totalProgress);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doDeleteCompleteBlobs() {
|
||||||
|
return dispatch => {
|
||||||
|
dispatch({
|
||||||
|
type: Constants.ACTION_DELETE_COMPLETED_BLOBS,
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
Lbry.file_list().then(files => {
|
||||||
|
files.forEach(fileInfo => {
|
||||||
|
if (fileInfo.completed) {
|
||||||
|
Lbry.blob_list({ sd_hash: fileInfo.sd_hash }).then(hashes => {
|
||||||
|
hashes.forEach(hash => {
|
||||||
|
Lbry.blob_delete({ blob_hash: hash });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Replace the relative path with an alias or a build resolve