Add a badge to the dock for downloaded files
This commit is contained in:
parent
56aa4d2255
commit
0214422e6b
8 changed files with 146 additions and 0 deletions
|
@ -11,6 +11,10 @@ import { selectResolvingUris } from "selectors/content";
|
||||||
import { selectCostInfoForUri } from "selectors/cost_info";
|
import { selectCostInfoForUri } from "selectors/cost_info";
|
||||||
import { doOpenModal } from "actions/app";
|
import { doOpenModal } from "actions/app";
|
||||||
import { doClaimEligiblePurchaseRewards } from "actions/rewards";
|
import { doClaimEligiblePurchaseRewards } from "actions/rewards";
|
||||||
|
import { selectBadgeNumber } from "selectors/app";
|
||||||
|
import { selectTotalDownloadProgress } from "selectors/file_info";
|
||||||
|
import setBadge from "util/setBadge";
|
||||||
|
import setProgressBar from "util/setProgressBar";
|
||||||
import batchActions from "util/batchActions";
|
import batchActions from "util/batchActions";
|
||||||
|
|
||||||
export function doResolveUri(uri) {
|
export function doResolveUri(uri) {
|
||||||
|
@ -121,6 +125,11 @@ export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
fileInfo,
|
fileInfo,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const badgeNumber = selectBadgeNumber(getState());
|
||||||
|
setBadge(badgeNumber === 0 ? "" : `${badgeNumber}`);
|
||||||
|
const totalProgress = selectTotalDownloadProgress(getState());
|
||||||
|
setProgressBar(totalProgress);
|
||||||
} else {
|
} else {
|
||||||
// ready to play
|
// ready to play
|
||||||
const { total_bytes, written_bytes } = fileInfo;
|
const { total_bytes, written_bytes } = fileInfo;
|
||||||
|
@ -135,6 +144,10 @@ export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
progress,
|
progress,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const totalProgress = selectTotalDownloadProgress(getState());
|
||||||
|
setProgressBar(totalProgress);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dispatch(doUpdateLoadStatus(uri, outpoint));
|
dispatch(doUpdateLoadStatus(uri, outpoint));
|
||||||
}, 250);
|
}, 250);
|
||||||
|
|
|
@ -4,6 +4,7 @@ export const CLOSE_MODAL = "CLOSE_MODAL";
|
||||||
export const HISTORY_BACK = "HISTORY_BACK";
|
export const HISTORY_BACK = "HISTORY_BACK";
|
||||||
export const SHOW_SNACKBAR = "SHOW_SNACKBAR";
|
export const SHOW_SNACKBAR = "SHOW_SNACKBAR";
|
||||||
export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
|
export const REMOVE_SNACKBAR_SNACK = "REMOVE_SNACKBAR_SNACK";
|
||||||
|
export const WINDOW_FOCUSED = "WINDOW_FOCUSED";
|
||||||
|
|
||||||
export const DAEMON_READY = "DAEMON_READY";
|
export const DAEMON_READY = "DAEMON_READY";
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ import SplashScreen from "component/splash.js";
|
||||||
import AuthOverlay from "component/authOverlay";
|
import AuthOverlay from "component/authOverlay";
|
||||||
import { doChangePath, doNavigate, doDaemonReady } from "actions/app";
|
import { doChangePath, doNavigate, doDaemonReady } from "actions/app";
|
||||||
import { toQueryString } from "util/query_params";
|
import { toQueryString } from "util/query_params";
|
||||||
|
import { selectBadgeNumber } from "selectors/app";
|
||||||
|
import * as types from "constants/action_types";
|
||||||
|
|
||||||
const env = ENV;
|
const env = ENV;
|
||||||
const { remote, ipcRenderer, shell } = require("electron");
|
const { remote, ipcRenderer, shell } = require("electron");
|
||||||
|
@ -71,6 +73,25 @@ document.addEventListener("click", event => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const application = remote.app;
|
||||||
|
const dock = application.dock;
|
||||||
|
const win = remote.BrowserWindow.getFocusedWindow();
|
||||||
|
|
||||||
|
// Clear the badge when the window is focused
|
||||||
|
win.on("focus", () => {
|
||||||
|
if (!dock) return;
|
||||||
|
|
||||||
|
app.store.dispatch({ type: types.WINDOW_FOCUSED });
|
||||||
|
dock.setBadge("");
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateProgress = () => {
|
||||||
|
const state = app.store.getState();
|
||||||
|
const progress = selectTotalDownloadProgress(state);
|
||||||
|
|
||||||
|
win.setProgressBar(progress || -1);
|
||||||
|
};
|
||||||
|
|
||||||
const initialState = app.store.getState();
|
const initialState = app.store.getState();
|
||||||
|
|
||||||
// import whyDidYouUpdate from "why-did-you-update";
|
// import whyDidYouUpdate from "why-did-you-update";
|
||||||
|
|
|
@ -7,6 +7,10 @@ const currentPath = () => {
|
||||||
else return "/discover";
|
else return "/discover";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { remote } = require("electron");
|
||||||
|
const application = remote.app;
|
||||||
|
const win = remote.BrowserWindow.getFocusedWindow();
|
||||||
|
|
||||||
const reducers = {};
|
const reducers = {};
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
isLoaded: false,
|
isLoaded: false,
|
||||||
|
@ -16,6 +20,7 @@ const defaultState = {
|
||||||
daemonReady: false,
|
daemonReady: false,
|
||||||
obscureNsfw: !lbry.getClientSetting("showNsfw"),
|
obscureNsfw: !lbry.getClientSetting("showNsfw"),
|
||||||
hasSignature: false,
|
hasSignature: false,
|
||||||
|
badgeNumber: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
reducers[types.DAEMON_READY] = function(state, action) {
|
reducers[types.DAEMON_READY] = function(state, action) {
|
||||||
|
@ -120,6 +125,23 @@ reducers[types.REMOVE_SNACKBAR_SNACK] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reducers[types.DOWNLOADING_COMPLETED] = function(state, action) {
|
||||||
|
const badgeNumber = state.badgeNumber;
|
||||||
|
|
||||||
|
// Don't update the badge number if the window is focused
|
||||||
|
if (win.isFocused()) return Object.assign({}, state);
|
||||||
|
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
badgeNumber: badgeNumber + 1,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
reducers[types.WINDOW_FOCUSED] = function(state, action) {
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
badgeNumber: 0,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
export default function reducer(state = defaultState, action) {
|
||||||
const handler = reducers[action.type];
|
const handler = reducers[action.type];
|
||||||
if (handler) return handler(state, action);
|
if (handler) return handler(state, action);
|
||||||
|
|
|
@ -190,3 +190,8 @@ export const selectSnackBarSnacks = createSelector(
|
||||||
selectSnackBar,
|
selectSnackBar,
|
||||||
snackBar => snackBar.snacks || []
|
snackBar => snackBar.snacks || []
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const selectBadgeNumber = createSelector(
|
||||||
|
_selectState,
|
||||||
|
state => state.badgeNumber
|
||||||
|
);
|
||||||
|
|
|
@ -108,3 +108,66 @@ export const selectFileInfosPublished = createSelector(
|
||||||
return [...fileInfos, ...pendingFileInfos];
|
return [...fileInfos, ...pendingFileInfos];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// export const selectFileInfoForUri = (state, props) => {
|
||||||
|
// const claims = selectClaimsByUri(state),
|
||||||
|
// claim = claims[props.uri],
|
||||||
|
// fileInfos = selectAllFileInfos(state),
|
||||||
|
// outpoint = claim ? `${claim.txid}:${claim.nout}` : undefined;
|
||||||
|
|
||||||
|
// return outpoint && fileInfos ? fileInfos[outpoint] : undefined;
|
||||||
|
// };
|
||||||
|
|
||||||
|
export const selectFileInfosByUri = createSelector(
|
||||||
|
selectClaimsByUri,
|
||||||
|
selectAllFileInfos,
|
||||||
|
(claimsByUri, byOutpoint) => {
|
||||||
|
const fileInfos = {};
|
||||||
|
const uris = Object.keys(claimsByUri);
|
||||||
|
|
||||||
|
uris.forEach(uri => {
|
||||||
|
const claim = claimsByUri[uri];
|
||||||
|
if (claim) {
|
||||||
|
const outpoint = `${claim.txid}:${claim.nout}`;
|
||||||
|
const fileInfo = byOutpoint[outpoint];
|
||||||
|
|
||||||
|
if (fileInfo) fileInfos[uri] = fileInfo;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return fileInfos;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectDownloadingFileInfos = createSelector(
|
||||||
|
selectUrisDownloading,
|
||||||
|
selectFileInfosByUri,
|
||||||
|
(urisDownloading, byUri) => {
|
||||||
|
const uris = Object.keys(urisDownloading);
|
||||||
|
const fileInfos = [];
|
||||||
|
|
||||||
|
uris.forEach(uri => {
|
||||||
|
const fileInfo = byUri[uri];
|
||||||
|
|
||||||
|
if (fileInfo) fileInfos.push(fileInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
return fileInfos;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectTotalDownloadProgress = createSelector(
|
||||||
|
selectDownloadingFileInfos,
|
||||||
|
fileInfos => {
|
||||||
|
const progress = [];
|
||||||
|
|
||||||
|
fileInfos.forEach(fileInfo => {
|
||||||
|
progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalProgress = progress.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
if (fileInfos.length > 0) return totalProgress / fileInfos.length / 100.0;
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
12
ui/js/util/setBadge.js
Normal file
12
ui/js/util/setBadge.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
const { remote } = require("electron");
|
||||||
|
const application = remote.app;
|
||||||
|
const dock = application.dock;
|
||||||
|
const win = remote.BrowserWindow.getFocusedWindow();
|
||||||
|
const setBadge = text => {
|
||||||
|
if (!dock) return;
|
||||||
|
if (win.isFocused()) return;
|
||||||
|
|
||||||
|
dock.setBadge(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setBadge;
|
9
ui/js/util/setProgressBar.js
Normal file
9
ui/js/util/setProgressBar.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
const { remote } = require("electron");
|
||||||
|
const application = remote.app;
|
||||||
|
const win = remote.BrowserWindow.getFocusedWindow();
|
||||||
|
|
||||||
|
const setProgressBar = progress => {
|
||||||
|
win.setProgressBar(progress);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setProgressBar;
|
Loading…
Reference in a new issue