user 6 rokov pred
rodič
commit
09aa54482b

+ 9 - 0
lib/contact-address.d.ts

@@ -0,0 +1,9 @@
+export declare class ContactAddress {
+    static fromPrefixedString(prefixed: string): ContactAddress;
+    type: string;
+    address: string;
+    constructor(type: string, address: string);
+    matches(search: string): boolean;
+    matchesExactly(addressType: string, addressValue: string): boolean;
+    toPrefixedString(): string;
+}

+ 31 - 0
lib/contact-address.js

@@ -0,0 +1,31 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+class ContactAddress {
+    static fromPrefixedString(prefixed) {
+        const components = prefixed.split(/:/);
+        const type = components.shift();
+        if (type == null) {
+            throw new Error('Invalid input: ' + prefixed);
+        }
+        const unprefixed = components.join(':');
+        return new ContactAddress(type, unprefixed);
+    }
+    constructor(type, address) {
+        this.type = type;
+        this.address = address;
+    }
+    matches(search) {
+        if (this.address.toLowerCase().trim().indexOf(search.toLowerCase().trim()) >= 0) {
+            return true;
+        }
+        return false;
+    }
+    matchesExactly(addressType, addressValue) {
+        return (this.type === addressType) && (this.address.toLowerCase().trim() === addressValue.toLowerCase().trim());
+    }
+    toPrefixedString() {
+        return `${this.type}:${this.address}`;
+    }
+}
+exports.ContactAddress = ContactAddress;
+//# sourceMappingURL=contact-address.js.map

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
lib/contact-address.js.map


+ 3 - 0
lib/contact-book.d.ts

@@ -6,4 +6,7 @@ export declare class ContactBook {
     getPrimaryPhoneNumber(): string;
     getFromPhoneNumbers(): string[];
     getFromEmailAddresses(): string[];
+    lookupByAddress(addressType: string, addressValue: string): ContactItem | undefined;
+    lookupById(id: string): ContactItem | undefined;
+    search(search: string): ContactItem[];
 }

+ 9 - 0
lib/contact-book.js

@@ -32,6 +32,15 @@ class ContactBook {
         }
         return result;
     }
+    lookupByAddress(addressType, addressValue) {
+        return this.items.find(item => item.matchesAddressExactly(addressType, addressValue));
+    }
+    lookupById(id) {
+        return this.items.find(item => item.id === id);
+    }
+    search(search) {
+        return this.items.filter(i => i.search(search));
+    }
 }
 exports.ContactBook = ContactBook;
 //# sourceMappingURL=contact-book.js.map

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 1
lib/contact-book.js.map


+ 4 - 3
lib/contact-item.d.ts

@@ -1,19 +1,20 @@
+import { ContactAddress } from "./contact-address";
 import { ContactParams } from "./contact-params";
 export declare class ContactItem {
     readonly data: ContactParams;
     readonly id: string;
     readonly hash: string;
-    addrs: string[];
+    addrs: ContactAddress[];
     groups: string[];
     names: string[];
     notes: string;
     canSendFromAddrs: string[];
     constructor(props: ContactParams);
-    matchesAddressOrName(search: string): boolean;
     matchesGroup(group: string): boolean;
     getFirstEmail(): string | undefined;
     getFirstPhone(): string | undefined;
-    getMatchingAddresses(search: string): string[];
+    search(search: string): boolean;
+    matchesAddressExactly(addressType: string, addressValue: string): boolean;
     getName(): string;
     getData(): ContactParams;
 }

+ 23 - 16
lib/contact-item.js

