diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js
index b9891751a..defa06a3d 100644
--- a/ui/js/actions/content.js
+++ b/ui/js/actions/content.js
@@ -505,3 +505,34 @@ export function doPublish(params) {
});
};
}
+
+export function doAbandonClaim(claimId, txid, nout) {
+ return function(dispatch, getState) {
+ const state = getState();
+
+ dispatch({
+ type: types.ABANDON_CLAIM_STARTED,
+ data: {
+ claimId: claimId,
+ txid: txid,
+ nout: nout,
+ },
+ });
+
+ const success = dispatch({
+ type: types.ABANDON_CLAIM_SUCCEEDED,
+ data: {
+ claimId: claimId,
+ txid: txid,
+ nout: nout,
+ },
+ });
+
+ lbry
+ .claim_abandon({
+ txid: txid,
+ nout: nout,
+ })
+ .then(success);
+ };
+}
diff --git a/ui/js/actions/file_info.js b/ui/js/actions/file_info.js
index 49c949e5c..825dfa07c 100644
--- a/ui/js/actions/file_info.js
+++ b/ui/js/actions/file_info.js
@@ -102,10 +102,15 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
const fileInfo = byOutpoint[outpoint];
if (fileInfo) {
+ txid = fileInfo.outpoint.slice(0, -2);
+ nout = fileInfo.outpoint.slice(-1);
+
dispatch({
type: types.ABANDON_CLAIM_STARTED,
data: {
claimId: fileInfo.claim_id,
+ txid: txid,
+ nout: nout,
},
});
@@ -113,9 +118,16 @@ export function doDeleteFile(outpoint, deleteFromComputer, abandonClaim) {
type: types.ABANDON_CLAIM_SUCCEEDED,
data: {
claimId: fileInfo.claim_id,
+ txid: txid,
+ nout: nout,
},
});
- lbry.claim_abandon({ claim_id: fileInfo.claim_id }).then(success);
+ lbry
+ .claim_abandon({
+ txid: txid,
+ nout: nout,
+ })
+ .then(success);
}
}
diff --git a/ui/js/component/transactionList/index.js b/ui/js/component/transactionList/index.js
index 5a6c10b6b..39d5cde5e 100644
--- a/ui/js/component/transactionList/index.js
+++ b/ui/js/component/transactionList/index.js
@@ -1,15 +1,23 @@
import React from "react";
import { connect } from "react-redux";
import { doNavigate } from "actions/navigation";
+import { doAbandonClaim, doResolveUri } from "actions/content";
import { selectClaimedRewardsByTransactionId } from "selectors/rewards";
+import { selectAllMyClaimsByTxidNout } from "selectors/claims";
+import { selectResolvingUris } from "selectors/content";
import TransactionList from "./view";
const select = state => ({
rewards: selectClaimedRewardsByTransactionId(state),
+ myClaims: selectAllMyClaimsByTxidNout(state),
+ resolvingUris: selectResolvingUris(state),
});
const perform = dispatch => ({
navigate: (path, params) => dispatch(doNavigate(path, params)),
+ resolveUri: uri => dispatch(doResolveUri(uri)),
+ abandonClaim: (claimId, txid, nout) =>
+ dispatch(doAbandonClaim(claimId, txid, nout)),
});
-export default connect(null, perform)(TransactionList);
+export default connect(select, perform)(TransactionList);
diff --git a/ui/js/component/transactionList/internal/TransactionListItem.jsx b/ui/js/component/transactionList/internal/TransactionListItem.jsx
index fd4429bd3..93e9e56d2 100644
--- a/ui/js/component/transactionList/internal/TransactionListItem.jsx
+++ b/ui/js/component/transactionList/internal/TransactionListItem.jsx
@@ -6,8 +6,12 @@ import Link from "component/link";
import lbryuri from "lbryuri";
class TransactionListItem extends React.PureComponent {
+ abandonClaim(abandonData) {
+ this.props.revokeClaim(abandonData);
+ }
+
render() {
- const { reward, transaction } = this.props;
+ const { reward, transaction, isRevokeable } = this.props;
const {
amount,
claim_id: claimId,
@@ -16,8 +20,16 @@ class TransactionListItem extends React.PureComponent {
fee,
txid,
type,
+ nout,
} = transaction;
+ const abandonData = {
+ name: name,
+ claimId: claimId,
+ txid: txid,
+ nout: nout,
+ };
+
const dateFormat = {
month: "short",
day: "numeric",
@@ -80,6 +92,12 @@ class TransactionListItem extends React.PureComponent {
|
+
+ {isRevokeable &&
+ this.abandonClaim(abandonData)}>
+ {__("Revoke")}
+ }
+ |
);
}
diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx
index beb2f8514..48f476eb6 100644
--- a/ui/js/component/transactionList/view.jsx
+++ b/ui/js/component/transactionList/view.jsx
@@ -1,6 +1,7 @@
import React from "react";
import TransactionListItem from "./internal/TransactionListItem";
import FormField from "component/formField";
+import lbryuri from "lbryuri";
class TransactionList extends React.PureComponent {
constructor(props) {
@@ -23,6 +24,27 @@ class TransactionList extends React.PureComponent {
return !filter || filter == transaction.type;
}
+ isRevokeable(txid, nout) {
+ // a claim/support/update is revokable if it
+ // is in my claim list(claim_list_mine)
+ return this.props.myClaims.has(`${txid}:${nout}`);
+ }
+
+ revokeClaim(abandonData) {
+ const {
+ name: name,
+ claimId: claimId,
+ txid: txid,
+ nout: nout,
+ } = abandonData;
+
+ const uri = lbryuri.build({ name, claimId });
+ this.props.resolveUri(uri);
+ if (!this.props.resolvingUris.includes(uri)) {
+ this.props.abandonClaim(claimId, txid, nout);
+ }
+ }
+
render() {
const { emptyMessage, rewards, transactions } = this.props;
@@ -62,6 +84,7 @@ class TransactionList extends React.PureComponent {
{__("Type")} |
{__("Details")} |
{__("Transaction")} |
+ {__("Action")} |
@@ -70,6 +93,8 @@ class TransactionList extends React.PureComponent {
key={`${t.txid}:${t.nout}`}
transaction={t}
reward={rewards && rewards[t.txid]}
+ isRevokeable={this.isRevokeable(t.txid, t.nout)}
+ revokeClaim={this.revokeClaim.bind(this)}
/>
)}
diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js
index a3e4ae2b4..2f0a8658f 100644
--- a/ui/js/reducers/claims.js
+++ b/ui/js/reducers/claims.js
@@ -45,6 +45,9 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
const byId = Object.assign({}, state.byId);
const pendingById = Object.assign({}, state.pendingById);
const abandoningById = Object.assign({}, state.abandoningById);
+ const allMyClaimsByTxidNout = new Set(
+ claims.map(claim => `${claim.txid}:${claim.nout}`)
+ );
const myClaims = new Set(
claims
.map(claim => claim.claim_id)
@@ -78,6 +81,7 @@ reducers[types.FETCH_CLAIM_LIST_MINE_COMPLETED] = function(state, action) {
return Object.assign({}, state, {
isFetchingClaimListMine: false,
myClaims: myClaims,
+ allMyClaimsByTxidNout: allMyClaimsByTxidNout,
byId,
pendingById,
});
@@ -157,21 +161,35 @@ reducers[types.ABANDON_CLAIM_STARTED] = function(state, action) {
};
reducers[types.ABANDON_CLAIM_SUCCEEDED] = function(state, action) {
- const { claimId } = action.data;
+ const { claimId, txid, nout } = action.data;
const myClaims = new Set(state.myClaims);
const byId = Object.assign({}, state.byId);
const claimsByUri = Object.assign({}, state.claimsByUri);
+ const supports = byId[claimId].supports;
const uris = [];
- Object.keys(claimsByUri).forEach(uri => {
- if (claimsByUri[uri] === claimId) {
- delete claimsByUri[uri];
- }
- });
+ // This logic is needed when a claim has supports
+ // and it is the support that is being abandoned
+ // so we need to remove the support from the state
+ // but this is not working, even after calling resolve on the uri.
+ if (supports && supports.length > 0) {
+ indexToDelete = supports.findIndex(support => {
+ return support.txid === txid && support.nout === nout;
+ });
- delete byId[claimId];
- myClaims.delete(claimId);
+ supports.splice[(indexToDelete, 1)];
+ }
+ if (!supports || supports.length == 0) {
+ Object.keys(claimsByUri).forEach(uri => {
+ if (claimsByUri[uri] === claimId) {
+ delete claimsByUri[uri];
+ }
+ });
+
+ delete byId[claimId];
+ myClaims.delete(claimId);
+ }
return Object.assign({}, state, {
myClaims,
byId,
diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js
index c90b78843..608ceae67 100644
--- a/ui/js/selectors/claims.js
+++ b/ui/js/selectors/claims.js
@@ -157,6 +157,11 @@ export const selectMyClaimsWithoutChannels = createSelector(
myClaims => myClaims.filter(claim => !claim.name.match(/^@/))
);
+export const selectAllMyClaimsByTxidNout = createSelector(
+ _selectState,
+ state => state.allMyClaimsByTxidNout || {}
+);
+
export const selectMyClaimsOutpoints = createSelector(
selectMyClaims,
myClaims => {
diff --git a/ui/scss/component/_table.scss b/ui/scss/component/_table.scss
index 06f33aaf0..e17e90253 100644
--- a/ui/scss/component/_table.scss
+++ b/ui/scss/component/_table.scss
@@ -62,9 +62,10 @@ table.table-stretch {
}
table.table-transactions {
- td:nth-of-type(1) { width: 15%; }
- td:nth-of-type(2) { width: 15%; }
- td:nth-of-type(3) { width: 15%; }
- td:nth-of-type(4) { width: 40%; }
- td:nth-of-type(5) { width: 15%; }
+ td:nth-of-type(1) { width: 13%; }
+ td:nth-of-type(2) { width: 13%; }
+ td:nth-of-type(3) { width: 13%; }
+ td:nth-of-type(4) { width: 35%; }
+ td:nth-of-type(5) { width: 13%; }
+ td:nth-of-type(6) { width: 13%; }
}