@majikah/majik-message 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -134,6 +134,12 @@ export declare class MajikMessageMail {
|
|
|
134
134
|
* @returns true if successfully marked, false if already read
|
|
135
135
|
*/
|
|
136
136
|
markAsRead(recipientPublicKey: MajikMessagePublicKey): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Marks this mail as unread by removing a recipient from the read_by list.
|
|
139
|
+
* @param recipientPublicKey - The public key of the recipient marking as unread
|
|
140
|
+
* @returns true if successfully unmarked, false if wasn't read
|
|
141
|
+
*/
|
|
142
|
+
markAsUnread(recipientPublicKey: MajikMessagePublicKey): boolean;
|
|
137
143
|
/**
|
|
138
144
|
* Checks if a specific user has read this mail.
|
|
139
145
|
*/
|
|
@@ -557,6 +557,39 @@ export class MajikMessageMail {
|
|
|
557
557
|
throw new MailOperationError(`Failed to mark as read: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
558
558
|
}
|
|
559
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Marks this mail as unread by removing a recipient from the read_by list.
|
|
562
|
+
* @param recipientPublicKey - The public key of the recipient marking as unread
|
|
563
|
+
* @returns true if successfully unmarked, false if wasn't read
|
|
564
|
+
*/
|
|
565
|
+
markAsUnread(recipientPublicKey) {
|
|
566
|
+
try {
|
|
567
|
+
if (!recipientPublicKey ||
|
|
568
|
+
typeof recipientPublicKey !== "string" ||
|
|
569
|
+
recipientPublicKey.trim() === "") {
|
|
570
|
+
throw new MailValidationError("Recipient public key must be a non-empty string");
|
|
571
|
+
}
|
|
572
|
+
const trimmedKey = recipientPublicKey.trim();
|
|
573
|
+
// Verify recipient is in recipients list
|
|
574
|
+
if (!this._recipients.includes(trimmedKey)) {
|
|
575
|
+
throw new MailOperationError(`User ${trimmedKey} is not a recipient of this mail`);
|
|
576
|
+
}
|
|
577
|
+
// Check if not in read_by list (idempotent)
|
|
578
|
+
const readIndex = this._readBy.indexOf(trimmedKey);
|
|
579
|
+
if (readIndex === -1) {
|
|
580
|
+
return false; // Already unread
|
|
581
|
+
}
|
|
582
|
+
// Remove from read_by array
|
|
583
|
+
this._readBy.splice(readIndex, 1);
|
|
584
|
+
return true; // Successfully marked as unread
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
if (error instanceof MajikMailError) {
|
|
588
|
+
throw error;
|
|
589
|
+
}
|
|
590
|
+
throw new MailOperationError(`Failed to mark as unread: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
560
593
|
/**
|
|
561
594
|
* Checks if a specific user has read this mail.
|
|
562
595
|
*/
|
|
@@ -13,7 +13,7 @@ export interface ThreadMetadata {
|
|
|
13
13
|
messageCount?: number;
|
|
14
14
|
}
|
|
15
15
|
export interface DeletionApproval {
|
|
16
|
-
publicKey:
|
|
16
|
+
publicKey: MajikMessagePublicKey;
|
|
17
17
|
approvalHash: string;
|
|
18
18
|
timestamp: Date;
|
|
19
19
|
}
|
|
@@ -50,6 +50,8 @@ export interface MajikMessageThreadSummary {
|
|
|
50
50
|
has_unread: boolean;
|
|
51
51
|
starred: boolean;
|
|
52
52
|
subject?: string;
|
|
53
|
+
status: ThreadStatus;
|
|
54
|
+
deletion_requested: boolean;
|
|
53
55
|
}
|
|
54
56
|
export interface MajikMessageThreadJSON {
|
|
55
57
|
id: MajikMessageThreadID;
|
|
@@ -113,9 +115,10 @@ export declare class MajikMessageThread {
|
|
|
113
115
|
private static generateApprovalHash;
|
|
114
116
|
validate(): boolean;
|
|
115
117
|
close(): void;
|
|
116
|
-
|
|
118
|
+
hasDeletionApproval(publicKey: MajikMessagePublicKey): boolean;
|
|
119
|
+
requestDeletion(publicKey: MajikMessagePublicKey): void;
|
|
117
120
|
private updateDeletionStatus;
|
|
118
|
-
revokeDeletionRequest(publicKey:
|
|
121
|
+
revokeDeletionRequest(publicKey: MajikMessagePublicKey): void;
|
|
119
122
|
canBeDeleted(): boolean;
|
|
120
123
|
getDeletionProgress(): {
|
|
121
124
|
approved: number;
|
|
@@ -141,8 +144,8 @@ export declare class MajikMessageThread {
|
|
|
141
144
|
updateMetadata(metadata: Partial<ThreadMetadata>): this;
|
|
142
145
|
toJSON(): MajikMessageThreadJSON;
|
|
143
146
|
static fromJSON(json: MajikMessageThreadJSON | string): MajikMessageThread;
|
|
144
|
-
isOwner(publicKey:
|
|
145
|
-
isParticipant(publicKey:
|
|
147
|
+
isOwner(publicKey: MajikMessagePublicKey): boolean;
|
|
148
|
+
isParticipant(publicKey: MajikMessagePublicKey): boolean;
|
|
146
149
|
toString(): string;
|
|
147
150
|
/**
|
|
148
151
|
* Deduplicates and sorts participants to ensure consistent ordering
|
|
@@ -266,6 +266,11 @@ export class MajikMessageThread {
|
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
// ==================== Deletion Approval System ====================
|
|
269
|
+
hasDeletionApproval(publicKey) {
|
|
270
|
+
if (!this.isParticipant(publicKey))
|
|
271
|
+
return false;
|
|
272
|
+
return this._deletionApprovals.some((approval) => approval.publicKey === publicKey);
|
|
273
|
+
}
|
|
269
274
|
requestDeletion(publicKey) {
|
|
270
275
|
try {
|
|
271
276
|
// Validate public key is a participant
|
|
@@ -276,9 +281,7 @@ export class MajikMessageThread {
|
|
|
276
281
|
if (this._status === ThreadStatus.CLOSED) {
|
|
277
282
|
throw new OperationNotAllowedError("Cannot request deletion of a closed thread");
|
|
278
283
|
}
|
|
279
|
-
|
|
280
|
-
const existingApproval = this._deletionApprovals.find((approval) => approval.publicKey === publicKey);
|
|
281
|
-
if (existingApproval) {
|
|
284
|
+
if (this.hasDeletionApproval(publicKey)) {
|
|
282
285
|
throw new OperationNotAllowedError("This participant has already approved deletion");
|
|
283
286
|
}
|
|
284
287
|
// Create approval
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-message",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Encrypt and decrypt messages on any website or platform. Secure chats with keypairs and seed-based accounts. Open source.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.7",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|