@@ -1,22 +1,17 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
+const contact_address_1 = require("./contact-address");
 class ContactItem {
     constructor(props) {
         this.data = props;
         this.hash = props.hash;
         this.id = props.id;
         this.canSendFromAddrs = props.canSendFromAddrs || [];
-        this.addrs = props.addrs || [];
+        this.addrs = (props.addrs || []).map(addrString => contact_address_1.ContactAddress.fromPrefixedString(addrString));
         this.groups = props.groups || [];
         this.names = props.names || [];
         this.notes = props.notes || '';
     }
-    matchesAddressOrName(search) {
-        if (this.addrs.filter(x => x.indexOf(search.trim()) >= 0).length > 0) {
-            return true;
-        }
-        return false;
-    }
     matchesGroup(group) {
         if (this.groups.filter(x => x === group.trim())[0].length > 0) {
             return true;
@@ -24,21 +19,33 @@ class ContactItem {
         return false;
     }
     getFirstEmail() {
-        const prefixed = this.addrs.filter(x => x.startsWith('email:'))[0];
-        if (prefixed == null) {
+        const first = this.addrs.filter(addr => addr.type === 'email')[0];
+        if (first == null) {
             return undefined;
         }
-        return prefixed.substring(6);
+        return first.address;
     }
     getFirstPhone() {
-        const prefixed = this.addrs.filter(x => x.startsWith('phone:'))[0];
-        if (prefixed == null) {
+        const first = this.addrs.filter(addr => addr.type === 'phone')[0];
+        if (first == null) {
             return undefined;
         }
-        return prefixed.substring(6);
+        return first.address;
     }
-    getMatchingAddresses(search) {
-        return this.addrs.filter(x => x.indexOf(search) >= 0);
+    search(search) {
+        if (this.names.find(i => i.toLowerCase().trim().indexOf(search.toLowerCase().trim()) >= 0)) {
+            return true;
+        }
+        if (this.addrs.find(addr => addr.matches(search))) {
+            return true;
+        }
+        return false;
+    }
+    matchesAddressExactly(addressType, addressValue) {
+        if (this.addrs.find(addr => addr.matchesExactly(addressType, addressValue))) {
+            return true;
+        }
+        return false;
     }
     getName() {
         if (this.names.length > 0) {
@@ -56,7 +63,7 @@ class ContactItem {
     }
     getData() {
         return {
-            addrs: this.addrs,
+            addrs: this.addrs.map(addr => addr.toPrefixedString()),
             canSendFromAddrs: this.canSendFromAddrs,
             groups: this.groups,
             hash: this.hash,

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 1
lib/contact-item.js.map


+ 1 - 2
lib/index.d.ts

@@ -29,10 +29,9 @@ export declare class BankClient {
     appendPrivate(peerAddr: string, topic: string, hash?: string, replaceHash?: string, deleteHash?: string): Promise<void>;
     retrievePrivate(peerAddr: string, topic: string): Promise<string>;
     subscribePrivate(peerAddr: string, topic: string, connectCallback: () => void, messageCallback: (data: any) => void): Promise<void>;
-    getOrCreateContact(peerId: string, contactAddr: string): Promise<ContactItem>;
+    getOrCreateContact(peerId: string, addressType: string, addressValue: string): Promise<ContactItem>;
     getAllContacts(peerId: string): Promise<ContactItem[]>;
     getContactBook(peerId: string): Promise<ContactBook>;
-    getContactById(peerId: string, contactId: string): Promise<ContactItem>;
     updateContact(peerId: string, contactId: string, newProperties: any): Promise<ContactItem>;
     getContentItemByHash(hash: string): Promise<ContentItem>;
     getItemsForCommaList(commaList: string): Promise<any[]>;

+ 13 - 17
lib/index.js

@@ -17,6 +17,7 @@ const ws_1 = __importDefault(require("ws"));
 const contact_item_1 = require("./contact-item");
 const content_item_1 = require("./content-item");
 const util_1 = require("./util");
+const contact_address_1 = require("./contact-address");
 class BankClient {
     constructor(urlBase, ipfsUrlBase, storage, webClient) {
         this.urlBase = urlBase;
@@ -232,24 +233,24 @@ class BankClient {
             yield this.connectWebsocket(peerAddr, topic, connectCallback, messageCallback);
         });
     }
-    getOrCreateContact(peerId, contactAddr) {
+    getOrCreateContact(peerId, addressType, addressValue) {
         return __awaiter(this, void 0, void 0, function* () {
-            const itemList = yield this.getAllContacts(peerId);
-            // console.log('contact hash for', contact, type, 'is', contactHash);
-            const existing = itemList.filter(item => item.addrs && item.addrs.includes(contactAddr))[0];
+            const contactBook = yield this.getContactBook(peerId);
+            const existing = contactBook.lookupByAddress(addressType, addressValue);
             if (existing != null) {
                 return existing;
             }
             const contactId = util_1.uuid();
             const newItem = {
                 addrs: [
-                    contactAddr
+                    new contact_address_1.ContactAddress(addressType, addressValue).toPrefixedString()
                 ],
                 id: contactId
             };
             const newItemHash = yield this.uploadSlimJSON(newItem);
             yield this.appendPrivate(peerId, '📇', newItemHash);
-            return yield this.getContactById(peerId, contactId);
+            const contactBook2 = yield this.getContactBook(peerId);
+            return (yield contactBook2.lookupById(contactId));
         });
     }
     getAllContacts(peerId) {
@@ -264,26 +265,21 @@ class BankClient {
             return new contact_book_1.ContactBook(yield this.getAllContacts(peerId));
         });
     }
-    getContactById(peerId, contactId) {
+    updateContact(peerId, contactId, newProperties) {
         return __awaiter(this, void 0, void 0, function* () {
-            const itemList = yield this.getAllContacts(peerId);
-            const existing = itemList.filter(item => item.id === contactId)[0];
+            const contactBook = yield this.getContactBook(peerId);
+            const existing = yield contactBook.lookupById(contactId);
             if (!existing) {
-                throw new Error('Cannot find contact with id ' + contactId);
+                throw new Error('missing contact with id ' + contactId);
             }
-            return new contact_item_1.ContactItem(existing);
-        });
-    }
-    updateContact(peerId, contactId, newProperties) {
-        return __awaiter(this, void 0, void 0, function* () {
-            const existing = yield this.getContactById(peerId, contactId);
             const newProps = util_1.mergeDeep({}, newProperties);
             delete newProps.id;
             const newItem = util_1.mergeDeep(existing, newProps);
             delete newItem.hash;
             const newItemHash = yield this.uploadSlimJSON(newItem);
             yield this.appendPrivate(peerId, '📇', newItemHash, existing.hash);
-            return yield this.getContactById(peerId, contactId);
+            const contactBook2 = yield this.getContactBook(peerId);
+            return (yield contactBook2.lookupById(contactId));
         });
     }
     getContentItemByHash(hash) {

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 1
lib/index.js.map


+ 35 - 0
src/contact-address.ts

@@ -0,0 +1,35 @@
+export class ContactAddress {
+
+  public static fromPrefixedString(prefixed: string) {
+    const components = prefixed.split(/:/);
+    const type = components.shift();
+    if (type == null) {
+      throw new Error('Invalid input: ' + prefixed);
+    }
+    const unprefixed = components.join(':');
+    return new ContactAddress(type, unprefixed);
+  }
+
+  public type: string;
+  public address: string;
+  
+  constructor(type: string, address: string) {
+    this.type = type;
+    this.address = address;
+  }
+
+  public matches(search: string): boolean {
+    if (this.address.toLowerCase().trim().indexOf(search.toLowerCase().trim()) >= 0) {
+      return true;
+    }
+    return false;
+  }
+
+  public matchesExactly(addressType: string, addressValue: string) {
+    return (this.type === addressType) && (this.address.toLowerCase().trim() === addressValue.toLowerCase().trim());
+  }
+
+  public toPrefixedString() {
+    return `${this.type}:${this.address}`;
+  }
+}

+ 11 - 0
src/contact-book.ts

@@ -40,5 +40,16 @@ export class ContactBook {
     return result;
   }
 
+  public lookupByAddress(addressType: string, addressValue: string): ContactItem | undefined {
+    return this.items.find(item => item.matchesAddressExactly(addressType, addressValue));
+  }
+
+  public lookupById(id: string): ContactItem | undefined {
+    return this.items.find(item => item.id === id);
+  }
+
+  public search(search: string): ContactItem[] {
+    return this.items.filter(i => i.search(search));
+  }
   
 }

+ 29 - 21
src/contact-item.ts

@@ -1,3 +1,4 @@
+import { ContactAddress } from "./contact-address";
 import { ContactParams } from "./contact-params";
 
 export class ContactItem {
@@ -5,30 +6,24 @@ export class ContactItem {
   public readonly data: ContactParams;
   public readonly id: string;
   public readonly hash: string;
-  public addrs: string[];
+  public addrs: ContactAddress[];
   public groups: string[];
   public names: string[];
   public notes: string;
   public canSendFromAddrs: string[];
   
+  
   constructor(props: ContactParams) {
     this.data = props;
     this.hash = props.hash;
     this.id = props.id;
     this.canSendFromAddrs = props.canSendFromAddrs || [];
-    this.addrs = props.addrs || [];
+    this.addrs = (props.addrs || []).map(addrString => ContactAddress.fromPrefixedString(addrString));
     this.groups = props.groups || [];
     this.names = props.names || [];
     this.notes = props.notes || '';
   }
 
-  public matchesAddressOrName(search: string): boolean {
-      if (this.addrs.filter(x => x.indexOf(search.trim()) >= 0).length > 0) {
-          return true;
-      }
-      return false;
-  }
-
   public matchesGroup(group: string): boolean {
     if (this.groups.filter(x => x === group.trim())[0].length > 0) {
         return true;
@@ -37,23 +32,36 @@ export class ContactItem {
   }
 
   public getFirstEmail(): string | undefined {
-      const prefixed = this.addrs.filter(x => x.startsWith('email:'))[0];
-      if (prefixed == null) {
-          return undefined;
-      }
-      return prefixed.substring(6);
+    const first = this.addrs.filter(addr => addr.type === 'email')[0];
+    if (first == null) {
+      return undefined;
+    }
+    return first.address;
   }
 
   public getFirstPhone(): string | undefined {
-    const prefixed = this.addrs.filter(x => x.startsWith('phone:'))[0];
-    if (prefixed == null) {
-        return undefined;
+    const first = this.addrs.filter(addr => addr.type === 'phone')[0];
+    if (first == null) {
+      return undefined;
     }
-    return prefixed.substring(6);
+    return first.address;
 }
 
-  public getMatchingAddresses(search: string): string[] {
-      return this.addrs.filter(x => x.indexOf(search) >= 0);
+  public search(search: string): boolean {
+    if (this.names.find(i => i.toLowerCase().trim().indexOf(search.toLowerCase().trim()) >= 0)) {
+      return true;
+    }
+    if (this.addrs.find(addr => addr.matches(search))) {
+      return true;
+    }
+    return false;
+  }
+
+  public matchesAddressExactly(addressType: string, addressValue: string): boolean {
+    if (this.addrs.find(addr => addr.matchesExactly(addressType, addressValue))) {
+      return true;
+    }
+    return false;
   }
 
   public getName(): string {
@@ -73,7 +81,7 @@ export class ContactItem {
 
   public getData(): ContactParams {
     return {
-      addrs: this.addrs,
+      addrs: this.addrs.map(addr => addr.toPrefixedString()),
       canSendFromAddrs: this.canSendFromAddrs,
       groups: this.groups,
       hash: this.hash,

+ 13 - 16
src/index.ts

@@ -9,6 +9,7 @@ import { Storage } from './storage';
 import { UploadItemParameters } from './upload-item-parameters';
 import { encodeHex, mergeDeep, uuid } from './util';
 import { IWebClient } from './webclient';
+import { ContactAddress } from './contact-address';
 
 export class BankClient {
 
@@ -226,23 +227,23 @@ export class BankClient {
       await this.connectWebsocket(peerAddr, topic, connectCallback, messageCallback);
     }
 
-    public async getOrCreateContact(peerId: string, contactAddr: string): Promise<ContactItem> {
-      const itemList = await this.getAllContacts(peerId);
-      // console.log('contact hash for', contact, type, 'is', contactHash);
-      const existing = itemList.filter(item => item.addrs && item.addrs.includes(contactAddr))[0];
+    public async getOrCreateContact(peerId: string, addressType: string, addressValue: string): Promise<ContactItem> {
+      const contactBook = await this.getContactBook(peerId);
+      const existing = contactBook.lookupByAddress(addressType, addressValue);
       if (existing != null) {
         return existing;
       }
       const contactId = uuid();
       const newItem = {
         addrs: [
-          contactAddr
+          new ContactAddress(addressType, addressValue).toPrefixedString()
         ],
         id: contactId
       };
       const newItemHash = await this.uploadSlimJSON(newItem);
       await this.appendPrivate(peerId, '📇', newItemHash);
-      return await this.getContactById(peerId, contactId);
+      const contactBook2 = await this.getContactBook(peerId);
+      return (await contactBook2.lookupById(contactId)) as ContactItem;
     }
 
     public async getAllContacts(peerId: string): Promise<ContactItem[]> {
@@ -255,24 +256,20 @@ export class BankClient {
       return new ContactBook(await this.getAllContacts(peerId));
     }
 
-    public async getContactById(peerId: string, contactId: string): Promise<ContactItem> {
-      const itemList = await this.getAllContacts(peerId);
-      const existing = itemList.filter(item => item.id === contactId)[0];
+    public async updateContact(peerId: string, contactId: string, newProperties: any): Promise<ContactItem> {
+      const contactBook = await this.getContactBook(peerId);
+      const existing = await contactBook.lookupById(contactId);
       if (!existing) {
-        throw new Error('Cannot find contact with id ' + contactId);
+        throw new Error('missing contact with id ' + contactId);
       }
-      return new ContactItem(existing);
-    }
-
-    public async updateContact(peerId: string, contactId: string, newProperties: any): Promise<ContactItem> {
-      const existing = await this.getContactById(peerId, contactId);
       const newProps: any = mergeDeep({}, newProperties);
       delete newProps.id;
       const newItem: any = mergeDeep(existing, newProps);
       delete newItem.hash;
       const newItemHash = await this.uploadSlimJSON(newItem);
       await this.appendPrivate(peerId, '📇', newItemHash, existing.hash);
-      return await this.getContactById(peerId, contactId);
+      const contactBook2 = await this.getContactBook(peerId);
+      return (await contactBook2.lookupById(contactId)) as ContactItem;
     }
 
     public async getContentItemByHash(hash: string): Promise<ContentItem> {