Workflows: add mark as read/unread actions
Fixed: twpowertools:147
Change-Id: I6bb2363256cfd2a0ff3aafb4df71f24561576b27
diff --git a/src/contentScripts/communityConsole/workflows/actionRunners/readState.js b/src/contentScripts/communityConsole/workflows/actionRunners/readState.js
new file mode 100644
index 0000000..73d9a4f
--- /dev/null
+++ b/src/contentScripts/communityConsole/workflows/actionRunners/readState.js
@@ -0,0 +1,21 @@
+import {CCApi} from '../../../../common/api.js';
+import {getAuthUser} from '../../../../common/communityConsoleUtils.js';
+
+export default class ReadStateRunner {
+ execute(readState, thread) {
+ // Although this should in theory be the last message ID, it seems like
+ // setting 0 marks the entire thread as read anyways.
+ const lastMessageId = readState ? '0' : '-1';
+
+ return CCApi(
+ 'SetUserReadStateBulk', {
+ // bulkItem:
+ 1: [{
+ 1: thread.forumId,
+ 2: thread.threadId,
+ 3: lastMessageId,
+ }],
+ },
+ /* authenticated = */ true, getAuthUser());
+ }
+}
diff --git a/src/contentScripts/communityConsole/workflows/models/thread.js b/src/contentScripts/communityConsole/workflows/models/thread.js
index 0f54316..96f69de 100644
--- a/src/contentScripts/communityConsole/workflows/models/thread.js
+++ b/src/contentScripts/communityConsole/workflows/models/thread.js
@@ -97,6 +97,10 @@
return this._details?.['2']?.['9'];
}
+ get lastMessageId() {
+ return this._details?.['2']?.['10'];
+ }
+
get payload() {
return this._details?.['2']?.['13'];
}
diff --git a/src/contentScripts/communityConsole/workflows/runner.js b/src/contentScripts/communityConsole/workflows/runner.js
index d181d46..35c291c 100644
--- a/src/contentScripts/communityConsole/workflows/runner.js
+++ b/src/contentScripts/communityConsole/workflows/runner.js
@@ -2,6 +2,7 @@
import * as pb from '../../../workflows/proto/main_pb.js';
import CRRunner from './actionRunners/replyWithCR.js';
+import ReadStateRunner from './actionRunners/readState.js';
import Thread from './models/thread.js';
export default class WorkflowRunner {
@@ -16,6 +17,7 @@
// Initialize action runners:
this._CRRunner = new CRRunner();
+ this._ReadStateRunner = new ReadStateRunner();
}
start() {
@@ -57,6 +59,12 @@
return this._CRRunner.execute(
this._currentAction?.getReplyWithCrAction?.(), this._currentThread);
+ case pb.workflows.Action.ActionCase.MARK_AS_READ_ACTION:
+ return this._ReadStateRunner.execute(true, this._currentThread);
+
+ case pb.workflows.Action.ActionCase.MARK_AS_UNREAD_ACTION:
+ return this._ReadStateRunner.execute(false, this._currentThread);
+
default:
return Promise.reject(new Error('This action isn\'t supported yet.'));
}
diff --git a/src/workflows/manager/components/ActionEditor.js b/src/workflows/manager/components/ActionEditor.js
index c4b3faf..9a57509 100644
--- a/src/workflows/manager/components/ActionEditor.js
+++ b/src/workflows/manager/components/ActionEditor.js
@@ -61,6 +61,10 @@
</wf-action-reply-with-cr>
`;
+ case pb.workflows.Action.ActionCase.MARK_AS_READ_ACTION:
+ case pb.workflows.Action.ActionCase.MARK_AS_UNREAD_ACTION:
+ return nothing;
+
default:
return html`<p>This action has not yet been implemented.</p>`;
}
@@ -97,6 +101,10 @@
checkValidity() {
if (this.readOnly || !kSupportedActions.has(this._actionCase)) return true;
+
+ const s = this._specificActionEditor();
+ if (!s) return true;
+
return this._specificActionEditor().checkValidity();
}
@@ -167,6 +175,14 @@
value = new pb.workflows.Action.ReportAction;
this.action.setReportAction(value);
break;
+ case pb.workflows.Action.ActionCase.MARK_AS_READ_ACTION:
+ value = new pb.workflows.Action.MarkAsReadAction;
+ this.action.setMarkAsReadAction(value);
+ break;
+ case pb.workflows.Action.ActionCase.MARK_AS_UNREAD_ACTION:
+ value = new pb.workflows.Action.MarkAsUnreadAction;
+ this.action.setMarkAsUnreadAction(value);
+ break;
default:
this.action.clearReplyAction();
this.action.clearMoveAction();
@@ -178,6 +194,8 @@
this.action.clearSubscribeAction();
this.action.clearVoteAction();
this.action.clearReportAction();
+ this.action.clearMarkAsReadAction();
+ this.action.clearMarkAsUnreadAction();
}
this.requestUpdate();
diff --git a/src/workflows/manager/shared/actions.js b/src/workflows/manager/shared/actions.js
index 4551f1f..fcf12e1 100644
--- a/src/workflows/manager/shared/actions.js
+++ b/src/workflows/manager/shared/actions.js
@@ -13,9 +13,11 @@
17: 'Subscribe/unsubscribe to thread',
18: 'Vote thread',
19: 'Report thread',
+ 20: 'Mark as read',
+ 21: 'Mark as unread',
};
-export const kSupportedActions = new Set([6]);
+export const kSupportedActions = new Set([6, 20, 21]);
export const kActionStyles = css`
.action {
diff --git a/src/workflows/proto/main.proto b/src/workflows/proto/main.proto
index 3431a63..660be5e 100644
--- a/src/workflows/proto/main.proto
+++ b/src/workflows/proto/main.proto
@@ -77,6 +77,10 @@
ReportType report_type = 1;
}
+ message MarkAsReadAction {}
+
+ message MarkAsUnreadAction {}
+
oneof action {
ReplyAction reply_action = 1;
MoveAction move_action = 2;
@@ -88,6 +92,8 @@
SubscribeAction subscribe_action = 17;
VoteAction vote_action = 18;
ReportAction report_action = 19;
+ MarkAsReadAction mark_as_read_action = 20;
+ MarkAsUnreadAction mark_as_unread_action = 21;
}
}
diff --git a/src/workflows/proto/main_pb.js b/src/workflows/proto/main_pb.js
index d44f49d..25f18ef 100644
--- a/src/workflows/proto/main_pb.js
+++ b/src/workflows/proto/main_pb.js
@@ -19,6 +19,8 @@
goog.exportSymbol('workflows.Action.ActionCase', null, proto);
goog.exportSymbol('workflows.Action.AttributeAction', null, proto);
goog.exportSymbol('workflows.Action.AttributeAction.AttributeAction', null, proto);
+goog.exportSymbol('workflows.Action.MarkAsReadAction', null, proto);
+goog.exportSymbol('workflows.Action.MarkAsUnreadAction', null, proto);
goog.exportSymbol('workflows.Action.MarkDuplicateAction', null, proto);
goog.exportSymbol('workflows.Action.MoveAction', null, proto);
goog.exportSymbol('workflows.Action.ReplyAction', null, proto);
@@ -294,6 +296,48 @@
* @extends {jspb.Message}
* @constructor
*/
+proto.workflows.Action.MarkAsReadAction = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.workflows.Action.MarkAsReadAction, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ /**
+ * @public
+ * @override
+ */
+ proto.workflows.Action.MarkAsReadAction.displayName = 'proto.workflows.Action.MarkAsReadAction';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.workflows.Action.MarkAsUnreadAction = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.workflows.Action.MarkAsUnreadAction, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ /**
+ * @public
+ * @override
+ */
+ proto.workflows.Action.MarkAsUnreadAction.displayName = 'proto.workflows.Action.MarkAsUnreadAction';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
proto.workflows.Workflow = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, proto.workflows.Workflow.repeatedFields_, null);
};
@@ -474,7 +518,7 @@
* @private {!Array<!Array<number>>}
* @const
*/
-proto.workflows.Action.oneofGroups_ = [[1,2,3,4,5,6,16,17,18,19]];
+proto.workflows.Action.oneofGroups_ = [[1,2,3,4,5,6,16,17,18,19,20,21]];
/**
* @enum {number}
@@ -490,7 +534,9 @@
STAR_ACTION: 16,
SUBSCRIBE_ACTION: 17,
VOTE_ACTION: 18,
- REPORT_ACTION: 19
+ REPORT_ACTION: 19,
+ MARK_AS_READ_ACTION: 20,
+ MARK_AS_UNREAD_ACTION: 21
};
/**
@@ -540,7 +586,9 @@
starAction: (f = msg.getStarAction()) && proto.workflows.Action.StarAction.toObject(includeInstance, f),
subscribeAction: (f = msg.getSubscribeAction()) && proto.workflows.Action.SubscribeAction.toObject(includeInstance, f),
voteAction: (f = msg.getVoteAction()) && proto.workflows.Action.VoteAction.toObject(includeInstance, f),
- reportAction: (f = msg.getReportAction()) && proto.workflows.Action.ReportAction.toObject(includeInstance, f)
+ reportAction: (f = msg.getReportAction()) && proto.workflows.Action.ReportAction.toObject(includeInstance, f),
+ markAsReadAction: (f = msg.getMarkAsReadAction()) && proto.workflows.Action.MarkAsReadAction.toObject(includeInstance, f),
+ markAsUnreadAction: (f = msg.getMarkAsUnreadAction()) && proto.workflows.Action.MarkAsUnreadAction.toObject(includeInstance, f)
};
if (includeInstance) {
@@ -627,6 +675,16 @@
reader.readMessage(value,proto.workflows.Action.ReportAction.deserializeBinaryFromReader);
msg.setReportAction(value);
break;
+ case 20:
+ var value = new proto.workflows.Action.MarkAsReadAction;
+ reader.readMessage(value,proto.workflows.Action.MarkAsReadAction.deserializeBinaryFromReader);
+ msg.setMarkAsReadAction(value);
+ break;
+ case 21:
+ var value = new proto.workflows.Action.MarkAsUnreadAction;
+ reader.readMessage(value,proto.workflows.Action.MarkAsUnreadAction.deserializeBinaryFromReader);
+ msg.setMarkAsUnreadAction(value);
+ break;
default:
reader.skipField();
break;
@@ -736,6 +794,22 @@
proto.workflows.Action.ReportAction.serializeBinaryToWriter
);
}
+ f = message.getMarkAsReadAction();
+ if (f != null) {
+ writer.writeMessage(
+ 20,
+ f,
+ proto.workflows.Action.MarkAsReadAction.serializeBinaryToWriter
+ );
+ }
+ f = message.getMarkAsUnreadAction();
+ if (f != null) {
+ writer.writeMessage(
+ 21,
+ f,
+ proto.workflows.Action.MarkAsUnreadAction.serializeBinaryToWriter
+ );
+ }
};
@@ -2280,6 +2354,208 @@
};
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ * JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.workflows.Action.MarkAsReadAction.prototype.toObject = function(opt_includeInstance) {
+ return proto.workflows.Action.MarkAsReadAction.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ * the JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.workflows.Action.MarkAsReadAction} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.workflows.Action.MarkAsReadAction.toObject = function(includeInstance, msg) {
+ var f, obj = {
+
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.workflows.Action.MarkAsReadAction}
+ */
+proto.workflows.Action.MarkAsReadAction.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.workflows.Action.MarkAsReadAction;
+ return proto.workflows.Action.MarkAsReadAction.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.workflows.Action.MarkAsReadAction} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.workflows.Action.MarkAsReadAction}
+ */
+proto.workflows.Action.MarkAsReadAction.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.workflows.Action.MarkAsReadAction.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.workflows.Action.MarkAsReadAction.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.workflows.Action.MarkAsReadAction} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.workflows.Action.MarkAsReadAction.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+};
+
+
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ * JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.workflows.Action.MarkAsUnreadAction.prototype.toObject = function(opt_includeInstance) {
+ return proto.workflows.Action.MarkAsUnreadAction.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ * the JSPB instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.workflows.Action.MarkAsUnreadAction} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.workflows.Action.MarkAsUnreadAction.toObject = function(includeInstance, msg) {
+ var f, obj = {
+
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.workflows.Action.MarkAsUnreadAction}
+ */
+proto.workflows.Action.MarkAsUnreadAction.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.workflows.Action.MarkAsUnreadAction;
+ return proto.workflows.Action.MarkAsUnreadAction.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.workflows.Action.MarkAsUnreadAction} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.workflows.Action.MarkAsUnreadAction}
+ */
+proto.workflows.Action.MarkAsUnreadAction.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.workflows.Action.MarkAsUnreadAction.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.workflows.Action.MarkAsUnreadAction.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.workflows.Action.MarkAsUnreadAction} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.workflows.Action.MarkAsUnreadAction.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+};
+
+
/**
* optional ReplyAction reply_action = 1;
* @return {?proto.workflows.Action.ReplyAction}
@@ -2650,6 +2926,80 @@
};
+/**
+ * optional MarkAsReadAction mark_as_read_action = 20;
+ * @return {?proto.workflows.Action.MarkAsReadAction}
+ */
+proto.workflows.Action.prototype.getMarkAsReadAction = function() {
+ return /** @type{?proto.workflows.Action.MarkAsReadAction} */ (
+ jspb.Message.getWrapperField(this, proto.workflows.Action.MarkAsReadAction, 20));
+};
+
+
+/**
+ * @param {?proto.workflows.Action.MarkAsReadAction|undefined} value
+ * @return {!proto.workflows.Action} returns this
+*/
+proto.workflows.Action.prototype.setMarkAsReadAction = function(value) {
+ return jspb.Message.setOneofWrapperField(this, 20, proto.workflows.Action.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.workflows.Action} returns this
+ */
+proto.workflows.Action.prototype.clearMarkAsReadAction = function() {
+ return this.setMarkAsReadAction(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.workflows.Action.prototype.hasMarkAsReadAction = function() {
+ return jspb.Message.getField(this, 20) != null;
+};
+
+
+/**
+ * optional MarkAsUnreadAction mark_as_unread_action = 21;
+ * @return {?proto.workflows.Action.MarkAsUnreadAction}
+ */
+proto.workflows.Action.prototype.getMarkAsUnreadAction = function() {
+ return /** @type{?proto.workflows.Action.MarkAsUnreadAction} */ (
+ jspb.Message.getWrapperField(this, proto.workflows.Action.MarkAsUnreadAction, 21));
+};
+
+
+/**
+ * @param {?proto.workflows.Action.MarkAsUnreadAction|undefined} value
+ * @return {!proto.workflows.Action} returns this
+*/
+proto.workflows.Action.prototype.setMarkAsUnreadAction = function(value) {
+ return jspb.Message.setOneofWrapperField(this, 21, proto.workflows.Action.oneofGroups_[0], value);
+};
+
+
+/**
+ * Clears the message field making it undefined.
+ * @return {!proto.workflows.Action} returns this
+ */
+proto.workflows.Action.prototype.clearMarkAsUnreadAction = function() {
+ return this.setMarkAsUnreadAction(undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.workflows.Action.prototype.hasMarkAsUnreadAction = function() {
+ return jspb.Message.getField(this, 21) != null;
+};
+
+
/**
* List of repeated fields within this message type.