Improve Prettier monorepo configuration (#225)

* Add prettier configuration files

* Move prettier command to monorepo root

* Format all files
This commit is contained in:
Pavel 2022-02-23 15:49:00 +01:00 committed by GitHub
parent 3334108bdd
commit 4fb78c3f96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
222 changed files with 6443 additions and 9709 deletions

5
.prettierignore Normal file
View File

@ -0,0 +1,5 @@
**/dist
**/node_modules
.parcel-cache
.github
.vscode

5
.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"arrowParens": "avoid"
}

View File

@ -1,6 +1,6 @@
import React, { render } from 'react-dom'; import React, { render } from 'react-dom'
import { GroupChat, lightTheme } from '@status-im/react'; import { GroupChat, lightTheme } from '@status-im/react'
import { StrictMode } from 'react'; import { StrictMode } from 'react'
const App = () => { const App = () => {
return ( return (
@ -14,12 +14,12 @@ const App = () => {
}} }}
/> />
</div> </div>
); )
}; }
render( render(
<StrictMode> <StrictMode>
<App /> <App />
</StrictMode>, </StrictMode>,
document.getElementById('root') document.getElementById('root')
); )

View File

@ -1,6 +1,6 @@
import React, { render } from 'react-dom'; import React, { render } from 'react-dom'
import { CommunityChat, lightTheme } from '@status-im/react'; import { CommunityChat, lightTheme } from '@status-im/react'
import { StrictMode } from 'react'; import { StrictMode } from 'react'
const App = () => { const App = () => {
return ( return (
@ -14,12 +14,12 @@ const App = () => {
}} }}
/> />
</div> </div>
); )
}; }
render( render(
<StrictMode> <StrictMode>
<App /> <App />
</StrictMode>, </StrictMode>,
document.getElementById('root') document.getElementById('root')
); )

View File

@ -7,13 +7,13 @@
"keywords": [], "keywords": [],
"scripts": { "scripts": {
"fix": "run-s 'fix:*' && wsrun -e -c -s fix", "fix": "run-s 'fix:*' && wsrun -e -c -s fix",
"fix:prettier": "prettier \"./*.json\" --write",
"build": "wsrun -e -c -s build", "build": "wsrun -e -c -s build",
"format": "prettier --write .",
"test": "wsrun -e -c -s test" "test": "wsrun -e -c -s test"
}, },
"devDependencies": { "devDependencies": {
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.3.2", "prettier": "^2.5.1",
"wsrun": "^5.2.4" "wsrun": "^5.2.4"
}, },
"packageManager": "yarn@1.22.17" "packageManager": "yarn@1.22.17"

View File

@ -18,11 +18,9 @@
"build:esm": "tsc --module es2020 --target es2017 --outDir dist/esm", "build:esm": "tsc --module es2020 --target es2017 --outDir dist/esm",
"build:cjs": "tsc --outDir dist/cjs", "build:cjs": "tsc --outDir dist/cjs",
"fix": "run-s 'fix:*'", "fix": "run-s 'fix:*'",
"fix:prettier": "prettier \"src/**/*.ts\" \"./*.json\" --write",
"fix:lint": "eslint src --ext .ts --fix", "fix:lint": "eslint src --ext .ts --fix",
"test": "run-s 'test:*'", "test": "run-s 'test:*'",
"test:lint": "eslint src --ext .ts", "test:lint": "eslint src --ext .ts",
"test:prettier": "prettier \"src/**/*.ts\" \"./*.json\" --list-different",
"test:unit": "mocha", "test:unit": "mocha",
"proto": "run-s 'proto:*'", "proto": "run-s 'proto:*'",
"proto:lint": "buf lint", "proto:lint": "buf lint",
@ -47,7 +45,6 @@
"eslint-plugin-import": "^2.24.2", "eslint-plugin-import": "^2.24.2",
"mocha": "^9.1.1", "mocha": "^9.1.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.4.0",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
"ts-proto": "^1.83.0", "ts-proto": "^1.83.0",
"typescript": "^4.4.3" "typescript": "^4.4.3"

View File

@ -1,14 +1,14 @@
import { idToContentTopic } from "./contentTopic"; import { idToContentTopic } from './contentTopic'
import { createSymKeyFromPassword } from "./encryption"; import { createSymKeyFromPassword } from './encryption'
import { ChatMessage, Content } from "./wire/chat_message"; import { ChatMessage, Content } from './wire/chat_message'
import { CommunityChat } from "./wire/community_chat"; import { CommunityChat } from './wire/community_chat'
/** /**
* Represent a chat room. Only public chats are currently supported. * Represent a chat room. Only public chats are currently supported.
*/ */
export class Chat { export class Chat {
private lastClockValue?: number; private lastClockValue?: number
private lastMessage?: ChatMessage; private lastMessage?: ChatMessage
private constructor( private constructor(
public id: string, public id: string,
@ -24,17 +24,17 @@ export class Chat {
id: string, id: string,
communityChat?: CommunityChat communityChat?: CommunityChat
): Promise<Chat> { ): Promise<Chat> {
const symKey = await createSymKeyFromPassword(id); const symKey = await createSymKeyFromPassword(id)
return new Chat(id, symKey, communityChat); return new Chat(id, symKey, communityChat)
} }
public get contentTopic(): string { public get contentTopic(): string {
return idToContentTopic(this.id); return idToContentTopic(this.id)
} }
public createMessage(content: Content, responseTo?: string): ChatMessage { public createMessage(content: Content, responseTo?: string): ChatMessage {
const { timestamp, clock } = this._nextClockAndTimestamp(); const { timestamp, clock } = this._nextClockAndTimestamp()
const message = ChatMessage.createMessage( const message = ChatMessage.createMessage(
clock, clock,
@ -42,28 +42,28 @@ export class Chat {
this.id, this.id,
content, content,
responseTo responseTo
); )
this._updateClockFromMessage(message); this._updateClockFromMessage(message)
return message; return message
} }
public handleNewMessage(message: ChatMessage): void { public handleNewMessage(message: ChatMessage): void {
this._updateClockFromMessage(message); this._updateClockFromMessage(message)
} }
private _nextClockAndTimestamp(): { clock: number; timestamp: number } { private _nextClockAndTimestamp(): { clock: number; timestamp: number } {
let clock = this.lastClockValue; let clock = this.lastClockValue
const timestamp = Date.now(); const timestamp = Date.now()
if (!clock || clock < timestamp) { if (!clock || clock < timestamp) {
clock = timestamp; clock = timestamp
} else { } else {
clock += 1; clock += 1
} }
return { clock, timestamp }; return { clock, timestamp }
} }
private _updateClockFromMessage(message: ChatMessage): void { private _updateClockFromMessage(message: ChatMessage): void {
@ -72,14 +72,14 @@ export class Chat {
!this.lastMessage.clock || !this.lastMessage.clock ||
(message.clock && this.lastMessage.clock <= message.clock) (message.clock && this.lastMessage.clock <= message.clock)
) { ) {
this.lastMessage = message; this.lastMessage = message
} }
if ( if (
!this.lastClockValue || !this.lastClockValue ||
(message.clock && this.lastClockValue < message.clock) (message.clock && this.lastClockValue < message.clock)
) { ) {
this.lastClockValue = message.clock; this.lastClockValue = message.clock
} }
} }
} }

View File

@ -1,42 +1,42 @@
import { expect } from "chai"; import { expect } from 'chai'
import { Waku } from "js-waku"; import { Waku } from 'js-waku'
import { Community } from "./community"; import { Community } from './community'
import { CommunityDescription } from "./wire/community_description"; import { CommunityDescription } from './wire/community_description'
describe("Community [live data]", () => { describe('Community [live data]', () => {
before(function () { before(function () {
if (process.env.CI) { if (process.env.CI) {
// Skip live data test in CI // Skip live data test in CI
this.skip(); this.skip()
} }
}); })
it("Retrieves community description For DappConnect Test from Waku prod fleet", async function () { it('Retrieves community description For DappConnect Test from Waku prod fleet', async function () {
this.timeout(20000); this.timeout(20000)
const waku = await Waku.create({ bootstrap: { default: true } }); const waku = await Waku.create({ bootstrap: { default: true } })
await waku.waitForRemotePeer(); await waku.waitForRemotePeer()
const community = await Community.instantiateCommunity( const community = await Community.instantiateCommunity(
"0x02cf13719c8b836bebd4e430c497ee38e798a43e4d8c4760c34bbd9bf4f2434d26", '0x02cf13719c8b836bebd4e430c497ee38e798a43e4d8c4760c34bbd9bf4f2434d26',
waku waku
); )
const desc = community.description as CommunityDescription; const desc = community.description as CommunityDescription
expect(desc).to.not.be.undefined; expect(desc).to.not.be.undefined
expect(desc.identity?.displayName).to.eq("Test Community"); expect(desc.identity?.displayName).to.eq('Test Community')
const descChats = Array.from(desc.chats.values()).map( const descChats = Array.from(desc.chats.values()).map(
(chat) => chat?.identity?.displayName chat => chat?.identity?.displayName
); )
expect(descChats).to.include("Test Chat"); expect(descChats).to.include('Test Chat')
expect(descChats).to.include("Additional Chat"); expect(descChats).to.include('Additional Chat')
const chats = Array.from(community.chats.values()).map( const chats = Array.from(community.chats.values()).map(
(chat) => chat?.communityChat?.identity?.displayName chat => chat?.communityChat?.identity?.displayName
); )
expect(chats).to.include("Test Chat"); expect(chats).to.include('Test Chat')
expect(chats).to.include("Additional Chat"); expect(chats).to.include('Additional Chat')
}); })
}); })

View File

@ -1,23 +1,23 @@
import debug from "debug"; import debug from 'debug'
import { Waku } from "js-waku"; import { Waku } from 'js-waku'
import { Chat } from "./chat"; import { Chat } from './chat'
import { bufToHex, hexToBuf } from "./utils"; import { bufToHex, hexToBuf } from './utils'
import { CommunityChat } from "./wire/community_chat"; import { CommunityChat } from './wire/community_chat'
import { CommunityDescription } from "./wire/community_description"; import { CommunityDescription } from './wire/community_description'
const dbg = debug("communities:community"); const dbg = debug('communities:community')
export class Community { export class Community {
public publicKey: Uint8Array; public publicKey: Uint8Array
private waku: Waku; private waku: Waku
public chats: Map<string, Chat>; // Chat id, Chat public chats: Map<string, Chat> // Chat id, Chat
public description?: CommunityDescription; public description?: CommunityDescription
constructor(publicKey: Uint8Array, waku: Waku) { constructor(publicKey: Uint8Array, waku: Waku) {
this.publicKey = publicKey; this.publicKey = publicKey
this.waku = waku; this.waku = waku
this.chats = new Map(); this.chats = new Map()
} }
/** /**
@ -34,15 +34,15 @@ export class Community {
publicKey: string, publicKey: string,
waku: Waku waku: Waku
): Promise<Community> { ): Promise<Community> {
const community = new Community(hexToBuf(publicKey), waku); const community = new Community(hexToBuf(publicKey), waku)
await community.refreshCommunityDescription(); await community.refreshCommunityDescription()
return community; return community
} }
public get publicKeyStr(): string { public get publicKeyStr(): string {
return bufToHex(this.publicKey); return bufToHex(this.publicKey)
} }
/** /**
@ -53,20 +53,20 @@ export class Community {
const desc = await CommunityDescription.retrieve( const desc = await CommunityDescription.retrieve(
this.publicKey, this.publicKey,
this.waku.store this.waku.store
); )
if (!desc) { if (!desc) {
dbg(`Failed to retrieve Community Description for ${this.publicKeyStr}`); dbg(`Failed to retrieve Community Description for ${this.publicKeyStr}`)
return; return
} }
this.description = desc; this.description = desc
await Promise.all( await Promise.all(
Array.from(this.description.chats).map(([chatUuid, communityChat]) => { Array.from(this.description.chats).map(([chatUuid, communityChat]) => {
return this.instantiateChat(chatUuid, communityChat); return this.instantiateChat(chatUuid, communityChat)
}) })
); )
} }
/** /**
@ -80,13 +80,13 @@ export class Community {
communityChat: CommunityChat communityChat: CommunityChat
): Promise<void> { ): Promise<void> {
if (!this.description) if (!this.description)
throw "Failed to retrieve community description, cannot instantiate chat"; throw 'Failed to retrieve community description, cannot instantiate chat'
const chatId = this.publicKeyStr + chatUuid; const chatId = this.publicKeyStr + chatUuid
if (this.chats.get(chatId)) return; if (this.chats.get(chatId)) return
const chat = await Chat.create(chatId, communityChat); const chat = await Chat.create(chatId, communityChat)
this.chats.set(chatId, chat); this.chats.set(chatId, chat)
} }
} }

View File

@ -1,22 +1,22 @@
import { PageDirection, Waku, WakuMessage } from "js-waku"; import { PageDirection, Waku, WakuMessage } from 'js-waku'
import { idToContactCodeTopic } from "./contentTopic"; import { idToContactCodeTopic } from './contentTopic'
import { Identity } from "./identity"; import { Identity } from './identity'
import { StatusUpdate_StatusType } from "./proto/communities/v1/status_update"; import { StatusUpdate_StatusType } from './proto/communities/v1/status_update'
import { bufToHex, getLatestUserNickname } from "./utils"; import { bufToHex, getLatestUserNickname } from './utils'
import { ChatIdentity } from "./wire/chat_identity"; import { ChatIdentity } from './wire/chat_identity'
import { StatusUpdate } from "./wire/status_update"; import { StatusUpdate } from './wire/status_update'
const STATUS_BROADCAST_INTERVAL = 30000; const STATUS_BROADCAST_INTERVAL = 30000
const NICKNAME_BROADCAST_INTERVAL = 300000; const NICKNAME_BROADCAST_INTERVAL = 300000
export class Contacts { export class Contacts {
waku: Waku; waku: Waku
identity: Identity | undefined; identity: Identity | undefined
nickname?: string; nickname?: string
private callback: (publicKey: string, clock: number) => void; private callback: (publicKey: string, clock: number) => void
private callbackNickname: (publicKey: string, nickname: string) => void; private callbackNickname: (publicKey: string, nickname: string) => void
private contacts: string[] = []; private contacts: string[] = []
/** /**
* Contacts holds a list of user contacts and listens to their status broadcast * Contacts holds a list of user contacts and listens to their status broadcast
@ -38,14 +38,14 @@ export class Contacts {
callbackNickname: (publicKey: string, nickname: string) => void, callbackNickname: (publicKey: string, nickname: string) => void,
nickname?: string nickname?: string
) { ) {
this.waku = waku; this.waku = waku
this.identity = identity; this.identity = identity
this.nickname = nickname; this.nickname = nickname
this.callback = callback; this.callback = callback
this.callbackNickname = callbackNickname; this.callbackNickname = callbackNickname
this.startBroadcast(); this.startBroadcast()
if (identity) { if (identity) {
this.addContact(bufToHex(identity.publicKey)); this.addContact(bufToHex(identity.publicKey))
} }
} }
@ -57,44 +57,44 @@ export class Contacts {
* @param publicKey public key of user * @param publicKey public key of user
*/ */
public addContact(publicKey: string): void { public addContact(publicKey: string): void {
if (!this.contacts.find((e) => publicKey === e)) { if (!this.contacts.find(e => publicKey === e)) {
const now = new Date(); const now = new Date()
const callback = (wakuMessage: WakuMessage): void => { const callback = (wakuMessage: WakuMessage): void => {
if (wakuMessage.payload) { if (wakuMessage.payload) {
const msg = StatusUpdate.decode(wakuMessage.payload); const msg = StatusUpdate.decode(wakuMessage.payload)
this.callback(publicKey, msg.clock ?? 0); this.callback(publicKey, msg.clock ?? 0)
} }
}; }
this.contacts.push(publicKey); this.contacts.push(publicKey)
this.callback(publicKey, 0); this.callback(publicKey, 0)
this.waku.store.queryHistory([idToContactCodeTopic(publicKey)], { this.waku.store.queryHistory([idToContactCodeTopic(publicKey)], {
callback: (msgs) => msgs.forEach((e) => callback(e)), callback: msgs => msgs.forEach(e => callback(e)),
timeFilter: { timeFilter: {
startTime: new Date(now.getTime() - STATUS_BROADCAST_INTERVAL * 2), startTime: new Date(now.getTime() - STATUS_BROADCAST_INTERVAL * 2),
endTime: now, endTime: now,
}, },
}); })
this.waku.store.queryHistory([idToContactCodeTopic(publicKey)], { this.waku.store.queryHistory([idToContactCodeTopic(publicKey)], {
callback: (msgs) => callback: msgs =>
msgs.some((e) => { msgs.some(e => {
try { try {
if (e.payload) { if (e.payload) {
const chatIdentity = ChatIdentity.decode(e?.payload); const chatIdentity = ChatIdentity.decode(e?.payload)
if (chatIdentity) { if (chatIdentity) {
this.callbackNickname( this.callbackNickname(
publicKey, publicKey,
chatIdentity?.displayName ?? "" chatIdentity?.displayName ?? ''
); )
} }
return true; return true
} }
} catch { } catch {
return false; return false
} }
}), }),
pageDirection: PageDirection.BACKWARD, pageDirection: PageDirection.BACKWARD,
}); })
this.waku.relay.addObserver(callback, [idToContactCodeTopic(publicKey)]); this.waku.relay.addObserver(callback, [idToContactCodeTopic(publicKey)])
} }
} }
@ -103,67 +103,67 @@ export class Contacts {
if (this.identity) { if (this.identity) {
const statusUpdate = StatusUpdate.create( const statusUpdate = StatusUpdate.create(
StatusUpdate_StatusType.AUTOMATIC, StatusUpdate_StatusType.AUTOMATIC,
"" ''
); )
const msg = await WakuMessage.fromBytes( const msg = await WakuMessage.fromBytes(
statusUpdate.encode(), statusUpdate.encode(),
idToContactCodeTopic(bufToHex(this.identity.publicKey)) idToContactCodeTopic(bufToHex(this.identity.publicKey))
); )
this.waku.relay.send(msg); this.waku.relay.send(msg)
} }
}; }
const handleNickname = async (): Promise<void> => { const handleNickname = async (): Promise<void> => {
if (this.identity) { if (this.identity) {
const now = new Date().getTime(); const now = new Date().getTime()
const { clock, nickname: newNickname } = await getLatestUserNickname( const { clock, nickname: newNickname } = await getLatestUserNickname(
this.identity.publicKey, this.identity.publicKey,
this.waku this.waku
); )
if (this.nickname) { if (this.nickname) {
if (this.nickname !== newNickname) { if (this.nickname !== newNickname) {
await sendNickname(); await sendNickname()
} else { } else {
if (clock < now - NICKNAME_BROADCAST_INTERVAL) { if (clock < now - NICKNAME_BROADCAST_INTERVAL) {
await sendNickname(); await sendNickname()
} }
} }
} else { } else {
this.nickname = newNickname; this.nickname = newNickname
this.callbackNickname(bufToHex(this.identity.publicKey), newNickname); this.callbackNickname(bufToHex(this.identity.publicKey), newNickname)
if (clock < now - NICKNAME_BROADCAST_INTERVAL) { if (clock < now - NICKNAME_BROADCAST_INTERVAL) {
await sendNickname(); await sendNickname()
} }
} }
} }
setInterval(send, NICKNAME_BROADCAST_INTERVAL); setInterval(send, NICKNAME_BROADCAST_INTERVAL)
}; }
const sendNickname = async (): Promise<void> => { const sendNickname = async (): Promise<void> => {
if (this.identity) { if (this.identity) {
const publicKey = bufToHex(this.identity.publicKey); const publicKey = bufToHex(this.identity.publicKey)
if (this.nickname) { if (this.nickname) {
const chatIdentity = new ChatIdentity({ const chatIdentity = new ChatIdentity({
clock: new Date().getTime(), clock: new Date().getTime(),
color: "", color: '',
description: "", description: '',
emoji: "", emoji: '',
images: {}, images: {},
ensName: "", ensName: '',
displayName: this?.nickname ?? "", displayName: this?.nickname ?? '',
}); })
const msg = await WakuMessage.fromBytes( const msg = await WakuMessage.fromBytes(
chatIdentity.encode(), chatIdentity.encode(),
idToContactCodeTopic(publicKey), idToContactCodeTopic(publicKey),
{ sigPrivKey: this.identity.privateKey } { sigPrivKey: this.identity.privateKey }
); )
await this.waku.relay.send(msg); await this.waku.relay.send(msg)
} }
} }
}; }
handleNickname(); handleNickname()
send(); send()
setInterval(send, STATUS_BROADCAST_INTERVAL); setInterval(send, STATUS_BROADCAST_INTERVAL)
} }
} }

View File

@ -1,8 +1,8 @@
import { Buffer } from "buffer"; import { Buffer } from 'buffer'
import { keccak256 } from "js-sha3"; import { keccak256 } from 'js-sha3'
const TopicLength = 4; const TopicLength = 4
/** /**
* Get the content topic of for a given Chat or Community * Get the content topic of for a given Chat or Community
@ -10,13 +10,13 @@ const TopicLength = 4;
* @returns string The Waku v2 Content Topic. * @returns string The Waku v2 Content Topic.
*/ */
export function idToContentTopic(id: string): string { export function idToContentTopic(id: string): string {
const hash = keccak256.arrayBuffer(id); const hash = keccak256.arrayBuffer(id)
const topic = Buffer.from(hash).slice(0, TopicLength); const topic = Buffer.from(hash).slice(0, TopicLength)
return "/waku/1/" + "0x" + topic.toString("hex") + "/rfc26"; return '/waku/1/' + '0x' + topic.toString('hex') + '/rfc26'
} }
export function idToContactCodeTopic(id: string): string { export function idToContactCodeTopic(id: string): string {
return idToContentTopic(id + "-contact-code"); return idToContentTopic(id + '-contact-code')
} }

View File

@ -1,24 +1,24 @@
import { expect } from "chai"; import { expect } from 'chai'
import { createSymKeyFromPassword } from "./encryption"; import { createSymKeyFromPassword } from './encryption'
describe("Encryption", () => { describe('Encryption', () => {
it("Generate symmetric key from password", async function () { it('Generate symmetric key from password', async function () {
const str = "arbitrary data here"; const str = 'arbitrary data here'
const symKey = await createSymKeyFromPassword(str); const symKey = await createSymKeyFromPassword(str)
expect(Buffer.from(symKey).toString("hex")).to.eq( expect(Buffer.from(symKey).toString('hex')).to.eq(
"c49ad65ebf2a7b7253bf400e3d27719362a91b2c9b9f54d50a69117021666c33" 'c49ad65ebf2a7b7253bf400e3d27719362a91b2c9b9f54d50a69117021666c33'
); )
}); })
it("Generate symmetric key from password for chat", async function () { it('Generate symmetric key from password for chat', async function () {
const str = const str =
"0x02dcec6041fb999d65f1d33363e08c93d3c1f6f0fbbb26add383e2cf46c2b921f41dc14fd8-9a8b-4df5-a358-2c3067be5439"; '0x02dcec6041fb999d65f1d33363e08c93d3c1f6f0fbbb26add383e2cf46c2b921f41dc14fd8-9a8b-4df5-a358-2c3067be5439'
const symKey = await createSymKeyFromPassword(str); const symKey = await createSymKeyFromPassword(str)
expect(Buffer.from(symKey).toString("hex")).to.eq( expect(Buffer.from(symKey).toString('hex')).to.eq(
"76ff5bf0a74a8e724367c7fc003f066d477641f468768a8da2817addf5c2ce76" '76ff5bf0a74a8e724367c7fc003f066d477641f468768a8da2817addf5c2ce76'
); )
}); })
}); })

View File

@ -1,15 +1,15 @@
import pbkdf2 from "pbkdf2"; import pbkdf2 from 'pbkdf2'
const AESKeyLength = 32; // bytes const AESKeyLength = 32 // bytes
export async function createSymKeyFromPassword( export async function createSymKeyFromPassword(
password: string password: string
): Promise<Uint8Array> { ): Promise<Uint8Array> {
return pbkdf2.pbkdf2Sync( return pbkdf2.pbkdf2Sync(
Buffer.from(password, "utf-8"), Buffer.from(password, 'utf-8'),
"", '',
65356, 65356,
AESKeyLength, AESKeyLength,
"sha256" 'sha256'
); )
} }

View File

@ -1,68 +1,68 @@
import { Waku, WakuMessage } from "js-waku"; import { Waku, WakuMessage } from 'js-waku'
import { DecryptionMethod } from "js-waku/build/main/lib/waku_message"; import { DecryptionMethod } from 'js-waku/build/main/lib/waku_message'
import { createSymKeyFromPassword } from "./encryption"; import { createSymKeyFromPassword } from './encryption'
import { Identity } from "./identity"; import { Identity } from './identity'
import { MembershipUpdateEvent_EventType } from "./proto/communities/v1/membership_update_message"; import { MembershipUpdateEvent_EventType } from './proto/communities/v1/membership_update_message'
import { getNegotiatedTopic, getPartitionedTopic } from "./topics"; import { getNegotiatedTopic, getPartitionedTopic } from './topics'
import { bufToHex, compressPublicKey } from "./utils"; import { bufToHex, compressPublicKey } from './utils'
import { import {
MembershipSignedEvent, MembershipSignedEvent,
MembershipUpdateMessage, MembershipUpdateMessage,
} from "./wire/membership_update_message"; } from './wire/membership_update_message'
import { ChatMessage, Content } from "."; import { ChatMessage, Content } from '.'
type GroupMember = { type GroupMember = {
id: string; id: string
topic: string; topic: string
symKey: Uint8Array; symKey: Uint8Array
partitionedTopic: string; partitionedTopic: string
}; }
export type GroupChat = { export type GroupChat = {
chatId: string; chatId: string
members: GroupMember[]; members: GroupMember[]
admins?: string[]; admins?: string[]
name?: string; name?: string
removed: boolean; removed: boolean
}; }
export type GroupChatsType = { export type GroupChatsType = {
[id: string]: GroupChat; [id: string]: GroupChat
}; }
/* TODO: add chat messages encryption */ /* TODO: add chat messages encryption */
class GroupChatUsers { class GroupChatUsers {
private users: { [id: string]: GroupMember } = {}; private users: { [id: string]: GroupMember } = {}
private identity: Identity; private identity: Identity
public constructor(_identity: Identity) { public constructor(_identity: Identity) {
this.identity = _identity; this.identity = _identity
} }
public async getUser(id: string): Promise<GroupMember> { public async getUser(id: string): Promise<GroupMember> {
if (this.users[id]) { if (this.users[id]) {
return this.users[id]; return this.users[id]
} }
const topic = await getNegotiatedTopic(this.identity, id); const topic = await getNegotiatedTopic(this.identity, id)
const symKey = await createSymKeyFromPassword(topic); const symKey = await createSymKeyFromPassword(topic)
const partitionedTopic = getPartitionedTopic(id); const partitionedTopic = getPartitionedTopic(id)
const groupUser: GroupMember = { topic, symKey, id, partitionedTopic }; const groupUser: GroupMember = { topic, symKey, id, partitionedTopic }
this.users[id] = groupUser; this.users[id] = groupUser
return groupUser; return groupUser
} }
} }
export class GroupChats { export class GroupChats {
waku: Waku; waku: Waku
identity: Identity; identity: Identity
private callback: (chats: GroupChat) => void; private callback: (chats: GroupChat) => void
private removeCallback: (chats: GroupChat) => void; private removeCallback: (chats: GroupChat) => void
private addMessage: (message: ChatMessage, sender: string) => void; private addMessage: (message: ChatMessage, sender: string) => void
private groupChatUsers; private groupChatUsers
public chats: GroupChatsType = {}; public chats: GroupChatsType = {}
/** /**
* GroupChats holds a list of private chats and listens to their status broadcast * GroupChats holds a list of private chats and listens to their status broadcast
* *
@ -83,13 +83,13 @@ export class GroupChats {
removeCallback: (chat: GroupChat) => void, removeCallback: (chat: GroupChat) => void,
addMessage: (message: ChatMessage, sender: string) => void addMessage: (message: ChatMessage, sender: string) => void
) { ) {
this.waku = waku; this.waku = waku
this.identity = identity; this.identity = identity
this.groupChatUsers = new GroupChatUsers(identity); this.groupChatUsers = new GroupChatUsers(identity)
this.callback = callback; this.callback = callback
this.removeCallback = removeCallback; this.removeCallback = removeCallback
this.addMessage = addMessage; this.addMessage = addMessage
this.listen(); this.listen()
} }
/** /**
@ -104,26 +104,26 @@ export class GroupChats {
content: Content, content: Content,
responseTo?: string responseTo?: string
): Promise<void> { ): Promise<void> {
const now = Date.now(); const now = Date.now()
const chat = this.chats[chatId]; const chat = this.chats[chatId]
if (chat) { if (chat) {
await Promise.all( await Promise.all(
chat.members.map(async (member) => { chat.members.map(async member => {
const chatMessage = ChatMessage.createMessage( const chatMessage = ChatMessage.createMessage(
now, now,
now, now,
chatId, chatId,
content, content,
responseTo responseTo
); )
const wakuMessage = await WakuMessage.fromBytes( const wakuMessage = await WakuMessage.fromBytes(
chatMessage.encode(), chatMessage.encode(),
member.topic, member.topic,
{ sigPrivKey: this.identity.privateKey, symKey: member.symKey } { sigPrivKey: this.identity.privateKey, symKey: member.symKey }
); )
this.waku.relay.send(wakuMessage); this.waku.relay.send(wakuMessage)
}) })
); )
} }
} }
@ -132,18 +132,18 @@ export class GroupChats {
event: MembershipSignedEvent, event: MembershipSignedEvent,
useCallback: boolean useCallback: boolean
): Promise<void> { ): Promise<void> {
const signer = event.signer ? bufToHex(event.signer) : ""; const signer = event.signer ? bufToHex(event.signer) : ''
const thisUser = bufToHex(this.identity.publicKey); const thisUser = bufToHex(this.identity.publicKey)
const chat: GroupChat | undefined = this.chats[chatId]; const chat: GroupChat | undefined = this.chats[chatId]
if (signer) { if (signer) {
switch (event.event.type) { switch (event.event.type) {
case MembershipUpdateEvent_EventType.CHAT_CREATED: { case MembershipUpdateEvent_EventType.CHAT_CREATED: {
const members: GroupMember[] = []; const members: GroupMember[] = []
await Promise.all( await Promise.all(
event.event.members.map(async (member) => { event.event.members.map(async member => {
members.push(await this.groupChatUsers.getUser(member)); members.push(await this.groupChatUsers.getUser(member))
}) })
); )
await this.addChat( await this.addChat(
{ {
chatId: chatId, chatId: chatId,
@ -152,14 +152,14 @@ export class GroupChats {
removed: false, removed: false,
}, },
useCallback useCallback
); )
break; break
} }
case MembershipUpdateEvent_EventType.MEMBER_REMOVED: { case MembershipUpdateEvent_EventType.MEMBER_REMOVED: {
if (chat) { if (chat) {
chat.members = chat.members.filter( chat.members = chat.members.filter(
(member) => !event.event.members.includes(member.id) member => !event.event.members.includes(member.id)
); )
if (event.event.members.includes(thisUser)) { if (event.event.members.includes(thisUser)) {
await this.removeChat( await this.removeChat(
{ {
@ -167,41 +167,39 @@ export class GroupChats {
removed: true, removed: true,
}, },
useCallback useCallback
); )
} else { } else {
if (!chat.removed && useCallback) { if (!chat.removed && useCallback) {
this.callback(this.chats[chatId]); this.callback(this.chats[chatId])
} }
} }
} }
break; break
} }
case MembershipUpdateEvent_EventType.MEMBERS_ADDED: { case MembershipUpdateEvent_EventType.MEMBERS_ADDED: {
if (chat && chat.admins?.includes(signer)) { if (chat && chat.admins?.includes(signer)) {
const members: GroupMember[] = []; const members: GroupMember[] = []
await Promise.all( await Promise.all(
event.event.members.map(async (member) => { event.event.members.map(async member => {
members.push(await this.groupChatUsers.getUser(member)); members.push(await this.groupChatUsers.getUser(member))
}) })
); )
chat.members.push(...members); chat.members.push(...members)
if ( if (chat.members.findIndex(member => member.id === thisUser) > -1) {
chat.members.findIndex((member) => member.id === thisUser) > -1 chat.removed = false
) { await this.addChat(chat, useCallback)
chat.removed = false;
await this.addChat(chat, useCallback);
} }
} }
break; break
} }
case MembershipUpdateEvent_EventType.NAME_CHANGED: { case MembershipUpdateEvent_EventType.NAME_CHANGED: {
if (chat) { if (chat) {
if (chat.admins?.includes(signer)) { if (chat.admins?.includes(signer)) {
chat.name = event.event.name; chat.name = event.event.name
this.callback(chat); this.callback(chat)
} }
} }
break; break
} }
} }
} }
@ -213,22 +211,20 @@ export class GroupChats {
): Promise<void> { ): Promise<void> {
try { try {
if (message?.payload) { if (message?.payload) {
const membershipUpdate = MembershipUpdateMessage.decode( const membershipUpdate = MembershipUpdateMessage.decode(message.payload)
message.payload
);
await Promise.all( await Promise.all(
membershipUpdate.events.map( membershipUpdate.events.map(
async (event) => async event =>
await this.handleUpdateEvent( await this.handleUpdateEvent(
membershipUpdate.chatId, membershipUpdate.chatId,
event, event,
useCallback useCallback
) )
) )
); )
} }
} catch { } catch {
return; return
} }
} }
@ -239,19 +235,19 @@ export class GroupChats {
): void { ): void {
try { try {
if (message.payload) { if (message.payload) {
const chatMessage = ChatMessage.decode(message.payload); const chatMessage = ChatMessage.decode(message.payload)
if (chatMessage) { if (chatMessage) {
if (chatMessage.chatId === chat.chatId) { if (chatMessage.chatId === chat.chatId) {
let sender = member; let sender = member
if (message.signaturePublicKey) { if (message.signaturePublicKey) {
sender = compressPublicKey(message.signaturePublicKey); sender = compressPublicKey(message.signaturePublicKey)
} }
this.addMessage(chatMessage, sender); this.addMessage(chatMessage, sender)
} }
} }
} }
} catch { } catch {
return; return
} }
} }
@ -259,34 +255,34 @@ export class GroupChats {
chat: GroupChat, chat: GroupChat,
removeObserver?: boolean removeObserver?: boolean
): Promise<void> { ): Promise<void> {
const observerFunction = removeObserver ? "deleteObserver" : "addObserver"; const observerFunction = removeObserver ? 'deleteObserver' : 'addObserver'
await Promise.all( await Promise.all(
chat.members.map(async (member) => { chat.members.map(async member => {
if (!removeObserver) { if (!removeObserver) {
this.waku.relay.addDecryptionKey(member.symKey, { this.waku.relay.addDecryptionKey(member.symKey, {
method: DecryptionMethod.Symmetric, method: DecryptionMethod.Symmetric,
contentTopics: [member.topic], contentTopics: [member.topic],
}); })
} }
this.waku.relay[observerFunction]( this.waku.relay[observerFunction](
(message) => this.handleWakuChatMessage(message, chat, member.id), message => this.handleWakuChatMessage(message, chat, member.id),
[member.topic] [member.topic]
); )
}) })
); )
} }
private async addChat(chat: GroupChat, useCallback: boolean): Promise<void> { private async addChat(chat: GroupChat, useCallback: boolean): Promise<void> {
if (this.chats[chat.chatId]) { if (this.chats[chat.chatId]) {
this.chats[chat.chatId] = chat; this.chats[chat.chatId] = chat
if (useCallback) { if (useCallback) {
this.callback(chat); this.callback(chat)
} }
} else { } else {
this.chats[chat.chatId] = chat; this.chats[chat.chatId] = chat
if (useCallback) { if (useCallback) {
await this.handleChatObserver(chat); await this.handleChatObserver(chat)
this.callback(chat); this.callback(chat)
} }
} }
} }
@ -295,34 +291,34 @@ export class GroupChats {
chat: GroupChat, chat: GroupChat,
useCallback: boolean useCallback: boolean
): Promise<void> { ): Promise<void> {
this.chats[chat.chatId] = chat; this.chats[chat.chatId] = chat
if (useCallback) { if (useCallback) {
await this.handleChatObserver(chat, true); await this.handleChatObserver(chat, true)
this.removeCallback(chat); this.removeCallback(chat)
} }
} }
private async listen(): Promise<void> { private async listen(): Promise<void> {
const topic = getPartitionedTopic(bufToHex(this.identity.publicKey)); const topic = getPartitionedTopic(bufToHex(this.identity.publicKey))
const messages = await this.waku.store.queryHistory([topic]); const messages = await this.waku.store.queryHistory([topic])
messages.sort((a, b) => messages.sort((a, b) =>
(a?.timestamp?.getTime() ?? 0) < (b?.timestamp?.getTime() ?? 0) ? -1 : 1 (a?.timestamp?.getTime() ?? 0) < (b?.timestamp?.getTime() ?? 0) ? -1 : 1
); )
for (let i = 0; i < messages.length; i++) { for (let i = 0; i < messages.length; i++) {
await this.decodeUpdateMessage(messages[i], false); await this.decodeUpdateMessage(messages[i], false)
} }
this.waku.relay.addObserver( this.waku.relay.addObserver(
(message) => this.decodeUpdateMessage(message, true), message => this.decodeUpdateMessage(message, true),
[topic] [topic]
); )
await Promise.all( await Promise.all(
Object.values(this.chats).map(async (chat) => { Object.values(this.chats).map(async chat => {
if (!chat?.removed) { if (!chat?.removed) {
await this.handleChatObserver(chat); await this.handleChatObserver(chat)
this.callback(chat); this.callback(chat)
} }
}) })
); )
} }
private async sendUpdateMessage( private async sendUpdateMessage(
@ -331,11 +327,11 @@ export class GroupChats {
): Promise<void> { ): Promise<void> {
const wakuMessages = await Promise.all( const wakuMessages = await Promise.all(
members.map( members.map(
async (member) => async member =>
await WakuMessage.fromBytes(payload, member.partitionedTopic) await WakuMessage.fromBytes(payload, member.partitionedTopic)
) )
); )
wakuMessages.forEach((msg) => this.waku.relay.send(msg)); wakuMessages.forEach(msg => this.waku.relay.send(msg))
} }
/** /**
@ -346,11 +342,11 @@ export class GroupChats {
* @param name a name which chat should be changed to * @param name a name which chat should be changed to
*/ */
public async changeChatName(chatId: string, name: string): Promise<void> { public async changeChatName(chatId: string, name: string): Promise<void> {
const payload = MembershipUpdateMessage.create(chatId, this.identity); const payload = MembershipUpdateMessage.create(chatId, this.identity)
const chat = this.chats[chatId]; const chat = this.chats[chatId]
if (chat && payload) { if (chat && payload) {
payload.addNameChangeEvent(name); payload.addNameChangeEvent(name)
await this.sendUpdateMessage(payload.encode(), chat.members); await this.sendUpdateMessage(payload.encode(), chat.members)
} }
} }
@ -362,27 +358,27 @@ export class GroupChats {
* @param members a list of members to be added * @param members a list of members to be added
*/ */
public async addMembers(chatId: string, members: string[]): Promise<void> { public async addMembers(chatId: string, members: string[]): Promise<void> {
const payload = MembershipUpdateMessage.create(chatId, this.identity); const payload = MembershipUpdateMessage.create(chatId, this.identity)
const chat = this.chats[chatId]; const chat = this.chats[chatId]
if (chat && payload) { if (chat && payload) {
const newMembers: GroupMember[] = []; const newMembers: GroupMember[] = []
await Promise.all( await Promise.all(
members members
.filter( .filter(
(member) => member =>
!chat.members.map((chatMember) => chatMember.id).includes(member) !chat.members.map(chatMember => chatMember.id).includes(member)
) )
.map(async (member) => { .map(async member => {
newMembers.push(await this.groupChatUsers.getUser(member)); newMembers.push(await this.groupChatUsers.getUser(member))
}) })
); )
payload.addMembersAddedEvent(newMembers.map((member) => member.id)); payload.addMembersAddedEvent(newMembers.map(member => member.id))
await this.sendUpdateMessage(payload.encode(), [ await this.sendUpdateMessage(payload.encode(), [
...chat.members, ...chat.members,
...newMembers, ...newMembers,
]); ])
} }
} }
@ -395,17 +391,17 @@ export class GroupChats {
const payload = MembershipUpdateMessage.createChat( const payload = MembershipUpdateMessage.createChat(
this.identity, this.identity,
members members
).encode(); ).encode()
const newMembers: GroupMember[] = []; const newMembers: GroupMember[] = []
await Promise.all( await Promise.all(
members.map(async (member) => { members.map(async member => {
newMembers.push(await this.groupChatUsers.getUser(member)); newMembers.push(await this.groupChatUsers.getUser(member))
}) })
); )
await this.sendUpdateMessage(payload, newMembers); await this.sendUpdateMessage(payload, newMembers)
} }
/** /**
@ -414,10 +410,10 @@ export class GroupChats {
* @param chatId id of private group chat * @param chatId id of private group chat
*/ */
public async quitChat(chatId: string): Promise<void> { public async quitChat(chatId: string): Promise<void> {
const payload = MembershipUpdateMessage.create(chatId, this.identity); const payload = MembershipUpdateMessage.create(chatId, this.identity)
const chat = this.chats[chatId]; const chat = this.chats[chatId]
payload.addMemberRemovedEvent(bufToHex(this.identity.publicKey)); payload.addMemberRemovedEvent(bufToHex(this.identity.publicKey))
await this.sendUpdateMessage(payload.encode(), chat.members); await this.sendUpdateMessage(payload.encode(), chat.members)
} }
/** /**
@ -429,31 +425,31 @@ export class GroupChats {
startTime: Date, startTime: Date,
endTime: Date endTime: Date
): Promise<number> { ): Promise<number> {
const chat = this.chats[chatId]; const chat = this.chats[chatId]
if (!chat) if (!chat)
throw `Failed to retrieve messages, chat is not joined: ${chatId}`; throw `Failed to retrieve messages, chat is not joined: ${chatId}`
const _callback = (wakuMessages: WakuMessage[], member: string): void => { const _callback = (wakuMessages: WakuMessage[], member: string): void => {
wakuMessages.forEach((wakuMessage: WakuMessage) => wakuMessages.forEach((wakuMessage: WakuMessage) =>
this.handleWakuChatMessage(wakuMessage, chat, member) this.handleWakuChatMessage(wakuMessage, chat, member)
); )
}; }
const amountOfMessages: number[] = []; const amountOfMessages: number[] = []
await Promise.all( await Promise.all(
chat.members.map(async (member) => { chat.members.map(async member => {
const msgLength = ( const msgLength = (
await this.waku.store.queryHistory([member.topic], { await this.waku.store.queryHistory([member.topic], {
timeFilter: { startTime, endTime }, timeFilter: { startTime, endTime },
callback: (msg) => _callback(msg, member.id), callback: msg => _callback(msg, member.id),
decryptionKeys: [member.symKey], decryptionKeys: [member.symKey],
}) })
).length; ).length
amountOfMessages.push(msgLength); amountOfMessages.push(msgLength)
}) })
); )
return amountOfMessages.reduce((a, b) => a + b); return amountOfMessages.reduce((a, b) => a + b)
} }
} }

View File

@ -1,39 +1,39 @@
import { Buffer } from "buffer"; import { Buffer } from 'buffer'
import { keccak256 } from "js-sha3"; import { keccak256 } from 'js-sha3'
import { generatePrivateKey } from "js-waku"; import { generatePrivateKey } from 'js-waku'
import * as secp256k1 from "secp256k1"; import * as secp256k1 from 'secp256k1'
import { hexToBuf } from "./utils"; import { hexToBuf } from './utils'
export class Identity { export class Identity {
private pubKey: Uint8Array; private pubKey: Uint8Array
public constructor(public privateKey: Uint8Array) { public constructor(public privateKey: Uint8Array) {
this.pubKey = secp256k1.publicKeyCreate(this.privateKey, true); this.pubKey = secp256k1.publicKeyCreate(this.privateKey, true)
} }
public static generate(): Identity { public static generate(): Identity {
const privateKey = generatePrivateKey(); const privateKey = generatePrivateKey()
return new Identity(privateKey); return new Identity(privateKey)
} }
/** /**
* Hashes the payload with SHA3-256 and signs the result using the internal private key. * Hashes the payload with SHA3-256 and signs the result using the internal private key.
*/ */
public sign(payload: Uint8Array): Uint8Array { public sign(payload: Uint8Array): Uint8Array {
const hash = keccak256(payload); const hash = keccak256(payload)
const { signature, recid } = secp256k1.ecdsaSign( const { signature, recid } = secp256k1.ecdsaSign(
hexToBuf(hash), hexToBuf(hash),
this.privateKey this.privateKey
); )
return Buffer.concat([signature, Buffer.from([recid])]); return Buffer.concat([signature, Buffer.from([recid])])
} }
/** /**
* Returns the compressed public key. * Returns the compressed public key.
*/ */
public get publicKey(): Uint8Array { public get publicKey(): Uint8Array {
return this.pubKey; return this.pubKey
} }
} }

View File

@ -1,11 +1,11 @@
export { Identity } from "./identity"; export { Identity } from './identity'
export { Messenger } from "./messenger"; export { Messenger } from './messenger'
export { Community } from "./community"; export { Community } from './community'
export { Contacts } from "./contacts"; export { Contacts } from './contacts'
export { Chat } from "./chat"; export { Chat } from './chat'
export * from "./groupChats"; export * from './groupChats'
export * as utils from "./utils"; export * as utils from './utils'
export { ApplicationMetadataMessage } from "./wire/application_metadata_message"; export { ApplicationMetadataMessage } from './wire/application_metadata_message'
export { export {
ChatMessage, ChatMessage,
ContentType, ContentType,
@ -14,5 +14,5 @@ export {
ImageContent, ImageContent,
AudioContent, AudioContent,
TextContent, TextContent,
} from "./wire/chat_message"; } from './wire/chat_message'
export { getNodesFromHostedJson } from "js-waku"; export { getNodesFromHostedJson } from 'js-waku'

View File

@ -1,178 +1,177 @@
import { expect } from "chai"; import { expect } from 'chai'
import debug from "debug"; import debug from 'debug'
import { Protocols } from "js-waku/build/main/lib/waku"; import { Protocols } from 'js-waku/build/main/lib/waku'
import { Community } from "./community"; import { Community } from './community'
import { Identity } from "./identity"; import { Identity } from './identity'
import { Messenger } from "./messenger"; import { Messenger } from './messenger'
import { bufToHex } from "./utils"; import { bufToHex } from './utils'
import { ApplicationMetadataMessage } from "./wire/application_metadata_message"; import { ApplicationMetadataMessage } from './wire/application_metadata_message'
import { ContentType } from "./wire/chat_message"; import { ContentType } from './wire/chat_message'
const testChatId = "test-chat-id"; const testChatId = 'test-chat-id'
const dbg = debug("communities:test:messenger"); const dbg = debug('communities:test:messenger')
describe("Messenger", () => { describe('Messenger', () => {
let messengerAlice: Messenger; let messengerAlice: Messenger
let messengerBob: Messenger; let messengerBob: Messenger
let identityAlice: Identity; let identityAlice: Identity
let identityBob: Identity; let identityBob: Identity
beforeEach(async function () { beforeEach(async function () {
this.timeout(20_000); this.timeout(20_000)
dbg("Generate keys"); dbg('Generate keys')
identityAlice = Identity.generate(); identityAlice = Identity.generate()
identityBob = Identity.generate(); identityBob = Identity.generate()
dbg("Create messengers"); dbg('Create messengers')
;[messengerAlice, messengerBob] = await Promise.all([
[messengerAlice, messengerBob] = await Promise.all([
Messenger.create(identityAlice, { bootstrap: {} }), Messenger.create(identityAlice, { bootstrap: {} }),
Messenger.create(identityBob, { Messenger.create(identityBob, {
bootstrap: {}, bootstrap: {},
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, libp2p: { addresses: { listen: ['/ip4/0.0.0.0/tcp/0/ws'] } },
}), }),
]); ])
dbg("Connect messengers"); dbg('Connect messengers')
// Connect both messengers together for test purposes // Connect both messengers together for test purposes
messengerAlice.waku.addPeerToAddressBook( messengerAlice.waku.addPeerToAddressBook(
messengerBob.waku.libp2p.peerId, messengerBob.waku.libp2p.peerId,
messengerBob.waku.libp2p.multiaddrs messengerBob.waku.libp2p.multiaddrs
); )
dbg("Wait for remote peer"); dbg('Wait for remote peer')
await Promise.all([ await Promise.all([
messengerAlice.waku.waitForRemotePeer([Protocols.Relay]), messengerAlice.waku.waitForRemotePeer([Protocols.Relay]),
messengerBob.waku.waitForRemotePeer([Protocols.Relay]), messengerBob.waku.waitForRemotePeer([Protocols.Relay]),
]); ])
dbg("Messengers ready"); dbg('Messengers ready')
}); })
it("Sends & Receive public chat messages", async function () { it('Sends & Receive public chat messages', async function () {
this.timeout(10_000); this.timeout(10_000)
await messengerAlice.joinChatById(testChatId); await messengerAlice.joinChatById(testChatId)
await messengerBob.joinChatById(testChatId); await messengerBob.joinChatById(testChatId)
const text = "This is a message."; const text = 'This is a message.'
const receivedMessagePromise: Promise<ApplicationMetadataMessage> = const receivedMessagePromise: Promise<ApplicationMetadataMessage> =
new Promise((resolve) => { new Promise(resolve => {
messengerBob.addObserver((message) => { messengerBob.addObserver(message => {
resolve(message); resolve(message)
}, testChatId); }, testChatId)
}); })
await messengerAlice.sendMessage(testChatId, { await messengerAlice.sendMessage(testChatId, {
text, text,
contentType: ContentType.Text, contentType: ContentType.Text,
}); })
const receivedMessage = await receivedMessagePromise; const receivedMessage = await receivedMessagePromise
expect(receivedMessage.chatMessage?.text).to.eq(text); expect(receivedMessage.chatMessage?.text).to.eq(text)
}); })
it("public chat messages have signers", async function () { it('public chat messages have signers', async function () {
this.timeout(10_000); this.timeout(10_000)
await messengerAlice.joinChatById(testChatId); await messengerAlice.joinChatById(testChatId)
await messengerBob.joinChatById(testChatId); await messengerBob.joinChatById(testChatId)
const text = "This is a message."; const text = 'This is a message.'
const receivedMessagePromise: Promise<ApplicationMetadataMessage> = const receivedMessagePromise: Promise<ApplicationMetadataMessage> =
new Promise((resolve) => { new Promise(resolve => {
messengerBob.addObserver((message) => { messengerBob.addObserver(message => {
resolve(message); resolve(message)
}, testChatId); }, testChatId)
}); })
await messengerAlice.sendMessage(testChatId, { await messengerAlice.sendMessage(testChatId, {
text, text,
contentType: ContentType.Text, contentType: ContentType.Text,
}); })
const receivedMessage = await receivedMessagePromise; const receivedMessage = await receivedMessagePromise
expect(bufToHex(receivedMessage.signer!)).to.eq( expect(bufToHex(receivedMessage.signer!)).to.eq(
bufToHex(identityAlice.publicKey) bufToHex(identityAlice.publicKey)
); )
}); })
afterEach(async function () { afterEach(async function () {
this.timeout(5000); this.timeout(5000)
await messengerAlice.stop(); await messengerAlice.stop()
await messengerBob.stop(); await messengerBob.stop()
}); })
}); })
describe("Messenger [live data]", () => { describe('Messenger [live data]', () => {
before(function () { before(function () {
if (process.env.CI) { if (process.env.CI) {
// Skip live data test in CI // Skip live data test in CI
this.skip(); this.skip()
} }
}); })
let messenger: Messenger; let messenger: Messenger
let identity: Identity; let identity: Identity
beforeEach(async function () { beforeEach(async function () {
this.timeout(20_000); this.timeout(20_000)
dbg("Generate keys"); dbg('Generate keys')
identity = Identity.generate(); identity = Identity.generate()
dbg("Create messengers"); dbg('Create messengers')
messenger = await Messenger.create(identity, { messenger = await Messenger.create(identity, {
bootstrap: { default: true }, bootstrap: { default: true },
}); })
dbg("Wait to be connected to a peer"); dbg('Wait to be connected to a peer')
await messenger.waku.waitForRemotePeer(); await messenger.waku.waitForRemotePeer()
dbg("Messengers ready"); dbg('Messengers ready')
}); })
it("Receive public chat messages", async function () { it('Receive public chat messages', async function () {
this.timeout(20_000); this.timeout(20_000)
const community = await Community.instantiateCommunity( const community = await Community.instantiateCommunity(
"0x02cf13719c8b836bebd4e430c497ee38e798a43e4d8c4760c34bbd9bf4f2434d26", '0x02cf13719c8b836bebd4e430c497ee38e798a43e4d8c4760c34bbd9bf4f2434d26',
messenger.waku messenger.waku
); )
await messenger.joinChats(community.chats.values()); await messenger.joinChats(community.chats.values())
const startTime = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); const startTime = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
const endTime = new Date(); const endTime = new Date()
const chat = Array.from(community.chats.values()).find( const chat = Array.from(community.chats.values()).find(
(chat) => chat.communityChat?.identity?.displayName === "Test Chat" chat => chat.communityChat?.identity?.displayName === 'Test Chat'
); )
if (!chat) throw "Could not find foobar chat"; if (!chat) throw 'Could not find foobar chat'
console.log(chat); console.log(chat)
await messenger.retrievePreviousMessages( await messenger.retrievePreviousMessages(
chat.id, chat.id,
startTime, startTime,
endTime, endTime,
(metadata) => { metadata => {
metadata.forEach((m) => { metadata.forEach(m => {
console.log("Message", m.chatMessage?.text); console.log('Message', m.chatMessage?.text)
}); })
} }
); )
}); })
afterEach(async function () { afterEach(async function () {
this.timeout(5000); this.timeout(5000)
await messenger.stop(); await messenger.stop()
}); })
}); })

View File

@ -1,20 +1,20 @@
import debug from "debug"; import debug from 'debug'
import { Waku, WakuMessage } from "js-waku"; import { Waku, WakuMessage } from 'js-waku'
import { CreateOptions as WakuCreateOptions } from "js-waku/build/main/lib/waku"; import { CreateOptions as WakuCreateOptions } from 'js-waku/build/main/lib/waku'
import { DecryptionMethod } from "js-waku/build/main/lib/waku_message"; import { DecryptionMethod } from 'js-waku/build/main/lib/waku_message'
import { Chat } from "./chat"; import { Chat } from './chat'
import { Identity } from "./identity"; import { Identity } from './identity'
import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message"; import { ApplicationMetadataMessage_Type } from './proto/status/v1/application_metadata_message'
import { getLatestUserNickname } from "./utils"; import { getLatestUserNickname } from './utils'
import { ApplicationMetadataMessage } from "./wire/application_metadata_message"; import { ApplicationMetadataMessage } from './wire/application_metadata_message'
import { ChatMessage, Content } from "./wire/chat_message"; import { ChatMessage, Content } from './wire/chat_message'
const dbg = debug("communities:messenger"); const dbg = debug('communities:messenger')
export class Messenger { export class Messenger {
waku: Waku; waku: Waku
chatsById: Map<string, Chat>; chatsById: Map<string, Chat>
observers: { observers: {
[chatId: string]: Set< [chatId: string]: Set<
( (
@ -22,15 +22,15 @@ export class Messenger {
timestamp: Date, timestamp: Date,
chatId: string chatId: string
) => void ) => void
>; >
}; }
identity: Identity | undefined; identity: Identity | undefined
private constructor(identity: Identity | undefined, waku: Waku) { private constructor(identity: Identity | undefined, waku: Waku) {
this.identity = identity; this.identity = identity
this.waku = waku; this.waku = waku
this.chatsById = new Map(); this.chatsById = new Map()
this.observers = {}; this.observers = {}
} }
public static async create( public static async create(
@ -40,9 +40,9 @@ export class Messenger {
const _wakuOptions = Object.assign( const _wakuOptions = Object.assign(
{ bootstrap: { default: true } }, { bootstrap: { default: true } },
wakuOptions wakuOptions
); )
const waku = await Waku.create(_wakuOptions); const waku = await Waku.create(_wakuOptions)
return new Messenger(identity, waku); return new Messenger(identity, waku)
} }
/** /**
@ -53,9 +53,9 @@ export class Messenger {
* Use `addListener` to get messages received on this chat. * Use `addListener` to get messages received on this chat.
*/ */
public async joinChatById(chatId: string): Promise<void> { public async joinChatById(chatId: string): Promise<void> {
const chat = await Chat.create(chatId); const chat = await Chat.create(chatId)
await this.joinChat(chat); await this.joinChat(chat)
} }
/** /**
@ -65,10 +65,10 @@ export class Messenger {
*/ */
public async joinChats(chats: Iterable<Chat>): Promise<void> { public async joinChats(chats: Iterable<Chat>): Promise<void> {
await Promise.all( await Promise.all(
Array.from(chats).map((chat) => { Array.from(chats).map(chat => {
return this.joinChat(chat); return this.joinChat(chat)
}) })
); )
} }
/** /**
@ -78,31 +78,31 @@ export class Messenger {
*/ */
public async joinChat(chat: Chat): Promise<void> { public async joinChat(chat: Chat): Promise<void> {
if (this.chatsById.has(chat.id)) if (this.chatsById.has(chat.id))
throw `Failed to join chat, it is already joined: ${chat.id}`; throw `Failed to join chat, it is already joined: ${chat.id}`
this.waku.addDecryptionKey(chat.symKey, { this.waku.addDecryptionKey(chat.symKey, {
method: DecryptionMethod.Symmetric, method: DecryptionMethod.Symmetric,
contentTopics: [chat.contentTopic], contentTopics: [chat.contentTopic],
}); })
this.waku.relay.addObserver( this.waku.relay.addObserver(
(wakuMessage: WakuMessage) => { (wakuMessage: WakuMessage) => {
if (!wakuMessage.payload || !wakuMessage.timestamp) return; if (!wakuMessage.payload || !wakuMessage.timestamp) return
const message = ApplicationMetadataMessage.decode(wakuMessage.payload); const message = ApplicationMetadataMessage.decode(wakuMessage.payload)
switch (message.type) { switch (message.type) {
case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE:
this._handleNewChatMessage(chat, message, wakuMessage.timestamp); this._handleNewChatMessage(chat, message, wakuMessage.timestamp)
break; break
default: default:
dbg("Received unsupported message type", message.type); dbg('Received unsupported message type', message.type)
} }
}, },
[chat.contentTopic] [chat.contentTopic]
); )
this.chatsById.set(chat.id, chat); this.chatsById.set(chat.id, chat)
} }
/** /**
@ -114,24 +114,24 @@ export class Messenger {
responseTo?: string responseTo?: string
): Promise<void> { ): Promise<void> {
if (this.identity) { if (this.identity) {
const chat = this.chatsById.get(chatId); const chat = this.chatsById.get(chatId)
if (!chat) throw `Failed to send message, chat not joined: ${chatId}`; if (!chat) throw `Failed to send message, chat not joined: ${chatId}`
const chatMessage = chat.createMessage(content, responseTo); const chatMessage = chat.createMessage(content, responseTo)
const appMetadataMessage = ApplicationMetadataMessage.create( const appMetadataMessage = ApplicationMetadataMessage.create(
chatMessage.encode(), chatMessage.encode(),
ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE, ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE,
this.identity this.identity
); )
const wakuMessage = await WakuMessage.fromBytes( const wakuMessage = await WakuMessage.fromBytes(
appMetadataMessage.encode(), appMetadataMessage.encode(),
chat.contentTopic, chat.contentTopic,
{ symKey: chat.symKey, sigPrivKey: this.identity.privateKey } { symKey: chat.symKey, sigPrivKey: this.identity.privateKey }
); )
await this.waku.relay.send(wakuMessage); await this.waku.relay.send(wakuMessage)
} }
} }
@ -148,23 +148,23 @@ export class Messenger {
) => void, ) => void,
chatId: string | string[] chatId: string | string[]
): void { ): void {
let chats = []; let chats = []
if (typeof chatId === "string") { if (typeof chatId === 'string') {
chats.push(chatId); chats.push(chatId)
} else { } else {
chats = [...chatId]; chats = [...chatId]
} }
chats.forEach((id) => { chats.forEach(id => {
if (!this.chatsById.has(id)) if (!this.chatsById.has(id))
throw "Cannot add observer on a chat that is not joined."; throw 'Cannot add observer on a chat that is not joined.'
if (!this.observers[id]) { if (!this.observers[id]) {
this.observers[id] = new Set(); this.observers[id] = new Set()
} }
this.observers[id].add(observer); this.observers[id].add(observer)
}); })
} }
/** /**
@ -178,7 +178,7 @@ export class Messenger {
chatId: string chatId: string
): void { ): void {
if (this.observers[chatId]) { if (this.observers[chatId]) {
this.observers[chatId].delete(observer); this.observers[chatId].delete(observer)
} }
} }
@ -186,7 +186,7 @@ export class Messenger {
* Stops the messenger. * Stops the messenger.
*/ */
public async stop(): Promise<void> { public async stop(): Promise<void> {
await this.waku.stop(); await this.waku.stop()
} }
/** /**
@ -202,43 +202,43 @@ export class Messenger {
endTime: Date, endTime: Date,
callback?: (messages: ApplicationMetadataMessage[]) => void callback?: (messages: ApplicationMetadataMessage[]) => void
): Promise<number> { ): Promise<number> {
const chat = this.chatsById.get(chatId); const chat = this.chatsById.get(chatId)
if (!chat) if (!chat)
throw `Failed to retrieve messages, chat is not joined: ${chatId}`; throw `Failed to retrieve messages, chat is not joined: ${chatId}`
const _callback = (wakuMessages: WakuMessage[]): void => { const _callback = (wakuMessages: WakuMessage[]): void => {
const isDefined = ( const isDefined = (
msg: ApplicationMetadataMessage | undefined msg: ApplicationMetadataMessage | undefined
): msg is ApplicationMetadataMessage => { ): msg is ApplicationMetadataMessage => {
return !!msg; return !!msg
}; }
const messages = wakuMessages.map((wakuMessage: WakuMessage) => { const messages = wakuMessages.map((wakuMessage: WakuMessage) => {
if (!wakuMessage.payload || !wakuMessage.timestamp) return; if (!wakuMessage.payload || !wakuMessage.timestamp) return
const message = ApplicationMetadataMessage.decode(wakuMessage.payload); const message = ApplicationMetadataMessage.decode(wakuMessage.payload)
switch (message.type) { switch (message.type) {
case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE:
this._handleNewChatMessage(chat, message, wakuMessage.timestamp); this._handleNewChatMessage(chat, message, wakuMessage.timestamp)
return message; return message
default: default:
dbg("Retrieved unsupported message type", message.type); dbg('Retrieved unsupported message type', message.type)
return; return
} }
}); })
if (callback) { if (callback) {
callback(messages.filter(isDefined)); callback(messages.filter(isDefined))
} }
}; }
const allMessages = await this.waku.store.queryHistory( const allMessages = await this.waku.store.queryHistory(
[chat.contentTopic], [chat.contentTopic],
{ {
timeFilter: { startTime, endTime }, timeFilter: { startTime, endTime },
callback: _callback, callback: _callback,
} }
); )
return allMessages.length; return allMessages.length
} }
private _handleNewChatMessage( private _handleNewChatMessage(
@ -246,15 +246,15 @@ export class Messenger {
message: ApplicationMetadataMessage, message: ApplicationMetadataMessage,
timestamp: Date timestamp: Date
): void { ): void {
if (!message.payload || !message.type || !message.signature) return; if (!message.payload || !message.type || !message.signature) return
const chatMessage = ChatMessage.decode(message.payload); const chatMessage = ChatMessage.decode(message.payload)
chat.handleNewMessage(chatMessage); chat.handleNewMessage(chatMessage)
if (this.observers[chat.id]) { if (this.observers[chat.id]) {
this.observers[chat.id].forEach((observer) => { this.observers[chat.id].forEach(observer => {
observer(message, timestamp, chat.id); observer(message, timestamp, chat.id)
}); })
} }
} }
@ -262,7 +262,7 @@ export class Messenger {
const { clock, nickname } = await getLatestUserNickname( const { clock, nickname } = await getLatestUserNickname(
publicKey, publicKey,
this.waku this.waku
); )
return clock > 0 && nickname !== ""; return clock > 0 && nickname !== ''
} }
} }

View File

@ -1,33 +1,33 @@
/* eslint-disable */ /* eslint-disable */
import Long from "long"; import Long from 'long'
import _m0 from "protobufjs/minimal"; import _m0 from 'protobufjs/minimal'
import { import {
ImageType, ImageType,
imageTypeFromJSON, imageTypeFromJSON,
imageTypeToJSON, imageTypeToJSON,
} from "../../communities/v1/enums"; } from '../../communities/v1/enums'
export const protobufPackage = "communities.v1"; export const protobufPackage = 'communities.v1'
/** ChatIdentity represents the user defined identity associated with their public chat key */ /** ChatIdentity represents the user defined identity associated with their public chat key */
export interface ChatIdentity { export interface ChatIdentity {
/** Lamport timestamp of the message */ /** Lamport timestamp of the message */
clock: number; clock: number
/** ens_name is the valid ENS name associated with the chat key */ /** ens_name is the valid ENS name associated with the chat key */
ensName: string; ensName: string
/** images is a string indexed mapping of images associated with an identity */ /** images is a string indexed mapping of images associated with an identity */
images: { [key: string]: IdentityImage }; images: { [key: string]: IdentityImage }
/** display name is the user set identity, valid only for organisations */ /** display name is the user set identity, valid only for organisations */
displayName: string; displayName: string
/** description is the user set description, valid only for organisations */ /** description is the user set description, valid only for organisations */
description: string; description: string
color: string; color: string
emoji: string; emoji: string
} }
export interface ChatIdentity_ImagesEntry { export interface ChatIdentity_ImagesEntry {
key: string; key: string
value: IdentityImage | undefined; value: IdentityImage | undefined
} }
/** ProfileImage represents data associated with a user's profile image */ /** ProfileImage represents data associated with a user's profile image */
@ -36,11 +36,11 @@ export interface IdentityImage {
* payload is a context based payload for the profile image data, * payload is a context based payload for the profile image data,
* context is determined by the `source_type` * context is determined by the `source_type`
*/ */
payload: Uint8Array; payload: Uint8Array
/** source_type signals the image payload source */ /** source_type signals the image payload source */
sourceType: IdentityImage_SourceType; sourceType: IdentityImage_SourceType
/** image_type signals the image type and method of parsing the payload */ /** image_type signals the image type and method of parsing the payload */
imageType: ImageType; imageType: ImageType
} }
/** SourceType are the predefined types of image source allowed */ /** SourceType are the predefined types of image source allowed */
@ -63,18 +63,18 @@ export function identityImage_SourceTypeFromJSON(
): IdentityImage_SourceType { ): IdentityImage_SourceType {
switch (object) { switch (object) {
case 0: case 0:
case "UNKNOWN_SOURCE_TYPE": case 'UNKNOWN_SOURCE_TYPE':
return IdentityImage_SourceType.UNKNOWN_SOURCE_TYPE; return IdentityImage_SourceType.UNKNOWN_SOURCE_TYPE
case 1: case 1:
case "RAW_PAYLOAD": case 'RAW_PAYLOAD':
return IdentityImage_SourceType.RAW_PAYLOAD; return IdentityImage_SourceType.RAW_PAYLOAD
case 2: case 2:
case "ENS_AVATAR": case 'ENS_AVATAR':
return IdentityImage_SourceType.ENS_AVATAR; return IdentityImage_SourceType.ENS_AVATAR
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return IdentityImage_SourceType.UNRECOGNIZED; return IdentityImage_SourceType.UNRECOGNIZED
} }
} }
@ -83,24 +83,24 @@ export function identityImage_SourceTypeToJSON(
): string { ): string {
switch (object) { switch (object) {
case IdentityImage_SourceType.UNKNOWN_SOURCE_TYPE: case IdentityImage_SourceType.UNKNOWN_SOURCE_TYPE:
return "UNKNOWN_SOURCE_TYPE"; return 'UNKNOWN_SOURCE_TYPE'
case IdentityImage_SourceType.RAW_PAYLOAD: case IdentityImage_SourceType.RAW_PAYLOAD:
return "RAW_PAYLOAD"; return 'RAW_PAYLOAD'
case IdentityImage_SourceType.ENS_AVATAR: case IdentityImage_SourceType.ENS_AVATAR:
return "ENS_AVATAR"; return 'ENS_AVATAR'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
const baseChatIdentity: object = { const baseChatIdentity: object = {
clock: 0, clock: 0,
ensName: "", ensName: '',
displayName: "", displayName: '',
description: "", description: '',
color: "", color: '',
emoji: "", emoji: '',
}; }
export const ChatIdentity = { export const ChatIdentity = {
encode( encode(
@ -108,246 +108,244 @@ export const ChatIdentity = {
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.clock !== 0) { if (message.clock !== 0) {
writer.uint32(8).uint64(message.clock); writer.uint32(8).uint64(message.clock)
} }
if (message.ensName !== "") { if (message.ensName !== '') {
writer.uint32(18).string(message.ensName); writer.uint32(18).string(message.ensName)
} }
Object.entries(message.images).forEach(([key, value]) => { Object.entries(message.images).forEach(([key, value]) => {
ChatIdentity_ImagesEntry.encode( ChatIdentity_ImagesEntry.encode(
{ key: key as any, value }, { key: key as any, value },
writer.uint32(26).fork() writer.uint32(26).fork()
).ldelim(); ).ldelim()
}); })
if (message.displayName !== "") { if (message.displayName !== '') {
writer.uint32(34).string(message.displayName); writer.uint32(34).string(message.displayName)
} }
if (message.description !== "") { if (message.description !== '') {
writer.uint32(42).string(message.description); writer.uint32(42).string(message.description)
} }
if (message.color !== "") { if (message.color !== '') {
writer.uint32(50).string(message.color); writer.uint32(50).string(message.color)
} }
if (message.emoji !== "") { if (message.emoji !== '') {
writer.uint32(58).string(message.emoji); writer.uint32(58).string(message.emoji)
} }
return writer; return writer
}, },
decode(input: _m0.Reader | Uint8Array, length?: number): ChatIdentity { decode(input: _m0.Reader | Uint8Array, length?: number): ChatIdentity {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { ...baseChatIdentity } as ChatIdentity; const message = { ...baseChatIdentity } as ChatIdentity
message.images = {}; message.images = {}
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.clock = longToNumber(reader.uint64() as Long); message.clock = longToNumber(reader.uint64() as Long)
break; break
case 2: case 2:
message.ensName = reader.string(); message.ensName = reader.string()
break; break
case 3: case 3:
const entry3 = ChatIdentity_ImagesEntry.decode( const entry3 = ChatIdentity_ImagesEntry.decode(
reader, reader,
reader.uint32() reader.uint32()
); )
if (entry3.value !== undefined) { if (entry3.value !== undefined) {
message.images[entry3.key] = entry3.value; message.images[entry3.key] = entry3.value
} }
break; break
case 4: case 4:
message.displayName = reader.string(); message.displayName = reader.string()
break; break
case 5: case 5:
message.description = reader.string(); message.description = reader.string()
break; break
case 6: case 6:
message.color = reader.string(); message.color = reader.string()
break; break
case 7: case 7:
message.emoji = reader.string(); message.emoji = reader.string()
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): ChatIdentity { fromJSON(object: any): ChatIdentity {
const message = { ...baseChatIdentity } as ChatIdentity; const message = { ...baseChatIdentity } as ChatIdentity
message.images = {}; message.images = {}
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = Number(object.clock); message.clock = Number(object.clock)
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.ensName !== undefined && object.ensName !== null) { if (object.ensName !== undefined && object.ensName !== null) {
message.ensName = String(object.ensName); message.ensName = String(object.ensName)
} else { } else {
message.ensName = ""; message.ensName = ''
} }
if (object.images !== undefined && object.images !== null) { if (object.images !== undefined && object.images !== null) {
Object.entries(object.images).forEach(([key, value]) => { Object.entries(object.images).forEach(([key, value]) => {
message.images[key] = IdentityImage.fromJSON(value); message.images[key] = IdentityImage.fromJSON(value)
}); })
} }
if (object.displayName !== undefined && object.displayName !== null) { if (object.displayName !== undefined && object.displayName !== null) {
message.displayName = String(object.displayName); message.displayName = String(object.displayName)
} else { } else {
message.displayName = ""; message.displayName = ''
} }
if (object.description !== undefined && object.description !== null) { if (object.description !== undefined && object.description !== null) {
message.description = String(object.description); message.description = String(object.description)
} else { } else {
message.description = ""; message.description = ''
} }
if (object.color !== undefined && object.color !== null) { if (object.color !== undefined && object.color !== null) {
message.color = String(object.color); message.color = String(object.color)
} else { } else {
message.color = ""; message.color = ''
} }
if (object.emoji !== undefined && object.emoji !== null) { if (object.emoji !== undefined && object.emoji !== null) {
message.emoji = String(object.emoji); message.emoji = String(object.emoji)
} else { } else {
message.emoji = ""; message.emoji = ''
} }
return message; return message
}, },
toJSON(message: ChatIdentity): unknown { toJSON(message: ChatIdentity): unknown {
const obj: any = {}; const obj: any = {}
message.clock !== undefined && (obj.clock = message.clock); message.clock !== undefined && (obj.clock = message.clock)
message.ensName !== undefined && (obj.ensName = message.ensName); message.ensName !== undefined && (obj.ensName = message.ensName)
obj.images = {}; obj.images = {}
if (message.images) { if (message.images) {
Object.entries(message.images).forEach(([k, v]) => { Object.entries(message.images).forEach(([k, v]) => {
obj.images[k] = IdentityImage.toJSON(v); obj.images[k] = IdentityImage.toJSON(v)
}); })
} }
message.displayName !== undefined && message.displayName !== undefined && (obj.displayName = message.displayName)
(obj.displayName = message.displayName); message.description !== undefined && (obj.description = message.description)
message.description !== undefined && message.color !== undefined && (obj.color = message.color)
(obj.description = message.description); message.emoji !== undefined && (obj.emoji = message.emoji)
message.color !== undefined && (obj.color = message.color); return obj
message.emoji !== undefined && (obj.emoji = message.emoji);
return obj;
}, },
fromPartial(object: DeepPartial<ChatIdentity>): ChatIdentity { fromPartial(object: DeepPartial<ChatIdentity>): ChatIdentity {
const message = { ...baseChatIdentity } as ChatIdentity; const message = { ...baseChatIdentity } as ChatIdentity
message.images = {}; message.images = {}
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = object.clock; message.clock = object.clock
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.ensName !== undefined && object.ensName !== null) { if (object.ensName !== undefined && object.ensName !== null) {
message.ensName = object.ensName; message.ensName = object.ensName
} else { } else {
message.ensName = ""; message.ensName = ''
} }
if (object.images !== undefined && object.images !== null) { if (object.images !== undefined && object.images !== null) {
Object.entries(object.images).forEach(([key, value]) => { Object.entries(object.images).forEach(([key, value]) => {
if (value !== undefined) { if (value !== undefined) {
message.images[key] = IdentityImage.fromPartial(value); message.images[key] = IdentityImage.fromPartial(value)
} }
}); })
} }
if (object.displayName !== undefined && object.displayName !== null) { if (object.displayName !== undefined && object.displayName !== null) {
message.displayName = object.displayName; message.displayName = object.displayName
} else { } else {
message.displayName = ""; message.displayName = ''
} }
if (object.description !== undefined && object.description !== null) { if (object.description !== undefined && object.description !== null) {
message.description = object.description; message.description = object.description
} else { } else {
message.description = ""; message.description = ''
} }
if (object.color !== undefined && object.color !== null) { if (object.color !== undefined && object.color !== null) {
message.color = object.color; message.color = object.color
} else { } else {
message.color = ""; message.color = ''
} }
if (object.emoji !== undefined && object.emoji !== null) { if (object.emoji !== undefined && object.emoji !== null) {
message.emoji = object.emoji; message.emoji = object.emoji
} else { } else {
message.emoji = ""; message.emoji = ''
} }
return message; return message
}, },
}; }
const baseChatIdentity_ImagesEntry: object = { key: "" }; const baseChatIdentity_ImagesEntry: object = { key: '' }
export const ChatIdentity_ImagesEntry = { export const ChatIdentity_ImagesEntry = {
encode( encode(
message: ChatIdentity_ImagesEntry, message: ChatIdentity_ImagesEntry,
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.key !== "") { if (message.key !== '') {
writer.uint32(10).string(message.key); writer.uint32(10).string(message.key)
} }
if (message.value !== undefined) { if (message.value !== undefined) {
IdentityImage.encode(message.value, writer.uint32(18).fork()).ldelim(); IdentityImage.encode(message.value, writer.uint32(18).fork()).ldelim()
} }
return writer; return writer
}, },
decode( decode(
input: _m0.Reader | Uint8Array, input: _m0.Reader | Uint8Array,
length?: number length?: number
): ChatIdentity_ImagesEntry { ): ChatIdentity_ImagesEntry {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { const message = {
...baseChatIdentity_ImagesEntry, ...baseChatIdentity_ImagesEntry,
} as ChatIdentity_ImagesEntry; } as ChatIdentity_ImagesEntry
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.key = reader.string(); message.key = reader.string()
break; break
case 2: case 2:
message.value = IdentityImage.decode(reader, reader.uint32()); message.value = IdentityImage.decode(reader, reader.uint32())
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): ChatIdentity_ImagesEntry { fromJSON(object: any): ChatIdentity_ImagesEntry {
const message = { const message = {
...baseChatIdentity_ImagesEntry, ...baseChatIdentity_ImagesEntry,
} as ChatIdentity_ImagesEntry; } as ChatIdentity_ImagesEntry
if (object.key !== undefined && object.key !== null) { if (object.key !== undefined && object.key !== null) {
message.key = String(object.key); message.key = String(object.key)
} else { } else {
message.key = ""; message.key = ''
} }
if (object.value !== undefined && object.value !== null) { if (object.value !== undefined && object.value !== null) {
message.value = IdentityImage.fromJSON(object.value); message.value = IdentityImage.fromJSON(object.value)
} else { } else {
message.value = undefined; message.value = undefined
} }
return message; return message
}, },
toJSON(message: ChatIdentity_ImagesEntry): unknown { toJSON(message: ChatIdentity_ImagesEntry): unknown {
const obj: any = {}; const obj: any = {}
message.key !== undefined && (obj.key = message.key); message.key !== undefined && (obj.key = message.key)
message.value !== undefined && message.value !== undefined &&
(obj.value = message.value (obj.value = message.value
? IdentityImage.toJSON(message.value) ? IdentityImage.toJSON(message.value)
: undefined); : undefined)
return obj; return obj
}, },
fromPartial( fromPartial(
@ -355,22 +353,22 @@ export const ChatIdentity_ImagesEntry = {
): ChatIdentity_ImagesEntry { ): ChatIdentity_ImagesEntry {
const message = { const message = {
...baseChatIdentity_ImagesEntry, ...baseChatIdentity_ImagesEntry,
} as ChatIdentity_ImagesEntry; } as ChatIdentity_ImagesEntry
if (object.key !== undefined && object.key !== null) { if (object.key !== undefined && object.key !== null) {
message.key = object.key; message.key = object.key
} else { } else {
message.key = ""; message.key = ''
} }
if (object.value !== undefined && object.value !== null) { if (object.value !== undefined && object.value !== null) {
message.value = IdentityImage.fromPartial(object.value); message.value = IdentityImage.fromPartial(object.value)
} else { } else {
message.value = undefined; message.value = undefined
} }
return message; return message
}, },
}; }
const baseIdentityImage: object = { sourceType: 0, imageType: 0 }; const baseIdentityImage: object = { sourceType: 0, imageType: 0 }
export const IdentityImage = { export const IdentityImage = {
encode( encode(
@ -378,127 +376,127 @@ export const IdentityImage = {
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.payload.length !== 0) { if (message.payload.length !== 0) {
writer.uint32(10).bytes(message.payload); writer.uint32(10).bytes(message.payload)
} }
if (message.sourceType !== 0) { if (message.sourceType !== 0) {
writer.uint32(16).int32(message.sourceType); writer.uint32(16).int32(message.sourceType)
} }
if (message.imageType !== 0) { if (message.imageType !== 0) {
writer.uint32(24).int32(message.imageType); writer.uint32(24).int32(message.imageType)
} }
return writer; return writer
}, },
decode(input: _m0.Reader | Uint8Array, length?: number): IdentityImage { decode(input: _m0.Reader | Uint8Array, length?: number): IdentityImage {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { ...baseIdentityImage } as IdentityImage; const message = { ...baseIdentityImage } as IdentityImage
message.payload = new Uint8Array(); message.payload = new Uint8Array()
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.payload = reader.bytes(); message.payload = reader.bytes()
break; break
case 2: case 2:
message.sourceType = reader.int32() as any; message.sourceType = reader.int32() as any
break; break
case 3: case 3:
message.imageType = reader.int32() as any; message.imageType = reader.int32() as any
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): IdentityImage { fromJSON(object: any): IdentityImage {
const message = { ...baseIdentityImage } as IdentityImage; const message = { ...baseIdentityImage } as IdentityImage
message.payload = new Uint8Array(); message.payload = new Uint8Array()
if (object.payload !== undefined && object.payload !== null) { if (object.payload !== undefined && object.payload !== null) {
message.payload = bytesFromBase64(object.payload); message.payload = bytesFromBase64(object.payload)
} }
if (object.sourceType !== undefined && object.sourceType !== null) { if (object.sourceType !== undefined && object.sourceType !== null) {
message.sourceType = identityImage_SourceTypeFromJSON(object.sourceType); message.sourceType = identityImage_SourceTypeFromJSON(object.sourceType)
} else { } else {
message.sourceType = 0; message.sourceType = 0
} }
if (object.imageType !== undefined && object.imageType !== null) { if (object.imageType !== undefined && object.imageType !== null) {
message.imageType = imageTypeFromJSON(object.imageType); message.imageType = imageTypeFromJSON(object.imageType)
} else { } else {
message.imageType = 0; message.imageType = 0
} }
return message; return message
}, },
toJSON(message: IdentityImage): unknown { toJSON(message: IdentityImage): unknown {
const obj: any = {}; const obj: any = {}
message.payload !== undefined && message.payload !== undefined &&
(obj.payload = base64FromBytes( (obj.payload = base64FromBytes(
message.payload !== undefined ? message.payload : new Uint8Array() message.payload !== undefined ? message.payload : new Uint8Array()
)); ))
message.sourceType !== undefined && message.sourceType !== undefined &&
(obj.sourceType = identityImage_SourceTypeToJSON(message.sourceType)); (obj.sourceType = identityImage_SourceTypeToJSON(message.sourceType))
message.imageType !== undefined && message.imageType !== undefined &&
(obj.imageType = imageTypeToJSON(message.imageType)); (obj.imageType = imageTypeToJSON(message.imageType))
return obj; return obj
}, },
fromPartial(object: DeepPartial<IdentityImage>): IdentityImage { fromPartial(object: DeepPartial<IdentityImage>): IdentityImage {
const message = { ...baseIdentityImage } as IdentityImage; const message = { ...baseIdentityImage } as IdentityImage
if (object.payload !== undefined && object.payload !== null) { if (object.payload !== undefined && object.payload !== null) {
message.payload = object.payload; message.payload = object.payload
} else { } else {
message.payload = new Uint8Array(); message.payload = new Uint8Array()
} }
if (object.sourceType !== undefined && object.sourceType !== null) { if (object.sourceType !== undefined && object.sourceType !== null) {
message.sourceType = object.sourceType; message.sourceType = object.sourceType
} else { } else {
message.sourceType = 0; message.sourceType = 0
} }
if (object.imageType !== undefined && object.imageType !== null) { if (object.imageType !== undefined && object.imageType !== null) {
message.imageType = object.imageType; message.imageType = object.imageType
} else { } else {
message.imageType = 0; message.imageType = 0
} }
return message; return message
}, },
}; }
declare var self: any | undefined; declare var self: any | undefined
declare var window: any | undefined; declare var window: any | undefined
declare var global: any | undefined; declare var global: any | undefined
var globalThis: any = (() => { var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis; if (typeof globalThis !== 'undefined') return globalThis
if (typeof self !== "undefined") return self; if (typeof self !== 'undefined') return self
if (typeof window !== "undefined") return window; if (typeof window !== 'undefined') return window
if (typeof global !== "undefined") return global; if (typeof global !== 'undefined') return global
throw "Unable to locate global object"; throw 'Unable to locate global object'
})(); })()
const atob: (b64: string) => string = const atob: (b64: string) => string =
globalThis.atob || globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary")); (b64 => globalThis.Buffer.from(b64, 'base64').toString('binary'))
function bytesFromBase64(b64: string): Uint8Array { function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64); const bin = atob(b64)
const arr = new Uint8Array(bin.length); const arr = new Uint8Array(bin.length)
for (let i = 0; i < bin.length; ++i) { for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i); arr[i] = bin.charCodeAt(i)
} }
return arr; return arr
} }
const btoa: (bin: string) => string = const btoa: (bin: string) => string =
globalThis.btoa || globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64")); (bin => globalThis.Buffer.from(bin, 'binary').toString('base64'))
function base64FromBytes(arr: Uint8Array): string { function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = []; const bin: string[] = []
for (const byte of arr) { for (const byte of arr) {
bin.push(String.fromCharCode(byte)); bin.push(String.fromCharCode(byte))
} }
return btoa(bin.join("")); return btoa(bin.join(''))
} }
type Builtin = type Builtin =
@ -508,7 +506,7 @@ type Builtin =
| string | string
| number | number
| boolean | boolean
| undefined; | undefined
export type DeepPartial<T> = T extends Builtin export type DeepPartial<T> = T extends Builtin
? T ? T
: T extends Array<infer U> : T extends Array<infer U>
@ -517,16 +515,16 @@ export type DeepPartial<T> = T extends Builtin
? ReadonlyArray<DeepPartial<U>> ? ReadonlyArray<DeepPartial<U>>
: T extends {} : T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> } ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>; : Partial<T>
function longToNumber(long: Long): number { function longToNumber(long: Long): number {
if (long.gt(Number.MAX_SAFE_INTEGER)) { if (long.gt(Number.MAX_SAFE_INTEGER)) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); throw new globalThis.Error('Value is larger than Number.MAX_SAFE_INTEGER')
} }
return long.toNumber(); return long.toNumber()
} }
if (_m0.util.Long !== Long) { if (_m0.util.Long !== Long) {
_m0.util.Long = Long as any; _m0.util.Long = Long as any
_m0.configure(); _m0.configure()
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,32 @@
/* eslint-disable */ /* eslint-disable */
import Long from "long"; import Long from 'long'
import _m0 from "protobufjs/minimal"; import _m0 from 'protobufjs/minimal'
import { import {
MessageType, MessageType,
messageTypeFromJSON, messageTypeFromJSON,
messageTypeToJSON, messageTypeToJSON,
} from "../../communities/v1/enums"; } from '../../communities/v1/enums'
export const protobufPackage = "communities.v1"; export const protobufPackage = 'communities.v1'
export interface EmojiReaction { export interface EmojiReaction {
/** clock Lamport timestamp of the chat message */ /** clock Lamport timestamp of the chat message */
clock: number; clock: number
/** /**
* chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the * chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the
* target message also stores the chat_id * target message also stores the chat_id
*/ */
chatId: string; chatId: string
/** message_id the ID of the target message that the user wishes to react to */ /** message_id the ID of the target message that the user wishes to react to */
messageId: string; messageId: string
/** message_type is (somewhat confusingly) the ID of the type of chat the message belongs to */ /** message_type is (somewhat confusingly) the ID of the type of chat the message belongs to */
messageType: MessageType; messageType: MessageType
/** type the ID of the emoji the user wishes to react with */ /** type the ID of the emoji the user wishes to react with */
type: EmojiReaction_Type; type: EmojiReaction_Type
/** whether this is a rectraction of a previously sent emoji */ /** whether this is a rectraction of a previously sent emoji */
retracted: boolean; retracted: boolean
/** Grant for organisation chat messages */ /** Grant for organisation chat messages */
grant: Uint8Array; grant: Uint8Array
} }
export enum EmojiReaction_Type { export enum EmojiReaction_Type {
@ -43,62 +43,62 @@ export enum EmojiReaction_Type {
export function emojiReaction_TypeFromJSON(object: any): EmojiReaction_Type { export function emojiReaction_TypeFromJSON(object: any): EmojiReaction_Type {
switch (object) { switch (object) {
case 0: case 0:
case "UNKNOWN_EMOJI_REACTION_TYPE": case 'UNKNOWN_EMOJI_REACTION_TYPE':
return EmojiReaction_Type.UNKNOWN_EMOJI_REACTION_TYPE; return EmojiReaction_Type.UNKNOWN_EMOJI_REACTION_TYPE
case 1: case 1:
case "LOVE": case 'LOVE':
return EmojiReaction_Type.LOVE; return EmojiReaction_Type.LOVE
case 2: case 2:
case "THUMBS_UP": case 'THUMBS_UP':
return EmojiReaction_Type.THUMBS_UP; return EmojiReaction_Type.THUMBS_UP
case 3: case 3:
case "THUMBS_DOWN": case 'THUMBS_DOWN':
return EmojiReaction_Type.THUMBS_DOWN; return EmojiReaction_Type.THUMBS_DOWN
case 4: case 4:
case "LAUGH": case 'LAUGH':
return EmojiReaction_Type.LAUGH; return EmojiReaction_Type.LAUGH
case 5: case 5:
case "SAD": case 'SAD':
return EmojiReaction_Type.SAD; return EmojiReaction_Type.SAD
case 6: case 6:
case "ANGRY": case 'ANGRY':
return EmojiReaction_Type.ANGRY; return EmojiReaction_Type.ANGRY
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return EmojiReaction_Type.UNRECOGNIZED; return EmojiReaction_Type.UNRECOGNIZED
} }
} }
export function emojiReaction_TypeToJSON(object: EmojiReaction_Type): string { export function emojiReaction_TypeToJSON(object: EmojiReaction_Type): string {
switch (object) { switch (object) {
case EmojiReaction_Type.UNKNOWN_EMOJI_REACTION_TYPE: case EmojiReaction_Type.UNKNOWN_EMOJI_REACTION_TYPE:
return "UNKNOWN_EMOJI_REACTION_TYPE"; return 'UNKNOWN_EMOJI_REACTION_TYPE'
case EmojiReaction_Type.LOVE: case EmojiReaction_Type.LOVE:
return "LOVE"; return 'LOVE'
case EmojiReaction_Type.THUMBS_UP: case EmojiReaction_Type.THUMBS_UP:
return "THUMBS_UP"; return 'THUMBS_UP'
case EmojiReaction_Type.THUMBS_DOWN: case EmojiReaction_Type.THUMBS_DOWN:
return "THUMBS_DOWN"; return 'THUMBS_DOWN'
case EmojiReaction_Type.LAUGH: case EmojiReaction_Type.LAUGH:
return "LAUGH"; return 'LAUGH'
case EmojiReaction_Type.SAD: case EmojiReaction_Type.SAD:
return "SAD"; return 'SAD'
case EmojiReaction_Type.ANGRY: case EmojiReaction_Type.ANGRY:
return "ANGRY"; return 'ANGRY'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
const baseEmojiReaction: object = { const baseEmojiReaction: object = {
clock: 0, clock: 0,
chatId: "", chatId: '',
messageId: "", messageId: '',
messageType: 0, messageType: 0,
type: 0, type: 0,
retracted: false, retracted: false,
}; }
export const EmojiReaction = { export const EmojiReaction = {
encode( encode(
@ -106,195 +106,195 @@ export const EmojiReaction = {
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.clock !== 0) { if (message.clock !== 0) {
writer.uint32(8).uint64(message.clock); writer.uint32(8).uint64(message.clock)
} }
if (message.chatId !== "") { if (message.chatId !== '') {
writer.uint32(18).string(message.chatId); writer.uint32(18).string(message.chatId)
} }
if (message.messageId !== "") { if (message.messageId !== '') {
writer.uint32(26).string(message.messageId); writer.uint32(26).string(message.messageId)
} }
if (message.messageType !== 0) { if (message.messageType !== 0) {
writer.uint32(32).int32(message.messageType); writer.uint32(32).int32(message.messageType)
} }
if (message.type !== 0) { if (message.type !== 0) {
writer.uint32(40).int32(message.type); writer.uint32(40).int32(message.type)
} }
if (message.retracted === true) { if (message.retracted === true) {
writer.uint32(48).bool(message.retracted); writer.uint32(48).bool(message.retracted)
} }
if (message.grant.length !== 0) { if (message.grant.length !== 0) {
writer.uint32(58).bytes(message.grant); writer.uint32(58).bytes(message.grant)
} }
return writer; return writer
}, },
decode(input: _m0.Reader | Uint8Array, length?: number): EmojiReaction { decode(input: _m0.Reader | Uint8Array, length?: number): EmojiReaction {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { ...baseEmojiReaction } as EmojiReaction; const message = { ...baseEmojiReaction } as EmojiReaction
message.grant = new Uint8Array(); message.grant = new Uint8Array()
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.clock = longToNumber(reader.uint64() as Long); message.clock = longToNumber(reader.uint64() as Long)
break; break
case 2: case 2:
message.chatId = reader.string(); message.chatId = reader.string()
break; break
case 3: case 3:
message.messageId = reader.string(); message.messageId = reader.string()
break; break
case 4: case 4:
message.messageType = reader.int32() as any; message.messageType = reader.int32() as any
break; break
case 5: case 5:
message.type = reader.int32() as any; message.type = reader.int32() as any
break; break
case 6: case 6:
message.retracted = reader.bool(); message.retracted = reader.bool()
break; break
case 7: case 7:
message.grant = reader.bytes(); message.grant = reader.bytes()
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): EmojiReaction { fromJSON(object: any): EmojiReaction {
const message = { ...baseEmojiReaction } as EmojiReaction; const message = { ...baseEmojiReaction } as EmojiReaction
message.grant = new Uint8Array(); message.grant = new Uint8Array()
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = Number(object.clock); message.clock = Number(object.clock)
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.chatId !== undefined && object.chatId !== null) { if (object.chatId !== undefined && object.chatId !== null) {
message.chatId = String(object.chatId); message.chatId = String(object.chatId)
} else { } else {
message.chatId = ""; message.chatId = ''
} }
if (object.messageId !== undefined && object.messageId !== null) { if (object.messageId !== undefined && object.messageId !== null) {
message.messageId = String(object.messageId); message.messageId = String(object.messageId)
} else { } else {
message.messageId = ""; message.messageId = ''
} }
if (object.messageType !== undefined && object.messageType !== null) { if (object.messageType !== undefined && object.messageType !== null) {
message.messageType = messageTypeFromJSON(object.messageType); message.messageType = messageTypeFromJSON(object.messageType)
} else { } else {
message.messageType = 0; message.messageType = 0
} }
if (object.type !== undefined && object.type !== null) { if (object.type !== undefined && object.type !== null) {
message.type = emojiReaction_TypeFromJSON(object.type); message.type = emojiReaction_TypeFromJSON(object.type)
} else { } else {
message.type = 0; message.type = 0
} }
if (object.retracted !== undefined && object.retracted !== null) { if (object.retracted !== undefined && object.retracted !== null) {
message.retracted = Boolean(object.retracted); message.retracted = Boolean(object.retracted)
} else { } else {
message.retracted = false; message.retracted = false
} }
if (object.grant !== undefined && object.grant !== null) { if (object.grant !== undefined && object.grant !== null) {
message.grant = bytesFromBase64(object.grant); message.grant = bytesFromBase64(object.grant)
} }
return message; return message
}, },
toJSON(message: EmojiReaction): unknown { toJSON(message: EmojiReaction): unknown {
const obj: any = {}; const obj: any = {}
message.clock !== undefined && (obj.clock = message.clock); message.clock !== undefined && (obj.clock = message.clock)
message.chatId !== undefined && (obj.chatId = message.chatId); message.chatId !== undefined && (obj.chatId = message.chatId)
message.messageId !== undefined && (obj.messageId = message.messageId); message.messageId !== undefined && (obj.messageId = message.messageId)
message.messageType !== undefined && message.messageType !== undefined &&
(obj.messageType = messageTypeToJSON(message.messageType)); (obj.messageType = messageTypeToJSON(message.messageType))
message.type !== undefined && message.type !== undefined &&
(obj.type = emojiReaction_TypeToJSON(message.type)); (obj.type = emojiReaction_TypeToJSON(message.type))
message.retracted !== undefined && (obj.retracted = message.retracted); message.retracted !== undefined && (obj.retracted = message.retracted)
message.grant !== undefined && message.grant !== undefined &&
(obj.grant = base64FromBytes( (obj.grant = base64FromBytes(
message.grant !== undefined ? message.grant : new Uint8Array() message.grant !== undefined ? message.grant : new Uint8Array()
)); ))
return obj; return obj
}, },
fromPartial(object: DeepPartial<EmojiReaction>): EmojiReaction { fromPartial(object: DeepPartial<EmojiReaction>): EmojiReaction {
const message = { ...baseEmojiReaction } as EmojiReaction; const message = { ...baseEmojiReaction } as EmojiReaction
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = object.clock; message.clock = object.clock
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.chatId !== undefined && object.chatId !== null) { if (object.chatId !== undefined && object.chatId !== null) {
message.chatId = object.chatId; message.chatId = object.chatId
} else { } else {
message.chatId = ""; message.chatId = ''
} }
if (object.messageId !== undefined && object.messageId !== null) { if (object.messageId !== undefined && object.messageId !== null) {
message.messageId = object.messageId; message.messageId = object.messageId
} else { } else {
message.messageId = ""; message.messageId = ''
} }
if (object.messageType !== undefined && object.messageType !== null) { if (object.messageType !== undefined && object.messageType !== null) {
message.messageType = object.messageType; message.messageType = object.messageType
} else { } else {
message.messageType = 0; message.messageType = 0
} }
if (object.type !== undefined && object.type !== null) { if (object.type !== undefined && object.type !== null) {
message.type = object.type; message.type = object.type
} else { } else {
message.type = 0; message.type = 0
} }
if (object.retracted !== undefined && object.retracted !== null) { if (object.retracted !== undefined && object.retracted !== null) {
message.retracted = object.retracted; message.retracted = object.retracted
} else { } else {
message.retracted = false; message.retracted = false
} }
if (object.grant !== undefined && object.grant !== null) { if (object.grant !== undefined && object.grant !== null) {
message.grant = object.grant; message.grant = object.grant
} else { } else {
message.grant = new Uint8Array(); message.grant = new Uint8Array()
} }
return message; return message
}, },
}; }
declare var self: any | undefined; declare var self: any | undefined
declare var window: any | undefined; declare var window: any | undefined
declare var global: any | undefined; declare var global: any | undefined
var globalThis: any = (() => { var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis; if (typeof globalThis !== 'undefined') return globalThis
if (typeof self !== "undefined") return self; if (typeof self !== 'undefined') return self
if (typeof window !== "undefined") return window; if (typeof window !== 'undefined') return window
if (typeof global !== "undefined") return global; if (typeof global !== 'undefined') return global
throw "Unable to locate global object"; throw 'Unable to locate global object'
})(); })()
const atob: (b64: string) => string = const atob: (b64: string) => string =
globalThis.atob || globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary")); (b64 => globalThis.Buffer.from(b64, 'base64').toString('binary'))
function bytesFromBase64(b64: string): Uint8Array { function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64); const bin = atob(b64)
const arr = new Uint8Array(bin.length); const arr = new Uint8Array(bin.length)
for (let i = 0; i < bin.length; ++i) { for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i); arr[i] = bin.charCodeAt(i)
} }
return arr; return arr
} }
const btoa: (bin: string) => string = const btoa: (bin: string) => string =
globalThis.btoa || globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64")); (bin => globalThis.Buffer.from(bin, 'binary').toString('base64'))
function base64FromBytes(arr: Uint8Array): string { function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = []; const bin: string[] = []
for (const byte of arr) { for (const byte of arr) {
bin.push(String.fromCharCode(byte)); bin.push(String.fromCharCode(byte))
} }
return btoa(bin.join("")); return btoa(bin.join(''))
} }
type Builtin = type Builtin =
@ -304,7 +304,7 @@ type Builtin =
| string | string
| number | number
| boolean | boolean
| undefined; | undefined
export type DeepPartial<T> = T extends Builtin export type DeepPartial<T> = T extends Builtin
? T ? T
: T extends Array<infer U> : T extends Array<infer U>
@ -313,16 +313,16 @@ export type DeepPartial<T> = T extends Builtin
? ReadonlyArray<DeepPartial<U>> ? ReadonlyArray<DeepPartial<U>>
: T extends {} : T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> } ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>; : Partial<T>
function longToNumber(long: Long): number { function longToNumber(long: Long): number {
if (long.gt(Number.MAX_SAFE_INTEGER)) { if (long.gt(Number.MAX_SAFE_INTEGER)) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); throw new globalThis.Error('Value is larger than Number.MAX_SAFE_INTEGER')
} }
return long.toNumber(); return long.toNumber()
} }
if (_m0.util.Long !== Long) { if (_m0.util.Long !== Long) {
_m0.util.Long = Long as any; _m0.util.Long = Long as any
_m0.configure(); _m0.configure()
} }

View File

@ -1,8 +1,8 @@
/* eslint-disable */ /* eslint-disable */
import Long from "long"; import Long from 'long'
import _m0 from "protobufjs/minimal"; import _m0 from 'protobufjs/minimal'
export const protobufPackage = "communities.v1"; export const protobufPackage = 'communities.v1'
export enum MessageType { export enum MessageType {
MESSAGE_TYPE_UNKNOWN_UNSPECIFIED = 0, MESSAGE_TYPE_UNKNOWN_UNSPECIFIED = 0,
@ -20,51 +20,51 @@ export enum MessageType {
export function messageTypeFromJSON(object: any): MessageType { export function messageTypeFromJSON(object: any): MessageType {
switch (object) { switch (object) {
case 0: case 0:
case "MESSAGE_TYPE_UNKNOWN_UNSPECIFIED": case 'MESSAGE_TYPE_UNKNOWN_UNSPECIFIED':
return MessageType.MESSAGE_TYPE_UNKNOWN_UNSPECIFIED; return MessageType.MESSAGE_TYPE_UNKNOWN_UNSPECIFIED
case 1: case 1:
case "MESSAGE_TYPE_ONE_TO_ONE": case 'MESSAGE_TYPE_ONE_TO_ONE':
return MessageType.MESSAGE_TYPE_ONE_TO_ONE; return MessageType.MESSAGE_TYPE_ONE_TO_ONE
case 2: case 2:
case "MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP": case 'MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP':
return MessageType.MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP; return MessageType.MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP
case 3: case 3:
case "MESSAGE_TYPE_PRIVATE_GROUP": case 'MESSAGE_TYPE_PRIVATE_GROUP':
return MessageType.MESSAGE_TYPE_PRIVATE_GROUP; return MessageType.MESSAGE_TYPE_PRIVATE_GROUP
case 4: case 4:
case "MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP": case 'MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP':
return MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP; return MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP
case 5: case 5:
case "MESSAGE_TYPE_COMMUNITY_CHAT": case 'MESSAGE_TYPE_COMMUNITY_CHAT':
return MessageType.MESSAGE_TYPE_COMMUNITY_CHAT; return MessageType.MESSAGE_TYPE_COMMUNITY_CHAT
case 6: case 6:
case "MESSAGE_TYPE_SYSTEM_MESSAGE_GAP": case 'MESSAGE_TYPE_SYSTEM_MESSAGE_GAP':
return MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_GAP; return MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_GAP
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return MessageType.UNRECOGNIZED; return MessageType.UNRECOGNIZED
} }
} }
export function messageTypeToJSON(object: MessageType): string { export function messageTypeToJSON(object: MessageType): string {
switch (object) { switch (object) {
case MessageType.MESSAGE_TYPE_UNKNOWN_UNSPECIFIED: case MessageType.MESSAGE_TYPE_UNKNOWN_UNSPECIFIED:
return "MESSAGE_TYPE_UNKNOWN_UNSPECIFIED"; return 'MESSAGE_TYPE_UNKNOWN_UNSPECIFIED'
case MessageType.MESSAGE_TYPE_ONE_TO_ONE: case MessageType.MESSAGE_TYPE_ONE_TO_ONE:
return "MESSAGE_TYPE_ONE_TO_ONE"; return 'MESSAGE_TYPE_ONE_TO_ONE'
case MessageType.MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP: case MessageType.MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP:
return "MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP"; return 'MESSAGE_TYPE_MESSAGE_TYPE_PUBLIC_GROUP'
case MessageType.MESSAGE_TYPE_PRIVATE_GROUP: case MessageType.MESSAGE_TYPE_PRIVATE_GROUP:
return "MESSAGE_TYPE_PRIVATE_GROUP"; return 'MESSAGE_TYPE_PRIVATE_GROUP'
case MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP: case MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP:
return "MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP"; return 'MESSAGE_TYPE_SYSTEM_MESSAGE_PRIVATE_GROUP'
case MessageType.MESSAGE_TYPE_COMMUNITY_CHAT: case MessageType.MESSAGE_TYPE_COMMUNITY_CHAT:
return "MESSAGE_TYPE_COMMUNITY_CHAT"; return 'MESSAGE_TYPE_COMMUNITY_CHAT'
case MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_GAP: case MessageType.MESSAGE_TYPE_SYSTEM_MESSAGE_GAP:
return "MESSAGE_TYPE_SYSTEM_MESSAGE_GAP"; return 'MESSAGE_TYPE_SYSTEM_MESSAGE_GAP'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
@ -81,45 +81,45 @@ export enum ImageType {
export function imageTypeFromJSON(object: any): ImageType { export function imageTypeFromJSON(object: any): ImageType {
switch (object) { switch (object) {
case 0: case 0:
case "IMAGE_TYPE_UNKNOWN_UNSPECIFIED": case 'IMAGE_TYPE_UNKNOWN_UNSPECIFIED':
return ImageType.IMAGE_TYPE_UNKNOWN_UNSPECIFIED; return ImageType.IMAGE_TYPE_UNKNOWN_UNSPECIFIED
case 1: case 1:
case "IMAGE_TYPE_PNG": case 'IMAGE_TYPE_PNG':
return ImageType.IMAGE_TYPE_PNG; return ImageType.IMAGE_TYPE_PNG
case 2: case 2:
case "IMAGE_TYPE_JPEG": case 'IMAGE_TYPE_JPEG':
return ImageType.IMAGE_TYPE_JPEG; return ImageType.IMAGE_TYPE_JPEG
case 3: case 3:
case "IMAGE_TYPE_WEBP": case 'IMAGE_TYPE_WEBP':
return ImageType.IMAGE_TYPE_WEBP; return ImageType.IMAGE_TYPE_WEBP
case 4: case 4:
case "IMAGE_TYPE_GIF": case 'IMAGE_TYPE_GIF':
return ImageType.IMAGE_TYPE_GIF; return ImageType.IMAGE_TYPE_GIF
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return ImageType.UNRECOGNIZED; return ImageType.UNRECOGNIZED
} }
} }
export function imageTypeToJSON(object: ImageType): string { export function imageTypeToJSON(object: ImageType): string {
switch (object) { switch (object) {
case ImageType.IMAGE_TYPE_UNKNOWN_UNSPECIFIED: case ImageType.IMAGE_TYPE_UNKNOWN_UNSPECIFIED:
return "IMAGE_TYPE_UNKNOWN_UNSPECIFIED"; return 'IMAGE_TYPE_UNKNOWN_UNSPECIFIED'
case ImageType.IMAGE_TYPE_PNG: case ImageType.IMAGE_TYPE_PNG:
return "IMAGE_TYPE_PNG"; return 'IMAGE_TYPE_PNG'
case ImageType.IMAGE_TYPE_JPEG: case ImageType.IMAGE_TYPE_JPEG:
return "IMAGE_TYPE_JPEG"; return 'IMAGE_TYPE_JPEG'
case ImageType.IMAGE_TYPE_WEBP: case ImageType.IMAGE_TYPE_WEBP:
return "IMAGE_TYPE_WEBP"; return 'IMAGE_TYPE_WEBP'
case ImageType.IMAGE_TYPE_GIF: case ImageType.IMAGE_TYPE_GIF:
return "IMAGE_TYPE_GIF"; return 'IMAGE_TYPE_GIF'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
if (_m0.util.Long !== Long) { if (_m0.util.Long !== Long) {
_m0.util.Long = Long as any; _m0.util.Long = Long as any
_m0.configure(); _m0.configure()
} }

View File

@ -1,20 +1,20 @@
/* eslint-disable */ /* eslint-disable */
import Long from "long"; import Long from 'long'
import _m0 from "protobufjs/minimal"; import _m0 from 'protobufjs/minimal'
import { ChatMessage } from "../../communities/v1/chat_message"; import { ChatMessage } from '../../communities/v1/chat_message'
import { EmojiReaction } from "../../communities/v1/emoji_reaction"; import { EmojiReaction } from '../../communities/v1/emoji_reaction'
export const protobufPackage = "communities.v1"; export const protobufPackage = 'communities.v1'
export interface MembershipUpdateEvent { export interface MembershipUpdateEvent {
/** Lamport timestamp of the event */ /** Lamport timestamp of the event */
clock: number; clock: number
/** List of public keys of objects of the action */ /** List of public keys of objects of the action */
members: string[]; members: string[]
/** Name of the chat for the CHAT_CREATED/NAME_CHANGED event types */ /** Name of the chat for the CHAT_CREATED/NAME_CHANGED event types */
name: string; name: string
/** The type of the event */ /** The type of the event */
type: MembershipUpdateEvent_EventType; type: MembershipUpdateEvent_EventType
} }
export enum MembershipUpdateEvent_EventType { export enum MembershipUpdateEvent_EventType {
@ -34,33 +34,33 @@ export function membershipUpdateEvent_EventTypeFromJSON(
): MembershipUpdateEvent_EventType { ): MembershipUpdateEvent_EventType {
switch (object) { switch (object) {
case 0: case 0:
case "UNKNOWN": case 'UNKNOWN':
return MembershipUpdateEvent_EventType.UNKNOWN; return MembershipUpdateEvent_EventType.UNKNOWN
case 1: case 1:
case "CHAT_CREATED": case 'CHAT_CREATED':
return MembershipUpdateEvent_EventType.CHAT_CREATED; return MembershipUpdateEvent_EventType.CHAT_CREATED
case 2: case 2:
case "NAME_CHANGED": case 'NAME_CHANGED':
return MembershipUpdateEvent_EventType.NAME_CHANGED; return MembershipUpdateEvent_EventType.NAME_CHANGED
case 3: case 3:
case "MEMBERS_ADDED": case 'MEMBERS_ADDED':
return MembershipUpdateEvent_EventType.MEMBERS_ADDED; return MembershipUpdateEvent_EventType.MEMBERS_ADDED
case 4: case 4:
case "MEMBER_JOINED": case 'MEMBER_JOINED':
return MembershipUpdateEvent_EventType.MEMBER_JOINED; return MembershipUpdateEvent_EventType.MEMBER_JOINED
case 5: case 5:
case "MEMBER_REMOVED": case 'MEMBER_REMOVED':
return MembershipUpdateEvent_EventType.MEMBER_REMOVED; return MembershipUpdateEvent_EventType.MEMBER_REMOVED
case 6: case 6:
case "ADMINS_ADDED": case 'ADMINS_ADDED':
return MembershipUpdateEvent_EventType.ADMINS_ADDED; return MembershipUpdateEvent_EventType.ADMINS_ADDED
case 7: case 7:
case "ADMIN_REMOVED": case 'ADMIN_REMOVED':
return MembershipUpdateEvent_EventType.ADMIN_REMOVED; return MembershipUpdateEvent_EventType.ADMIN_REMOVED
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return MembershipUpdateEvent_EventType.UNRECOGNIZED; return MembershipUpdateEvent_EventType.UNRECOGNIZED
} }
} }
@ -69,23 +69,23 @@ export function membershipUpdateEvent_EventTypeToJSON(
): string { ): string {
switch (object) { switch (object) {
case MembershipUpdateEvent_EventType.UNKNOWN: case MembershipUpdateEvent_EventType.UNKNOWN:
return "UNKNOWN"; return 'UNKNOWN'
case MembershipUpdateEvent_EventType.CHAT_CREATED: case MembershipUpdateEvent_EventType.CHAT_CREATED:
return "CHAT_CREATED"; return 'CHAT_CREATED'
case MembershipUpdateEvent_EventType.NAME_CHANGED: case MembershipUpdateEvent_EventType.NAME_CHANGED:
return "NAME_CHANGED"; return 'NAME_CHANGED'
case MembershipUpdateEvent_EventType.MEMBERS_ADDED: case MembershipUpdateEvent_EventType.MEMBERS_ADDED:
return "MEMBERS_ADDED"; return 'MEMBERS_ADDED'
case MembershipUpdateEvent_EventType.MEMBER_JOINED: case MembershipUpdateEvent_EventType.MEMBER_JOINED:
return "MEMBER_JOINED"; return 'MEMBER_JOINED'
case MembershipUpdateEvent_EventType.MEMBER_REMOVED: case MembershipUpdateEvent_EventType.MEMBER_REMOVED:
return "MEMBER_REMOVED"; return 'MEMBER_REMOVED'
case MembershipUpdateEvent_EventType.ADMINS_ADDED: case MembershipUpdateEvent_EventType.ADMINS_ADDED:
return "ADMINS_ADDED"; return 'ADMINS_ADDED'
case MembershipUpdateEvent_EventType.ADMIN_REMOVED: case MembershipUpdateEvent_EventType.ADMIN_REMOVED:
return "ADMIN_REMOVED"; return 'ADMIN_REMOVED'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
@ -96,22 +96,22 @@ export function membershipUpdateEvent_EventTypeToJSON(
*/ */
export interface MembershipUpdateMessage { export interface MembershipUpdateMessage {
/** The chat id of the private group chat */ /** The chat id of the private group chat */
chatId: string; chatId: string
/** /**
* A list of events for this group chat, first x bytes are the signature, then is a * A list of events for this group chat, first x bytes are the signature, then is a
* protobuf encoded MembershipUpdateEvent * protobuf encoded MembershipUpdateEvent
*/ */
events: Uint8Array[]; events: Uint8Array[]
message: ChatMessage | undefined; message: ChatMessage | undefined
emojiReaction: EmojiReaction | undefined; emojiReaction: EmojiReaction | undefined
} }
const baseMembershipUpdateEvent: object = { const baseMembershipUpdateEvent: object = {
clock: 0, clock: 0,
members: "", members: '',
name: "", name: '',
type: 0, type: 0,
}; }
export const MembershipUpdateEvent = { export const MembershipUpdateEvent = {
encode( encode(
@ -119,225 +119,225 @@ export const MembershipUpdateEvent = {
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.clock !== 0) { if (message.clock !== 0) {
writer.uint32(8).uint64(message.clock); writer.uint32(8).uint64(message.clock)
} }
for (const v of message.members) { for (const v of message.members) {
writer.uint32(18).string(v!); writer.uint32(18).string(v!)
} }
if (message.name !== "") { if (message.name !== '') {
writer.uint32(26).string(message.name); writer.uint32(26).string(message.name)
} }
if (message.type !== 0) { if (message.type !== 0) {
writer.uint32(32).int32(message.type); writer.uint32(32).int32(message.type)
} }
return writer; return writer
}, },
decode( decode(
input: _m0.Reader | Uint8Array, input: _m0.Reader | Uint8Array,
length?: number length?: number
): MembershipUpdateEvent { ): MembershipUpdateEvent {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { ...baseMembershipUpdateEvent } as MembershipUpdateEvent; const message = { ...baseMembershipUpdateEvent } as MembershipUpdateEvent
message.members = []; message.members = []
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.clock = longToNumber(reader.uint64() as Long); message.clock = longToNumber(reader.uint64() as Long)
break; break
case 2: case 2:
message.members.push(reader.string()); message.members.push(reader.string())
break; break
case 3: case 3:
message.name = reader.string(); message.name = reader.string()
break; break
case 4: case 4:
message.type = reader.int32() as any; message.type = reader.int32() as any
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): MembershipUpdateEvent { fromJSON(object: any): MembershipUpdateEvent {
const message = { ...baseMembershipUpdateEvent } as MembershipUpdateEvent; const message = { ...baseMembershipUpdateEvent } as MembershipUpdateEvent
message.members = []; message.members = []
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = Number(object.clock); message.clock = Number(object.clock)
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.members !== undefined && object.members !== null) { if (object.members !== undefined && object.members !== null) {
for (const e of object.members) { for (const e of object.members) {
message.members.push(String(e)); message.members.push(String(e))
} }
} }
if (object.name !== undefined && object.name !== null) { if (object.name !== undefined && object.name !== null) {
message.name = String(object.name); message.name = String(object.name)
} else { } else {
message.name = ""; message.name = ''
} }
if (object.type !== undefined && object.type !== null) { if (object.type !== undefined && object.type !== null) {
message.type = membershipUpdateEvent_EventTypeFromJSON(object.type); message.type = membershipUpdateEvent_EventTypeFromJSON(object.type)
} else { } else {
message.type = 0; message.type = 0
} }
return message; return message
}, },
toJSON(message: MembershipUpdateEvent): unknown { toJSON(message: MembershipUpdateEvent): unknown {
const obj: any = {}; const obj: any = {}
message.clock !== undefined && (obj.clock = message.clock); message.clock !== undefined && (obj.clock = message.clock)
if (message.members) { if (message.members) {
obj.members = message.members.map((e) => e); obj.members = message.members.map(e => e)
} else { } else {
obj.members = []; obj.members = []
} }
message.name !== undefined && (obj.name = message.name); message.name !== undefined && (obj.name = message.name)
message.type !== undefined && message.type !== undefined &&
(obj.type = membershipUpdateEvent_EventTypeToJSON(message.type)); (obj.type = membershipUpdateEvent_EventTypeToJSON(message.type))
return obj; return obj
}, },
fromPartial( fromPartial(
object: DeepPartial<MembershipUpdateEvent> object: DeepPartial<MembershipUpdateEvent>
): MembershipUpdateEvent { ): MembershipUpdateEvent {
const message = { ...baseMembershipUpdateEvent } as MembershipUpdateEvent; const message = { ...baseMembershipUpdateEvent } as MembershipUpdateEvent
message.members = []; message.members = []
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = object.clock; message.clock = object.clock
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.members !== undefined && object.members !== null) { if (object.members !== undefined && object.members !== null) {
for (const e of object.members) { for (const e of object.members) {
message.members.push(e); message.members.push(e)
} }
} }
if (object.name !== undefined && object.name !== null) { if (object.name !== undefined && object.name !== null) {
message.name = object.name; message.name = object.name
} else { } else {
message.name = ""; message.name = ''
} }
if (object.type !== undefined && object.type !== null) { if (object.type !== undefined && object.type !== null) {
message.type = object.type; message.type = object.type
} else { } else {
message.type = 0; message.type = 0
} }
return message; return message
}, },
}; }
const baseMembershipUpdateMessage: object = { chatId: "" }; const baseMembershipUpdateMessage: object = { chatId: '' }
export const MembershipUpdateMessage = { export const MembershipUpdateMessage = {
encode( encode(
message: MembershipUpdateMessage, message: MembershipUpdateMessage,
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.chatId !== "") { if (message.chatId !== '') {
writer.uint32(10).string(message.chatId); writer.uint32(10).string(message.chatId)
} }
for (const v of message.events) { for (const v of message.events) {
writer.uint32(18).bytes(v!); writer.uint32(18).bytes(v!)
} }
if (message.message !== undefined) { if (message.message !== undefined) {
ChatMessage.encode(message.message, writer.uint32(26).fork()).ldelim(); ChatMessage.encode(message.message, writer.uint32(26).fork()).ldelim()
} }
if (message.emojiReaction !== undefined) { if (message.emojiReaction !== undefined) {
EmojiReaction.encode( EmojiReaction.encode(
message.emojiReaction, message.emojiReaction,
writer.uint32(34).fork() writer.uint32(34).fork()
).ldelim(); ).ldelim()
} }
return writer; return writer
}, },
decode( decode(
input: _m0.Reader | Uint8Array, input: _m0.Reader | Uint8Array,
length?: number length?: number
): MembershipUpdateMessage { ): MembershipUpdateMessage {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { const message = {
...baseMembershipUpdateMessage, ...baseMembershipUpdateMessage,
} as MembershipUpdateMessage; } as MembershipUpdateMessage
message.events = []; message.events = []
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.chatId = reader.string(); message.chatId = reader.string()
break; break
case 2: case 2:
message.events.push(reader.bytes()); message.events.push(reader.bytes())
break; break
case 3: case 3:
message.message = ChatMessage.decode(reader, reader.uint32()); message.message = ChatMessage.decode(reader, reader.uint32())
break; break
case 4: case 4:
message.emojiReaction = EmojiReaction.decode(reader, reader.uint32()); message.emojiReaction = EmojiReaction.decode(reader, reader.uint32())
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): MembershipUpdateMessage { fromJSON(object: any): MembershipUpdateMessage {
const message = { const message = {
...baseMembershipUpdateMessage, ...baseMembershipUpdateMessage,
} as MembershipUpdateMessage; } as MembershipUpdateMessage
message.events = []; message.events = []
if (object.chatId !== undefined && object.chatId !== null) { if (object.chatId !== undefined && object.chatId !== null) {
message.chatId = String(object.chatId); message.chatId = String(object.chatId)
} else { } else {
message.chatId = ""; message.chatId = ''
} }
if (object.events !== undefined && object.events !== null) { if (object.events !== undefined && object.events !== null) {
for (const e of object.events) { for (const e of object.events) {
message.events.push(bytesFromBase64(e)); message.events.push(bytesFromBase64(e))
} }
} }
if (object.message !== undefined && object.message !== null) { if (object.message !== undefined && object.message !== null) {
message.message = ChatMessage.fromJSON(object.message); message.message = ChatMessage.fromJSON(object.message)
} else { } else {
message.message = undefined; message.message = undefined
} }
if (object.emojiReaction !== undefined && object.emojiReaction !== null) { if (object.emojiReaction !== undefined && object.emojiReaction !== null) {
message.emojiReaction = EmojiReaction.fromJSON(object.emojiReaction); message.emojiReaction = EmojiReaction.fromJSON(object.emojiReaction)
} else { } else {
message.emojiReaction = undefined; message.emojiReaction = undefined
} }
return message; return message
}, },
toJSON(message: MembershipUpdateMessage): unknown { toJSON(message: MembershipUpdateMessage): unknown {
const obj: any = {}; const obj: any = {}
message.chatId !== undefined && (obj.chatId = message.chatId); message.chatId !== undefined && (obj.chatId = message.chatId)
if (message.events) { if (message.events) {
obj.events = message.events.map((e) => obj.events = message.events.map(e =>
base64FromBytes(e !== undefined ? e : new Uint8Array()) base64FromBytes(e !== undefined ? e : new Uint8Array())
); )
} else { } else {
obj.events = []; obj.events = []
} }
message.message !== undefined && message.message !== undefined &&
(obj.message = message.message (obj.message = message.message
? ChatMessage.toJSON(message.message) ? ChatMessage.toJSON(message.message)
: undefined); : undefined)
message.emojiReaction !== undefined && message.emojiReaction !== undefined &&
(obj.emojiReaction = message.emojiReaction (obj.emojiReaction = message.emojiReaction
? EmojiReaction.toJSON(message.emojiReaction) ? EmojiReaction.toJSON(message.emojiReaction)
: undefined); : undefined)
return obj; return obj
}, },
fromPartial( fromPartial(
@ -345,64 +345,64 @@ export const MembershipUpdateMessage = {
): MembershipUpdateMessage { ): MembershipUpdateMessage {
const message = { const message = {
...baseMembershipUpdateMessage, ...baseMembershipUpdateMessage,
} as MembershipUpdateMessage; } as MembershipUpdateMessage
message.events = []; message.events = []
if (object.chatId !== undefined && object.chatId !== null) { if (object.chatId !== undefined && object.chatId !== null) {
message.chatId = object.chatId; message.chatId = object.chatId
} else { } else {
message.chatId = ""; message.chatId = ''
} }
if (object.events !== undefined && object.events !== null) { if (object.events !== undefined && object.events !== null) {
for (const e of object.events) { for (const e of object.events) {
message.events.push(e); message.events.push(e)
} }
} }
if (object.message !== undefined && object.message !== null) { if (object.message !== undefined && object.message !== null) {
message.message = ChatMessage.fromPartial(object.message); message.message = ChatMessage.fromPartial(object.message)
} else { } else {
message.message = undefined; message.message = undefined
} }
if (object.emojiReaction !== undefined && object.emojiReaction !== null) { if (object.emojiReaction !== undefined && object.emojiReaction !== null) {
message.emojiReaction = EmojiReaction.fromPartial(object.emojiReaction); message.emojiReaction = EmojiReaction.fromPartial(object.emojiReaction)
} else { } else {
message.emojiReaction = undefined; message.emojiReaction = undefined
} }
return message; return message
}, },
}; }
declare var self: any | undefined; declare var self: any | undefined
declare var window: any | undefined; declare var window: any | undefined
declare var global: any | undefined; declare var global: any | undefined
var globalThis: any = (() => { var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis; if (typeof globalThis !== 'undefined') return globalThis
if (typeof self !== "undefined") return self; if (typeof self !== 'undefined') return self
if (typeof window !== "undefined") return window; if (typeof window !== 'undefined') return window
if (typeof global !== "undefined") return global; if (typeof global !== 'undefined') return global
throw "Unable to locate global object"; throw 'Unable to locate global object'
})(); })()
const atob: (b64: string) => string = const atob: (b64: string) => string =
globalThis.atob || globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary")); (b64 => globalThis.Buffer.from(b64, 'base64').toString('binary'))
function bytesFromBase64(b64: string): Uint8Array { function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64); const bin = atob(b64)
const arr = new Uint8Array(bin.length); const arr = new Uint8Array(bin.length)
for (let i = 0; i < bin.length; ++i) { for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i); arr[i] = bin.charCodeAt(i)
} }
return arr; return arr
} }
const btoa: (bin: string) => string = const btoa: (bin: string) => string =
globalThis.btoa || globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64")); (bin => globalThis.Buffer.from(bin, 'binary').toString('base64'))
function base64FromBytes(arr: Uint8Array): string { function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = []; const bin: string[] = []
for (const byte of arr) { for (const byte of arr) {
bin.push(String.fromCharCode(byte)); bin.push(String.fromCharCode(byte))
} }
return btoa(bin.join("")); return btoa(bin.join(''))
} }
type Builtin = type Builtin =
@ -412,7 +412,7 @@ type Builtin =
| string | string
| number | number
| boolean | boolean
| undefined; | undefined
export type DeepPartial<T> = T extends Builtin export type DeepPartial<T> = T extends Builtin
? T ? T
: T extends Array<infer U> : T extends Array<infer U>
@ -421,16 +421,16 @@ export type DeepPartial<T> = T extends Builtin
? ReadonlyArray<DeepPartial<U>> ? ReadonlyArray<DeepPartial<U>>
: T extends {} : T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> } ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>; : Partial<T>
function longToNumber(long: Long): number { function longToNumber(long: Long): number {
if (long.gt(Number.MAX_SAFE_INTEGER)) { if (long.gt(Number.MAX_SAFE_INTEGER)) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); throw new globalThis.Error('Value is larger than Number.MAX_SAFE_INTEGER')
} }
return long.toNumber(); return long.toNumber()
} }
if (_m0.util.Long !== Long) { if (_m0.util.Long !== Long) {
_m0.util.Long = Long as any; _m0.util.Long = Long as any
_m0.configure(); _m0.configure()
} }

View File

@ -1,8 +1,8 @@
/* eslint-disable */ /* eslint-disable */
import Long from "long"; import Long from 'long'
import _m0 from "protobufjs/minimal"; import _m0 from 'protobufjs/minimal'
export const protobufPackage = "communities.v1"; export const protobufPackage = 'communities.v1'
/** /**
* Specs: * Specs:
@ -18,9 +18,9 @@ export const protobufPackage = "communities.v1";
* Note: Only send pings if the user interacted with the app in the last x minutes. * Note: Only send pings if the user interacted with the app in the last x minutes.
*/ */
export interface StatusUpdate { export interface StatusUpdate {
clock: number; clock: number
statusType: StatusUpdate_StatusType; statusType: StatusUpdate_StatusType
customText: string; customText: string
} }
export enum StatusUpdate_StatusType { export enum StatusUpdate_StatusType {
@ -37,24 +37,24 @@ export function statusUpdate_StatusTypeFromJSON(
): StatusUpdate_StatusType { ): StatusUpdate_StatusType {
switch (object) { switch (object) {
case 0: case 0:
case "UNKNOWN_STATUS_TYPE": case 'UNKNOWN_STATUS_TYPE':
return StatusUpdate_StatusType.UNKNOWN_STATUS_TYPE; return StatusUpdate_StatusType.UNKNOWN_STATUS_TYPE
case 1: case 1:
case "AUTOMATIC": case 'AUTOMATIC':
return StatusUpdate_StatusType.AUTOMATIC; return StatusUpdate_StatusType.AUTOMATIC
case 2: case 2:
case "DO_NOT_DISTURB": case 'DO_NOT_DISTURB':
return StatusUpdate_StatusType.DO_NOT_DISTURB; return StatusUpdate_StatusType.DO_NOT_DISTURB
case 3: case 3:
case "ALWAYS_ONLINE": case 'ALWAYS_ONLINE':
return StatusUpdate_StatusType.ALWAYS_ONLINE; return StatusUpdate_StatusType.ALWAYS_ONLINE
case 4: case 4:
case "INACTIVE": case 'INACTIVE':
return StatusUpdate_StatusType.INACTIVE; return StatusUpdate_StatusType.INACTIVE
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return StatusUpdate_StatusType.UNRECOGNIZED; return StatusUpdate_StatusType.UNRECOGNIZED
} }
} }
@ -63,21 +63,21 @@ export function statusUpdate_StatusTypeToJSON(
): string { ): string {
switch (object) { switch (object) {
case StatusUpdate_StatusType.UNKNOWN_STATUS_TYPE: case StatusUpdate_StatusType.UNKNOWN_STATUS_TYPE:
return "UNKNOWN_STATUS_TYPE"; return 'UNKNOWN_STATUS_TYPE'
case StatusUpdate_StatusType.AUTOMATIC: case StatusUpdate_StatusType.AUTOMATIC:
return "AUTOMATIC"; return 'AUTOMATIC'
case StatusUpdate_StatusType.DO_NOT_DISTURB: case StatusUpdate_StatusType.DO_NOT_DISTURB:
return "DO_NOT_DISTURB"; return 'DO_NOT_DISTURB'
case StatusUpdate_StatusType.ALWAYS_ONLINE: case StatusUpdate_StatusType.ALWAYS_ONLINE:
return "ALWAYS_ONLINE"; return 'ALWAYS_ONLINE'
case StatusUpdate_StatusType.INACTIVE: case StatusUpdate_StatusType.INACTIVE:
return "INACTIVE"; return 'INACTIVE'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
const baseStatusUpdate: object = { clock: 0, statusType: 0, customText: "" }; const baseStatusUpdate: object = { clock: 0, statusType: 0, customText: '' }
export const StatusUpdate = { export const StatusUpdate = {
encode( encode(
@ -85,101 +85,101 @@ export const StatusUpdate = {
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.clock !== 0) { if (message.clock !== 0) {
writer.uint32(8).uint64(message.clock); writer.uint32(8).uint64(message.clock)
} }
if (message.statusType !== 0) { if (message.statusType !== 0) {
writer.uint32(16).int32(message.statusType); writer.uint32(16).int32(message.statusType)
} }
if (message.customText !== "") { if (message.customText !== '') {
writer.uint32(26).string(message.customText); writer.uint32(26).string(message.customText)
} }
return writer; return writer
}, },
decode(input: _m0.Reader | Uint8Array, length?: number): StatusUpdate { decode(input: _m0.Reader | Uint8Array, length?: number): StatusUpdate {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { ...baseStatusUpdate } as StatusUpdate; const message = { ...baseStatusUpdate } as StatusUpdate
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.clock = longToNumber(reader.uint64() as Long); message.clock = longToNumber(reader.uint64() as Long)
break; break
case 2: case 2:
message.statusType = reader.int32() as any; message.statusType = reader.int32() as any
break; break
case 3: case 3:
message.customText = reader.string(); message.customText = reader.string()
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): StatusUpdate { fromJSON(object: any): StatusUpdate {
const message = { ...baseStatusUpdate } as StatusUpdate; const message = { ...baseStatusUpdate } as StatusUpdate
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = Number(object.clock); message.clock = Number(object.clock)
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.statusType !== undefined && object.statusType !== null) { if (object.statusType !== undefined && object.statusType !== null) {
message.statusType = statusUpdate_StatusTypeFromJSON(object.statusType); message.statusType = statusUpdate_StatusTypeFromJSON(object.statusType)
} else { } else {
message.statusType = 0; message.statusType = 0
} }
if (object.customText !== undefined && object.customText !== null) { if (object.customText !== undefined && object.customText !== null) {
message.customText = String(object.customText); message.customText = String(object.customText)
} else { } else {
message.customText = ""; message.customText = ''
} }
return message; return message
}, },
toJSON(message: StatusUpdate): unknown { toJSON(message: StatusUpdate): unknown {
const obj: any = {}; const obj: any = {}
message.clock !== undefined && (obj.clock = message.clock); message.clock !== undefined && (obj.clock = message.clock)
message.statusType !== undefined && message.statusType !== undefined &&
(obj.statusType = statusUpdate_StatusTypeToJSON(message.statusType)); (obj.statusType = statusUpdate_StatusTypeToJSON(message.statusType))
message.customText !== undefined && (obj.customText = message.customText); message.customText !== undefined && (obj.customText = message.customText)
return obj; return obj
}, },
fromPartial(object: DeepPartial<StatusUpdate>): StatusUpdate { fromPartial(object: DeepPartial<StatusUpdate>): StatusUpdate {
const message = { ...baseStatusUpdate } as StatusUpdate; const message = { ...baseStatusUpdate } as StatusUpdate
if (object.clock !== undefined && object.clock !== null) { if (object.clock !== undefined && object.clock !== null) {
message.clock = object.clock; message.clock = object.clock
} else { } else {
message.clock = 0; message.clock = 0
} }
if (object.statusType !== undefined && object.statusType !== null) { if (object.statusType !== undefined && object.statusType !== null) {
message.statusType = object.statusType; message.statusType = object.statusType
} else { } else {
message.statusType = 0; message.statusType = 0
} }
if (object.customText !== undefined && object.customText !== null) { if (object.customText !== undefined && object.customText !== null) {
message.customText = object.customText; message.customText = object.customText
} else { } else {
message.customText = ""; message.customText = ''
} }
return message; return message
}, },
}; }
declare var self: any | undefined; declare var self: any | undefined
declare var window: any | undefined; declare var window: any | undefined
declare var global: any | undefined; declare var global: any | undefined
var globalThis: any = (() => { var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis; if (typeof globalThis !== 'undefined') return globalThis
if (typeof self !== "undefined") return self; if (typeof self !== 'undefined') return self
if (typeof window !== "undefined") return window; if (typeof window !== 'undefined') return window
if (typeof global !== "undefined") return global; if (typeof global !== 'undefined') return global
throw "Unable to locate global object"; throw 'Unable to locate global object'
})(); })()
type Builtin = type Builtin =
| Date | Date
@ -188,7 +188,7 @@ type Builtin =
| string | string
| number | number
| boolean | boolean
| undefined; | undefined
export type DeepPartial<T> = T extends Builtin export type DeepPartial<T> = T extends Builtin
? T ? T
: T extends Array<infer U> : T extends Array<infer U>
@ -197,16 +197,16 @@ export type DeepPartial<T> = T extends Builtin
? ReadonlyArray<DeepPartial<U>> ? ReadonlyArray<DeepPartial<U>>
: T extends {} : T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> } ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>; : Partial<T>
function longToNumber(long: Long): number { function longToNumber(long: Long): number {
if (long.gt(Number.MAX_SAFE_INTEGER)) { if (long.gt(Number.MAX_SAFE_INTEGER)) {
throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); throw new globalThis.Error('Value is larger than Number.MAX_SAFE_INTEGER')
} }
return long.toNumber(); return long.toNumber()
} }
if (_m0.util.Long !== Long) { if (_m0.util.Long !== Long) {
_m0.util.Long = Long as any; _m0.util.Long = Long as any
_m0.configure(); _m0.configure()
} }

View File

@ -1,16 +1,16 @@
/* eslint-disable */ /* eslint-disable */
import Long from "long"; import Long from 'long'
import _m0 from "protobufjs/minimal"; import _m0 from 'protobufjs/minimal'
export const protobufPackage = "status.v1"; export const protobufPackage = 'status.v1'
export interface ApplicationMetadataMessage { export interface ApplicationMetadataMessage {
/** Signature of the payload field */ /** Signature of the payload field */
signature: Uint8Array; signature: Uint8Array
/** This is the encoded protobuf of the application level message, i.e ChatMessage */ /** This is the encoded protobuf of the application level message, i.e ChatMessage */
payload: Uint8Array; payload: Uint8Array
/** The type of protobuf message sent */ /** The type of protobuf message sent */
type: ApplicationMetadataMessage_Type; type: ApplicationMetadataMessage_Type
} }
export enum ApplicationMetadataMessage_Type { export enum ApplicationMetadataMessage_Type {
@ -56,111 +56,111 @@ export function applicationMetadataMessage_TypeFromJSON(
): ApplicationMetadataMessage_Type { ): ApplicationMetadataMessage_Type {
switch (object) { switch (object) {
case 0: case 0:
case "TYPE_UNKNOWN_UNSPECIFIED": case 'TYPE_UNKNOWN_UNSPECIFIED':
return ApplicationMetadataMessage_Type.TYPE_UNKNOWN_UNSPECIFIED; return ApplicationMetadataMessage_Type.TYPE_UNKNOWN_UNSPECIFIED
case 1: case 1:
case "TYPE_CHAT_MESSAGE": case 'TYPE_CHAT_MESSAGE':
return ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE; return ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE
case 2: case 2:
case "TYPE_CONTACT_UPDATE": case 'TYPE_CONTACT_UPDATE':
return ApplicationMetadataMessage_Type.TYPE_CONTACT_UPDATE; return ApplicationMetadataMessage_Type.TYPE_CONTACT_UPDATE
case 3: case 3:
case "TYPE_MEMBERSHIP_UPDATE_MESSAGE": case 'TYPE_MEMBERSHIP_UPDATE_MESSAGE':
return ApplicationMetadataMessage_Type.TYPE_MEMBERSHIP_UPDATE_MESSAGE; return ApplicationMetadataMessage_Type.TYPE_MEMBERSHIP_UPDATE_MESSAGE
case 4: case 4:
case "TYPE_PAIR_INSTALLATION": case 'TYPE_PAIR_INSTALLATION':
return ApplicationMetadataMessage_Type.TYPE_PAIR_INSTALLATION; return ApplicationMetadataMessage_Type.TYPE_PAIR_INSTALLATION
case 5: case 5:
case "TYPE_SYNC_INSTALLATION": case 'TYPE_SYNC_INSTALLATION':
return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION; return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION
case 6: case 6:
case "TYPE_REQUEST_ADDRESS_FOR_TRANSACTION": case 'TYPE_REQUEST_ADDRESS_FOR_TRANSACTION':
return ApplicationMetadataMessage_Type.TYPE_REQUEST_ADDRESS_FOR_TRANSACTION; return ApplicationMetadataMessage_Type.TYPE_REQUEST_ADDRESS_FOR_TRANSACTION
case 7: case 7:
case "TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION": case 'TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION':
return ApplicationMetadataMessage_Type.TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION; return ApplicationMetadataMessage_Type.TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION
case 8: case 8:
case "TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION": case 'TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION':
return ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION; return ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION
case 9: case 9:
case "TYPE_REQUEST_TRANSACTION": case 'TYPE_REQUEST_TRANSACTION':
return ApplicationMetadataMessage_Type.TYPE_REQUEST_TRANSACTION; return ApplicationMetadataMessage_Type.TYPE_REQUEST_TRANSACTION
case 10: case 10:
case "TYPE_SEND_TRANSACTION": case 'TYPE_SEND_TRANSACTION':
return ApplicationMetadataMessage_Type.TYPE_SEND_TRANSACTION; return ApplicationMetadataMessage_Type.TYPE_SEND_TRANSACTION
case 11: case 11:
case "TYPE_DECLINE_REQUEST_TRANSACTION": case 'TYPE_DECLINE_REQUEST_TRANSACTION':
return ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_TRANSACTION; return ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_TRANSACTION
case 12: case 12:
case "TYPE_SYNC_INSTALLATION_CONTACT": case 'TYPE_SYNC_INSTALLATION_CONTACT':
return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_CONTACT; return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_CONTACT
case 13: case 13:
case "TYPE_SYNC_INSTALLATION_ACCOUNT": case 'TYPE_SYNC_INSTALLATION_ACCOUNT':
return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_ACCOUNT; return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_ACCOUNT
case 14: case 14:
case "TYPE_SYNC_INSTALLATION_PUBLIC_CHAT": case 'TYPE_SYNC_INSTALLATION_PUBLIC_CHAT':
return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_PUBLIC_CHAT; return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_PUBLIC_CHAT
case 15: case 15:
case "TYPE_CONTACT_CODE_ADVERTISEMENT": case 'TYPE_CONTACT_CODE_ADVERTISEMENT':
return ApplicationMetadataMessage_Type.TYPE_CONTACT_CODE_ADVERTISEMENT; return ApplicationMetadataMessage_Type.TYPE_CONTACT_CODE_ADVERTISEMENT
case 16: case 16:
case "TYPE_PUSH_NOTIFICATION_REGISTRATION": case 'TYPE_PUSH_NOTIFICATION_REGISTRATION':
return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION; return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION
case 17: case 17:
case "TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE": case 'TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE':
return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE; return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE
case 18: case 18:
case "TYPE_PUSH_NOTIFICATION_QUERY": case 'TYPE_PUSH_NOTIFICATION_QUERY':
return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY; return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY
case 19: case 19:
case "TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE": case 'TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE':
return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE; return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE
case 20: case 20:
case "TYPE_PUSH_NOTIFICATION_REQUEST": case 'TYPE_PUSH_NOTIFICATION_REQUEST':
return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REQUEST; return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REQUEST
case 21: case 21:
case "TYPE_PUSH_NOTIFICATION_RESPONSE": case 'TYPE_PUSH_NOTIFICATION_RESPONSE':
return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_RESPONSE; return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_RESPONSE
case 22: case 22:
case "TYPE_EMOJI_REACTION": case 'TYPE_EMOJI_REACTION':
return ApplicationMetadataMessage_Type.TYPE_EMOJI_REACTION; return ApplicationMetadataMessage_Type.TYPE_EMOJI_REACTION
case 23: case 23:
case "TYPE_GROUP_CHAT_INVITATION": case 'TYPE_GROUP_CHAT_INVITATION':
return ApplicationMetadataMessage_Type.TYPE_GROUP_CHAT_INVITATION; return ApplicationMetadataMessage_Type.TYPE_GROUP_CHAT_INVITATION
case 24: case 24:
case "TYPE_CHAT_IDENTITY": case 'TYPE_CHAT_IDENTITY':
return ApplicationMetadataMessage_Type.TYPE_CHAT_IDENTITY; return ApplicationMetadataMessage_Type.TYPE_CHAT_IDENTITY
case 25: case 25:
case "TYPE_COMMUNITY_DESCRIPTION": case 'TYPE_COMMUNITY_DESCRIPTION':
return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_DESCRIPTION; return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_DESCRIPTION
case 26: case 26:
case "TYPE_COMMUNITY_INVITATION": case 'TYPE_COMMUNITY_INVITATION':
return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_INVITATION; return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_INVITATION
case 27: case 27:
case "TYPE_COMMUNITY_REQUEST_TO_JOIN": case 'TYPE_COMMUNITY_REQUEST_TO_JOIN':
return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_REQUEST_TO_JOIN; return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_REQUEST_TO_JOIN
case 28: case 28:
case "TYPE_PIN_MESSAGE": case 'TYPE_PIN_MESSAGE':
return ApplicationMetadataMessage_Type.TYPE_PIN_MESSAGE; return ApplicationMetadataMessage_Type.TYPE_PIN_MESSAGE
case 29: case 29:
case "TYPE_EDIT_MESSAGE": case 'TYPE_EDIT_MESSAGE':
return ApplicationMetadataMessage_Type.TYPE_EDIT_MESSAGE; return ApplicationMetadataMessage_Type.TYPE_EDIT_MESSAGE
case 30: case 30:
case "TYPE_STATUS_UPDATE": case 'TYPE_STATUS_UPDATE':
return ApplicationMetadataMessage_Type.TYPE_STATUS_UPDATE; return ApplicationMetadataMessage_Type.TYPE_STATUS_UPDATE
case 31: case 31:
case "TYPE_DELETE_MESSAGE": case 'TYPE_DELETE_MESSAGE':
return ApplicationMetadataMessage_Type.TYPE_DELETE_MESSAGE; return ApplicationMetadataMessage_Type.TYPE_DELETE_MESSAGE
case 32: case 32:
case "TYPE_SYNC_INSTALLATION_COMMUNITY": case 'TYPE_SYNC_INSTALLATION_COMMUNITY':
return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_COMMUNITY; return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_COMMUNITY
case 33: case 33:
case "TYPE_ANONYMOUS_METRIC_BATCH": case 'TYPE_ANONYMOUS_METRIC_BATCH':
return ApplicationMetadataMessage_Type.TYPE_ANONYMOUS_METRIC_BATCH; return ApplicationMetadataMessage_Type.TYPE_ANONYMOUS_METRIC_BATCH
case -1: case -1:
case "UNRECOGNIZED": case 'UNRECOGNIZED':
default: default:
return ApplicationMetadataMessage_Type.UNRECOGNIZED; return ApplicationMetadataMessage_Type.UNRECOGNIZED
} }
} }
@ -169,79 +169,79 @@ export function applicationMetadataMessage_TypeToJSON(
): string { ): string {
switch (object) { switch (object) {
case ApplicationMetadataMessage_Type.TYPE_UNKNOWN_UNSPECIFIED: case ApplicationMetadataMessage_Type.TYPE_UNKNOWN_UNSPECIFIED:
return "TYPE_UNKNOWN_UNSPECIFIED"; return 'TYPE_UNKNOWN_UNSPECIFIED'
case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE:
return "TYPE_CHAT_MESSAGE"; return 'TYPE_CHAT_MESSAGE'
case ApplicationMetadataMessage_Type.TYPE_CONTACT_UPDATE: case ApplicationMetadataMessage_Type.TYPE_CONTACT_UPDATE:
return "TYPE_CONTACT_UPDATE"; return 'TYPE_CONTACT_UPDATE'
case ApplicationMetadataMessage_Type.TYPE_MEMBERSHIP_UPDATE_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_MEMBERSHIP_UPDATE_MESSAGE:
return "TYPE_MEMBERSHIP_UPDATE_MESSAGE"; return 'TYPE_MEMBERSHIP_UPDATE_MESSAGE'
case ApplicationMetadataMessage_Type.TYPE_PAIR_INSTALLATION: case ApplicationMetadataMessage_Type.TYPE_PAIR_INSTALLATION:
return "TYPE_PAIR_INSTALLATION"; return 'TYPE_PAIR_INSTALLATION'
case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION: case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION:
return "TYPE_SYNC_INSTALLATION"; return 'TYPE_SYNC_INSTALLATION'
case ApplicationMetadataMessage_Type.TYPE_REQUEST_ADDRESS_FOR_TRANSACTION: case ApplicationMetadataMessage_Type.TYPE_REQUEST_ADDRESS_FOR_TRANSACTION:
return "TYPE_REQUEST_ADDRESS_FOR_TRANSACTION"; return 'TYPE_REQUEST_ADDRESS_FOR_TRANSACTION'
case ApplicationMetadataMessage_Type.TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION: case ApplicationMetadataMessage_Type.TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION:
return "TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION"; return 'TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION'
case ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION: case ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION:
return "TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION"; return 'TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION'
case ApplicationMetadataMessage_Type.TYPE_REQUEST_TRANSACTION: case ApplicationMetadataMessage_Type.TYPE_REQUEST_TRANSACTION:
return "TYPE_REQUEST_TRANSACTION"; return 'TYPE_REQUEST_TRANSACTION'
case ApplicationMetadataMessage_Type.TYPE_SEND_TRANSACTION: case ApplicationMetadataMessage_Type.TYPE_SEND_TRANSACTION:
return "TYPE_SEND_TRANSACTION"; return 'TYPE_SEND_TRANSACTION'
case ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_TRANSACTION: case ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_TRANSACTION:
return "TYPE_DECLINE_REQUEST_TRANSACTION"; return 'TYPE_DECLINE_REQUEST_TRANSACTION'
case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_CONTACT: case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_CONTACT:
return "TYPE_SYNC_INSTALLATION_CONTACT"; return 'TYPE_SYNC_INSTALLATION_CONTACT'
case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_ACCOUNT: case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_ACCOUNT:
return "TYPE_SYNC_INSTALLATION_ACCOUNT"; return 'TYPE_SYNC_INSTALLATION_ACCOUNT'
case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_PUBLIC_CHAT: case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_PUBLIC_CHAT:
return "TYPE_SYNC_INSTALLATION_PUBLIC_CHAT"; return 'TYPE_SYNC_INSTALLATION_PUBLIC_CHAT'
case ApplicationMetadataMessage_Type.TYPE_CONTACT_CODE_ADVERTISEMENT: case ApplicationMetadataMessage_Type.TYPE_CONTACT_CODE_ADVERTISEMENT:
return "TYPE_CONTACT_CODE_ADVERTISEMENT"; return 'TYPE_CONTACT_CODE_ADVERTISEMENT'
case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION: case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION:
return "TYPE_PUSH_NOTIFICATION_REGISTRATION"; return 'TYPE_PUSH_NOTIFICATION_REGISTRATION'
case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE: case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE:
return "TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE"; return 'TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE'
case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY: case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY:
return "TYPE_PUSH_NOTIFICATION_QUERY"; return 'TYPE_PUSH_NOTIFICATION_QUERY'
case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE: case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE:
return "TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE"; return 'TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE'
case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REQUEST: case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REQUEST:
return "TYPE_PUSH_NOTIFICATION_REQUEST"; return 'TYPE_PUSH_NOTIFICATION_REQUEST'
case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_RESPONSE: case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_RESPONSE:
return "TYPE_PUSH_NOTIFICATION_RESPONSE"; return 'TYPE_PUSH_NOTIFICATION_RESPONSE'
case ApplicationMetadataMessage_Type.TYPE_EMOJI_REACTION: case ApplicationMetadataMessage_Type.TYPE_EMOJI_REACTION:
return "TYPE_EMOJI_REACTION"; return 'TYPE_EMOJI_REACTION'
case ApplicationMetadataMessage_Type.TYPE_GROUP_CHAT_INVITATION: case ApplicationMetadataMessage_Type.TYPE_GROUP_CHAT_INVITATION:
return "TYPE_GROUP_CHAT_INVITATION"; return 'TYPE_GROUP_CHAT_INVITATION'
case ApplicationMetadataMessage_Type.TYPE_CHAT_IDENTITY: case ApplicationMetadataMessage_Type.TYPE_CHAT_IDENTITY:
return "TYPE_CHAT_IDENTITY"; return 'TYPE_CHAT_IDENTITY'
case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_DESCRIPTION: case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_DESCRIPTION:
return "TYPE_COMMUNITY_DESCRIPTION"; return 'TYPE_COMMUNITY_DESCRIPTION'
case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_INVITATION: case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_INVITATION:
return "TYPE_COMMUNITY_INVITATION"; return 'TYPE_COMMUNITY_INVITATION'
case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_REQUEST_TO_JOIN: case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_REQUEST_TO_JOIN:
return "TYPE_COMMUNITY_REQUEST_TO_JOIN"; return 'TYPE_COMMUNITY_REQUEST_TO_JOIN'
case ApplicationMetadataMessage_Type.TYPE_PIN_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_PIN_MESSAGE:
return "TYPE_PIN_MESSAGE"; return 'TYPE_PIN_MESSAGE'
case ApplicationMetadataMessage_Type.TYPE_EDIT_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_EDIT_MESSAGE:
return "TYPE_EDIT_MESSAGE"; return 'TYPE_EDIT_MESSAGE'
case ApplicationMetadataMessage_Type.TYPE_STATUS_UPDATE: case ApplicationMetadataMessage_Type.TYPE_STATUS_UPDATE:
return "TYPE_STATUS_UPDATE"; return 'TYPE_STATUS_UPDATE'
case ApplicationMetadataMessage_Type.TYPE_DELETE_MESSAGE: case ApplicationMetadataMessage_Type.TYPE_DELETE_MESSAGE:
return "TYPE_DELETE_MESSAGE"; return 'TYPE_DELETE_MESSAGE'
case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_COMMUNITY: case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_COMMUNITY:
return "TYPE_SYNC_INSTALLATION_COMMUNITY"; return 'TYPE_SYNC_INSTALLATION_COMMUNITY'
case ApplicationMetadataMessage_Type.TYPE_ANONYMOUS_METRIC_BATCH: case ApplicationMetadataMessage_Type.TYPE_ANONYMOUS_METRIC_BATCH:
return "TYPE_ANONYMOUS_METRIC_BATCH"; return 'TYPE_ANONYMOUS_METRIC_BATCH'
default: default:
return "UNKNOWN"; return 'UNKNOWN'
} }
} }
const baseApplicationMetadataMessage: object = { type: 0 }; const baseApplicationMetadataMessage: object = { type: 0 }
export const ApplicationMetadataMessage = { export const ApplicationMetadataMessage = {
encode( encode(
@ -249,81 +249,81 @@ export const ApplicationMetadataMessage = {
writer: _m0.Writer = _m0.Writer.create() writer: _m0.Writer = _m0.Writer.create()
): _m0.Writer { ): _m0.Writer {
if (message.signature.length !== 0) { if (message.signature.length !== 0) {
writer.uint32(10).bytes(message.signature); writer.uint32(10).bytes(message.signature)
} }
if (message.payload.length !== 0) { if (message.payload.length !== 0) {
writer.uint32(18).bytes(message.payload); writer.uint32(18).bytes(message.payload)
} }
if (message.type !== 0) { if (message.type !== 0) {
writer.uint32(24).int32(message.type); writer.uint32(24).int32(message.type)
} }
return writer; return writer
}, },
decode( decode(
input: _m0.Reader | Uint8Array, input: _m0.Reader | Uint8Array,
length?: number length?: number
): ApplicationMetadataMessage { ): ApplicationMetadataMessage {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input)
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length
const message = { const message = {
...baseApplicationMetadataMessage, ...baseApplicationMetadataMessage,
} as ApplicationMetadataMessage; } as ApplicationMetadataMessage
message.signature = new Uint8Array(); message.signature = new Uint8Array()
message.payload = new Uint8Array(); message.payload = new Uint8Array()
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32()
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: case 1:
message.signature = reader.bytes(); message.signature = reader.bytes()
break; break
case 2: case 2:
message.payload = reader.bytes(); message.payload = reader.bytes()
break; break
case 3: case 3:
message.type = reader.int32() as any; message.type = reader.int32() as any
break; break
default: default:
reader.skipType(tag & 7); reader.skipType(tag & 7)
break; break
} }
} }
return message; return message
}, },
fromJSON(object: any): ApplicationMetadataMessage { fromJSON(object: any): ApplicationMetadataMessage {
const message = { const message = {
...baseApplicationMetadataMessage, ...baseApplicationMetadataMessage,
} as ApplicationMetadataMessage; } as ApplicationMetadataMessage
message.signature = new Uint8Array(); message.signature = new Uint8Array()
message.payload = new Uint8Array(); message.payload = new Uint8Array()
if (object.signature !== undefined && object.signature !== null) { if (object.signature !== undefined && object.signature !== null) {
message.signature = bytesFromBase64(object.signature); message.signature = bytesFromBase64(object.signature)
} }
if (object.payload !== undefined && object.payload !== null) { if (object.payload !== undefined && object.payload !== null) {
message.payload = bytesFromBase64(object.payload); message.payload = bytesFromBase64(object.payload)
} }
if (object.type !== undefined && object.type !== null) { if (object.type !== undefined && object.type !== null) {
message.type = applicationMetadataMessage_TypeFromJSON(object.type); message.type = applicationMetadataMessage_TypeFromJSON(object.type)
} else { } else {
message.type = 0; message.type = 0
} }
return message; return message
}, },
toJSON(message: ApplicationMetadataMessage): unknown { toJSON(message: ApplicationMetadataMessage): unknown {
const obj: any = {}; const obj: any = {}
message.signature !== undefined && message.signature !== undefined &&
(obj.signature = base64FromBytes( (obj.signature = base64FromBytes(
message.signature !== undefined ? message.signature : new Uint8Array() message.signature !== undefined ? message.signature : new Uint8Array()
)); ))
message.payload !== undefined && message.payload !== undefined &&
(obj.payload = base64FromBytes( (obj.payload = base64FromBytes(
message.payload !== undefined ? message.payload : new Uint8Array() message.payload !== undefined ? message.payload : new Uint8Array()
)); ))
message.type !== undefined && message.type !== undefined &&
(obj.type = applicationMetadataMessage_TypeToJSON(message.type)); (obj.type = applicationMetadataMessage_TypeToJSON(message.type))
return obj; return obj
}, },
fromPartial( fromPartial(
@ -331,58 +331,58 @@ export const ApplicationMetadataMessage = {
): ApplicationMetadataMessage { ): ApplicationMetadataMessage {
const message = { const message = {
...baseApplicationMetadataMessage, ...baseApplicationMetadataMessage,
} as ApplicationMetadataMessage; } as ApplicationMetadataMessage
if (object.signature !== undefined && object.signature !== null) { if (object.signature !== undefined && object.signature !== null) {
message.signature = object.signature; message.signature = object.signature
} else { } else {
message.signature = new Uint8Array(); message.signature = new Uint8Array()
} }
if (object.payload !== undefined && object.payload !== null) { if (object.payload !== undefined && object.payload !== null) {
message.payload = object.payload; message.payload = object.payload
} else { } else {
message.payload = new Uint8Array(); message.payload = new Uint8Array()
} }
if (object.type !== undefined && object.type !== null) { if (object.type !== undefined && object.type !== null) {
message.type = object.type; message.type = object.type
} else { } else {
message.type = 0; message.type = 0
} }
return message; return message
}, },
}; }
declare var self: any | undefined; declare var self: any | undefined
declare var window: any | undefined; declare var window: any | undefined
declare var global: any | undefined; declare var global: any | undefined
var globalThis: any = (() => { var globalThis: any = (() => {
if (typeof globalThis !== "undefined") return globalThis; if (typeof globalThis !== 'undefined') return globalThis
if (typeof self !== "undefined") return self; if (typeof self !== 'undefined') return self
if (typeof window !== "undefined") return window; if (typeof window !== 'undefined') return window
if (typeof global !== "undefined") return global; if (typeof global !== 'undefined') return global
throw "Unable to locate global object"; throw 'Unable to locate global object'
})(); })()
const atob: (b64: string) => string = const atob: (b64: string) => string =
globalThis.atob || globalThis.atob ||
((b64) => globalThis.Buffer.from(b64, "base64").toString("binary")); (b64 => globalThis.Buffer.from(b64, 'base64').toString('binary'))
function bytesFromBase64(b64: string): Uint8Array { function bytesFromBase64(b64: string): Uint8Array {
const bin = atob(b64); const bin = atob(b64)
const arr = new Uint8Array(bin.length); const arr = new Uint8Array(bin.length)
for (let i = 0; i < bin.length; ++i) { for (let i = 0; i < bin.length; ++i) {
arr[i] = bin.charCodeAt(i); arr[i] = bin.charCodeAt(i)
} }
return arr; return arr
} }
const btoa: (bin: string) => string = const btoa: (bin: string) => string =
globalThis.btoa || globalThis.btoa ||
((bin) => globalThis.Buffer.from(bin, "binary").toString("base64")); (bin => globalThis.Buffer.from(bin, 'binary').toString('base64'))
function base64FromBytes(arr: Uint8Array): string { function base64FromBytes(arr: Uint8Array): string {
const bin: string[] = []; const bin: string[] = []
for (const byte of arr) { for (const byte of arr) {
bin.push(String.fromCharCode(byte)); bin.push(String.fromCharCode(byte))
} }
return btoa(bin.join("")); return btoa(bin.join(''))
} }
type Builtin = type Builtin =
@ -392,7 +392,7 @@ type Builtin =
| string | string
| number | number
| boolean | boolean
| undefined; | undefined
export type DeepPartial<T> = T extends Builtin export type DeepPartial<T> = T extends Builtin
? T ? T
: T extends Array<infer U> : T extends Array<infer U>
@ -401,9 +401,9 @@ export type DeepPartial<T> = T extends Builtin
? ReadonlyArray<DeepPartial<U>> ? ReadonlyArray<DeepPartial<U>>
: T extends {} : T extends {}
? { [K in keyof T]?: DeepPartial<T[K]> } ? { [K in keyof T]?: DeepPartial<T[K]> }
: Partial<T>; : Partial<T>
if (_m0.util.Long !== Long) { if (_m0.util.Long !== Long) {
_m0.util.Long = Long as any; _m0.util.Long = Long as any
_m0.configure(); _m0.configure()
} }

View File

@ -1,15 +1,15 @@
import { BN } from "bn.js"; import { BN } from 'bn.js'
import { derive } from "ecies-geth"; import { derive } from 'ecies-geth'
import { ec } from "elliptic"; import { ec } from 'elliptic'
import { bufToHex } from "js-waku/build/main/lib/utils"; import { bufToHex } from 'js-waku/build/main/lib/utils'
import { idToContentTopic } from "./contentTopic"; import { idToContentTopic } from './contentTopic'
import { hexToBuf } from "./utils"; import { hexToBuf } from './utils'
import { Identity } from "."; import { Identity } from '.'
const EC = new ec("secp256k1"); const EC = new ec('secp256k1')
const partitionsNum = new BN(5000); const partitionsNum = new BN(5000)
/** /**
* Get the partitioned topic https://specs.status.im/spec/3#partitioned-topic * Get the partitioned topic https://specs.status.im/spec/3#partitioned-topic
@ -17,14 +17,14 @@ const partitionsNum = new BN(5000);
* @returns string The Waku v2 Content Topic. * @returns string The Waku v2 Content Topic.
*/ */
export function getPartitionedTopic(publicKey: string): string { export function getPartitionedTopic(publicKey: string): string {
const key = EC.keyFromPublic(publicKey.slice(2), "hex"); const key = EC.keyFromPublic(publicKey.slice(2), 'hex')
const X = key.getPublic().getX(); const X = key.getPublic().getX()
const partition = X.mod(partitionsNum); const partition = X.mod(partitionsNum)
const partitionTopic = `contact-discovery-${partition.toString()}`; const partitionTopic = `contact-discovery-${partition.toString()}`
return idToContentTopic(partitionTopic); return idToContentTopic(partitionTopic)
} }
/** /**
@ -37,10 +37,10 @@ export async function getNegotiatedTopic(
identity: Identity, identity: Identity,
publicKey: string publicKey: string
): Promise<string> { ): Promise<string> {
const key = EC.keyFromPublic(publicKey.slice(2), "hex"); const key = EC.keyFromPublic(publicKey.slice(2), 'hex')
const sharedSecret = await derive( const sharedSecret = await derive(
Buffer.from(identity.privateKey), Buffer.from(identity.privateKey),
hexToBuf(key.getPublic("hex")) hexToBuf(key.getPublic('hex'))
); )
return idToContentTopic(bufToHex(sharedSecret)); return idToContentTopic(bufToHex(sharedSecret))
} }

View File

@ -1,57 +1,57 @@
import { ec } from "elliptic"; import { ec } from 'elliptic'
import { PageDirection, utils, Waku } from "js-waku"; import { PageDirection, utils, Waku } from 'js-waku'
import { idToContactCodeTopic } from "./contentTopic"; import { idToContactCodeTopic } from './contentTopic'
import { ChatIdentity } from "./proto/communities/v1/chat_identity"; import { ChatIdentity } from './proto/communities/v1/chat_identity'
const EC = new ec("secp256k1"); const EC = new ec('secp256k1')
const hexToBuf = utils.hexToBuf; const hexToBuf = utils.hexToBuf
export { hexToBuf }; export { hexToBuf }
/** /**
* Return hex string with 0x prefix (commonly used for string format of a community id/public key. * Return hex string with 0x prefix (commonly used for string format of a community id/public key.
*/ */
export function bufToHex(buf: Uint8Array): string { export function bufToHex(buf: Uint8Array): string {
return "0x" + utils.bufToHex(buf); return '0x' + utils.bufToHex(buf)
} }
export function compressPublicKey(key: Uint8Array): string { export function compressPublicKey(key: Uint8Array): string {
const PubKey = EC.keyFromPublic(key); const PubKey = EC.keyFromPublic(key)
return "0x" + PubKey.getPublic(true, "hex"); return '0x' + PubKey.getPublic(true, 'hex')
} }
export function genPrivateKeyWithEntropy(key: string): Uint8Array { export function genPrivateKeyWithEntropy(key: string): Uint8Array {
const pair = EC.genKeyPair({ entropy: key }); const pair = EC.genKeyPair({ entropy: key })
return hexToBuf("0x" + pair.getPrivate("hex")); return hexToBuf('0x' + pair.getPrivate('hex'))
} }
export async function getLatestUserNickname( export async function getLatestUserNickname(
key: Uint8Array, key: Uint8Array,
waku: Waku waku: Waku
): Promise<{ clock: number; nickname: string }> { ): Promise<{ clock: number; nickname: string }> {
const publicKey = bufToHex(key); const publicKey = bufToHex(key)
let nickname = ""; let nickname = ''
let clock = 0; let clock = 0
await waku.store.queryHistory([idToContactCodeTopic(publicKey)], { await waku.store.queryHistory([idToContactCodeTopic(publicKey)], {
callback: (msgs) => callback: msgs =>
msgs.some((e) => { msgs.some(e => {
try { try {
if (e.payload) { if (e.payload) {
const chatIdentity = ChatIdentity.decode(e?.payload); const chatIdentity = ChatIdentity.decode(e?.payload)
if (chatIdentity) { if (chatIdentity) {
if (chatIdentity?.displayName) { if (chatIdentity?.displayName) {
clock = chatIdentity?.clock ?? 0; clock = chatIdentity?.clock ?? 0
nickname = chatIdentity?.displayName; nickname = chatIdentity?.displayName
} }
} }
return true; return true
} }
} catch { } catch {
return false; return false
} }
}), }),
pageDirection: PageDirection.BACKWARD, pageDirection: PageDirection.BACKWARD,
}); })
return { clock, nickname }; return { clock, nickname }
} }

View File

@ -1,13 +1,13 @@
import { keccak256 } from "js-sha3"; import { keccak256 } from 'js-sha3'
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import secp256k1 from "secp256k1"; import secp256k1 from 'secp256k1'
import { Identity } from "../identity"; import { Identity } from '../identity'
import * as proto from "../proto/status/v1/application_metadata_message"; import * as proto from '../proto/status/v1/application_metadata_message'
import { ApplicationMetadataMessage_Type } from "../proto/status/v1/application_metadata_message"; import { ApplicationMetadataMessage_Type } from '../proto/status/v1/application_metadata_message'
import { hexToBuf } from "../utils"; import { hexToBuf } from '../utils'
import { ChatMessage } from "./chat_message"; import { ChatMessage } from './chat_message'
export class ApplicationMetadataMessage { export class ApplicationMetadataMessage {
private constructor(public proto: proto.ApplicationMetadataMessage) {} private constructor(public proto: proto.ApplicationMetadataMessage) {}
@ -20,56 +20,56 @@ export class ApplicationMetadataMessage {
type: ApplicationMetadataMessage_Type, type: ApplicationMetadataMessage_Type,
identity: Identity identity: Identity
): ApplicationMetadataMessage { ): ApplicationMetadataMessage {
const signature = identity.sign(payload); const signature = identity.sign(payload)
const proto = { const proto = {
signature, signature,
payload, payload,
type, type,
}; }
return new ApplicationMetadataMessage(proto); return new ApplicationMetadataMessage(proto)
} }
static decode(bytes: Uint8Array): ApplicationMetadataMessage { static decode(bytes: Uint8Array): ApplicationMetadataMessage {
const protoBuf = proto.ApplicationMetadataMessage.decode( const protoBuf = proto.ApplicationMetadataMessage.decode(
Reader.create(bytes) Reader.create(bytes)
); )
return new ApplicationMetadataMessage(protoBuf); return new ApplicationMetadataMessage(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.ApplicationMetadataMessage.encode(this.proto).finish(); return proto.ApplicationMetadataMessage.encode(this.proto).finish()
} }
public get signature(): Uint8Array | undefined { public get signature(): Uint8Array | undefined {
return this.proto.signature; return this.proto.signature
} }
public get payload(): Uint8Array | undefined { public get payload(): Uint8Array | undefined {
return this.proto.payload; return this.proto.payload
} }
public get type(): ApplicationMetadataMessage_Type | undefined { public get type(): ApplicationMetadataMessage_Type | undefined {
return this.proto.type; return this.proto.type
} }
/** /**
* Returns a chat message if the type is [TYPE_CHAT_MESSAGE], undefined otherwise. * Returns a chat message if the type is [TYPE_CHAT_MESSAGE], undefined otherwise.
*/ */
public get chatMessage(): ChatMessage | undefined { public get chatMessage(): ChatMessage | undefined {
if (!this.payload) return; if (!this.payload) return
return ChatMessage.decode(this.payload); return ChatMessage.decode(this.payload)
} }
public get signer(): Uint8Array | undefined { public get signer(): Uint8Array | undefined {
if (!this.signature || !this.payload) return; if (!this.signature || !this.payload) return
const signature = this.signature.slice(0, 64); const signature = this.signature.slice(0, 64)
const recid = this.signature.slice(64)[0]; const recid = this.signature.slice(64)[0]
const hash = keccak256(this.payload); const hash = keccak256(this.payload)
return secp256k1.ecdsaRecover(signature, recid, hexToBuf(hash)); return secp256k1.ecdsaRecover(signature, recid, hexToBuf(hash))
} }
} }

View File

@ -1,51 +1,51 @@
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import * as proto from "../proto/communities/v1/chat_identity"; import * as proto from '../proto/communities/v1/chat_identity'
import { IdentityImage } from "../proto/communities/v1/chat_identity"; import { IdentityImage } from '../proto/communities/v1/chat_identity'
export class ChatIdentity { export class ChatIdentity {
public constructor(public proto: proto.ChatIdentity) {} public constructor(public proto: proto.ChatIdentity) {}
static decode(bytes: Uint8Array): ChatIdentity { static decode(bytes: Uint8Array): ChatIdentity {
const protoBuf = proto.ChatIdentity.decode(Reader.create(bytes)); const protoBuf = proto.ChatIdentity.decode(Reader.create(bytes))
return new ChatIdentity(protoBuf); return new ChatIdentity(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.ChatIdentity.encode(this.proto).finish(); return proto.ChatIdentity.encode(this.proto).finish()
} }
/** Lamport timestamp of the message */ /** Lamport timestamp of the message */
get clock(): number | undefined { get clock(): number | undefined {
return this.proto.clock; return this.proto.clock
} }
/** ens_name is the valid ENS name associated with the chat key */ /** ens_name is the valid ENS name associated with the chat key */
get ensName(): string | undefined { get ensName(): string | undefined {
return this.proto.ensName; return this.proto.ensName
} }
/** images is a string indexed mapping of images associated with an identity */ /** images is a string indexed mapping of images associated with an identity */
get images(): { [key: string]: IdentityImage } | undefined { get images(): { [key: string]: IdentityImage } | undefined {
return this.proto.images; return this.proto.images
} }
/** display name is the user set identity, valid only for organisations */ /** display name is the user set identity, valid only for organisations */
get displayName(): string | undefined { get displayName(): string | undefined {
return this.proto.displayName; return this.proto.displayName
} }
/** description is the user set description, valid only for organisations */ /** description is the user set description, valid only for organisations */
get description(): string | undefined { get description(): string | undefined {
return this.proto.description; return this.proto.description
} }
get color(): string | undefined { get color(): string | undefined {
return this.proto.color; return this.proto.color
} }
get emoji(): string | undefined { get emoji(): string | undefined {
return this.proto.emoji; return this.proto.emoji
} }
} }

View File

@ -1,10 +1,10 @@
import { expect } from "chai"; import { expect } from 'chai'
import { import {
AudioMessage_AudioType, AudioMessage_AudioType,
ChatMessage_ContentType, ChatMessage_ContentType,
} from "../proto/communities/v1/chat_message"; } from '../proto/communities/v1/chat_message'
import { ImageType } from "../proto/communities/v1/enums"; import { ImageType } from '../proto/communities/v1/enums'
import { import {
AudioContent, AudioContent,
@ -12,67 +12,67 @@ import {
ContentType, ContentType,
ImageContent, ImageContent,
StickerContent, StickerContent,
} from "./chat_message"; } from './chat_message'
describe("Chat Message", () => { describe('Chat Message', () => {
it("Encode & decode Image message", () => { it('Encode & decode Image message', () => {
const payload = Buffer.from([1, 1]); const payload = Buffer.from([1, 1])
const imageContent: ImageContent = { const imageContent: ImageContent = {
image: payload, image: payload,
imageType: ImageType.IMAGE_TYPE_PNG, imageType: ImageType.IMAGE_TYPE_PNG,
contentType: ContentType.Image, contentType: ContentType.Image,
}; }
const message = ChatMessage.createMessage(1, 1, "chat-id", imageContent); const message = ChatMessage.createMessage(1, 1, 'chat-id', imageContent)
const buf = message.encode(); const buf = message.encode()
const dec = ChatMessage.decode(buf); const dec = ChatMessage.decode(buf)
expect(dec.contentType).eq(ChatMessage_ContentType.CONTENT_TYPE_IMAGE); expect(dec.contentType).eq(ChatMessage_ContentType.CONTENT_TYPE_IMAGE)
expect(dec.image?.payload?.toString()).eq(payload.toString()); expect(dec.image?.payload?.toString()).eq(payload.toString())
expect(dec.image?.type).eq(ImageType.IMAGE_TYPE_PNG); expect(dec.image?.type).eq(ImageType.IMAGE_TYPE_PNG)
}); })
it("Encode & decode Audio message", () => { it('Encode & decode Audio message', () => {
const payload = Buffer.from([1, 1]); const payload = Buffer.from([1, 1])
const durationMs = 12345; const durationMs = 12345
const audioContent: AudioContent = { const audioContent: AudioContent = {
audio: payload, audio: payload,
audioType: AudioMessage_AudioType.AUDIO_TYPE_AAC, audioType: AudioMessage_AudioType.AUDIO_TYPE_AAC,
durationMs, durationMs,
contentType: ContentType.Audio, contentType: ContentType.Audio,
}; }
const message = ChatMessage.createMessage(1, 1, "chat-id", audioContent); const message = ChatMessage.createMessage(1, 1, 'chat-id', audioContent)
const buf = message.encode(); const buf = message.encode()
const dec = ChatMessage.decode(buf); const dec = ChatMessage.decode(buf)
expect(dec.contentType).eq(ChatMessage_ContentType.CONTENT_TYPE_AUDIO); expect(dec.contentType).eq(ChatMessage_ContentType.CONTENT_TYPE_AUDIO)
expect(dec.audio?.payload?.toString()).eq(payload.toString()); expect(dec.audio?.payload?.toString()).eq(payload.toString())
expect(dec.audio?.type).eq(ImageType.IMAGE_TYPE_PNG); expect(dec.audio?.type).eq(ImageType.IMAGE_TYPE_PNG)
expect(dec.audio?.durationMs).eq(durationMs); expect(dec.audio?.durationMs).eq(durationMs)
}); })
it("Encode & decode Sticker message", () => { it('Encode & decode Sticker message', () => {
const hash = "deadbeef"; const hash = 'deadbeef'
const pack = 12345; const pack = 12345
const stickerContent: StickerContent = { const stickerContent: StickerContent = {
hash, hash,
pack, pack,
contentType: ContentType.Sticker, contentType: ContentType.Sticker,
}; }
const message = ChatMessage.createMessage(1, 1, "chat-id", stickerContent); const message = ChatMessage.createMessage(1, 1, 'chat-id', stickerContent)
const buf = message.encode(); const buf = message.encode()
const dec = ChatMessage.decode(buf); const dec = ChatMessage.decode(buf)
expect(dec.contentType).eq(ChatMessage_ContentType.CONTENT_TYPE_STICKER); expect(dec.contentType).eq(ChatMessage_ContentType.CONTENT_TYPE_STICKER)
expect(dec.sticker?.hash).eq(hash); expect(dec.sticker?.hash).eq(hash)
expect(dec.sticker?.pack).eq(pack); expect(dec.sticker?.pack).eq(pack)
}); })
}); })

View File

@ -1,20 +1,16 @@
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import * as proto from "../proto/communities/v1/chat_message"; import * as proto from '../proto/communities/v1/chat_message'
import { import {
AudioMessage, AudioMessage,
AudioMessage_AudioType, AudioMessage_AudioType,
ChatMessage_ContentType, ChatMessage_ContentType,
ImageMessage, ImageMessage,
StickerMessage, StickerMessage,
} from "../proto/communities/v1/chat_message"; } from '../proto/communities/v1/chat_message'
import { ImageType, MessageType } from "../proto/communities/v1/enums"; import { ImageType, MessageType } from '../proto/communities/v1/enums'
export type Content = export type Content = TextContent | StickerContent | ImageContent | AudioContent
| TextContent
| StickerContent
| ImageContent
| AudioContent;
export enum ContentType { export enum ContentType {
Text, Text,
@ -24,43 +20,43 @@ export enum ContentType {
} }
export interface TextContent { export interface TextContent {
text: string; text: string
contentType: ContentType.Text; contentType: ContentType.Text
} }
export interface StickerContent { export interface StickerContent {
hash: string; hash: string
pack: number; pack: number
contentType: ContentType.Sticker; contentType: ContentType.Sticker
} }
export interface ImageContent { export interface ImageContent {
image: Uint8Array; image: Uint8Array
imageType: ImageType; imageType: ImageType
contentType: ContentType.Image; contentType: ContentType.Image
} }
export interface AudioContent { export interface AudioContent {
audio: Uint8Array; audio: Uint8Array
audioType: AudioMessage_AudioType; audioType: AudioMessage_AudioType
durationMs: number; durationMs: number
contentType: ContentType.Audio; contentType: ContentType.Audio
} }
function isText(content: Content): content is TextContent { function isText(content: Content): content is TextContent {
return content.contentType === ContentType.Text; return content.contentType === ContentType.Text
} }
function isSticker(content: Content): content is StickerContent { function isSticker(content: Content): content is StickerContent {
return content.contentType === ContentType.Sticker; return content.contentType === ContentType.Sticker
} }
function isImage(content: Content): content is ImageContent { function isImage(content: Content): content is ImageContent {
return content.contentType === ContentType.Image; return content.contentType === ContentType.Image
} }
function isAudio(content: Content): content is AudioContent { function isAudio(content: Content): content is AudioContent {
return content.contentType === ContentType.Audio; return content.contentType === ContentType.Audio
} }
export class ChatMessage { export class ChatMessage {
@ -81,36 +77,36 @@ export class ChatMessage {
let sticker, let sticker,
image, image,
audio, audio,
text = "Upgrade to the latest version to see this media content."; text = 'Upgrade to the latest version to see this media content.'
let contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN; let contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN
if (isText(content)) { if (isText(content)) {
if (!content.text) throw "Malformed Text Content"; if (!content.text) throw 'Malformed Text Content'
text = content.text; text = content.text
contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN; contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN
} else if (isSticker(content)) { } else if (isSticker(content)) {
if (!content.hash || !content.pack) throw "Malformed Sticker Content"; if (!content.hash || !content.pack) throw 'Malformed Sticker Content'
sticker = { sticker = {
hash: content.hash, hash: content.hash,
pack: content.pack, pack: content.pack,
}; }
contentType = ChatMessage_ContentType.CONTENT_TYPE_STICKER; contentType = ChatMessage_ContentType.CONTENT_TYPE_STICKER
} else if (isImage(content)) { } else if (isImage(content)) {
if (!content.image || !content.imageType) throw "Malformed Image Content"; if (!content.image || !content.imageType) throw 'Malformed Image Content'
image = { image = {
payload: content.image, payload: content.image,
type: content.imageType, type: content.imageType,
}; }
contentType = ChatMessage_ContentType.CONTENT_TYPE_IMAGE; contentType = ChatMessage_ContentType.CONTENT_TYPE_IMAGE
} else if (isAudio(content)) { } else if (isAudio(content)) {
if (!content.audio || !content.audioType || !content.durationMs) if (!content.audio || !content.audioType || !content.durationMs)
throw "Malformed Audio Content"; throw 'Malformed Audio Content'
audio = { audio = {
payload: content.audio, payload: content.audio,
type: content.audioType, type: content.audioType,
durationMs: content.durationMs, durationMs: content.durationMs,
}; }
contentType = ChatMessage_ContentType.CONTENT_TYPE_AUDIO; contentType = ChatMessage_ContentType.CONTENT_TYPE_AUDIO
} }
const proto = { const proto = {
@ -118,9 +114,9 @@ export class ChatMessage {
timestamp, //ms? timestamp, //ms?
text, text,
/** Id of the message that we are replying to */ /** Id of the message that we are replying to */
responseTo: responseTo ?? "", responseTo: responseTo ?? '',
/** Ens name of the sender */ /** Ens name of the sender */
ensName: "", ensName: '',
/** Public Key of the community (TBC) **/ /** Public Key of the community (TBC) **/
chatId, chatId,
/** The type of message (public/one-to-one/private-group-chat) */ /** The type of message (public/one-to-one/private-group-chat) */
@ -132,24 +128,24 @@ export class ChatMessage {
audio, audio,
community: undefined, // Used to share a community community: undefined, // Used to share a community
grant: undefined, grant: undefined,
}; }
return new ChatMessage(proto); return new ChatMessage(proto)
} }
static decode(bytes: Uint8Array): ChatMessage { static decode(bytes: Uint8Array): ChatMessage {
const protoBuf = proto.ChatMessage.decode(Reader.create(bytes)); const protoBuf = proto.ChatMessage.decode(Reader.create(bytes))
return new ChatMessage(protoBuf); return new ChatMessage(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.ChatMessage.encode(this.proto).finish(); return proto.ChatMessage.encode(this.proto).finish()
} }
/** Lamport timestamp of the chat message */ /** Lamport timestamp of the chat message */
public get clock(): number | undefined { public get clock(): number | undefined {
return this.proto.clock; return this.proto.clock
} }
/** /**
@ -157,28 +153,28 @@ export class ChatMessage {
* so that we don't rely on it * so that we don't rely on it
*/ */
public get timestamp(): number | undefined { public get timestamp(): number | undefined {
return this.proto.timestamp; return this.proto.timestamp
} }
/** /**
* Text of the message * Text of the message
*/ */
public get text(): string | undefined { public get text(): string | undefined {
return this.proto.text; return this.proto.text
} }
/** /**
* Id of the message that we are replying to * Id of the message that we are replying to
*/ */
public get responseTo(): string | undefined { public get responseTo(): string | undefined {
return this.proto.responseTo; return this.proto.responseTo
} }
/** /**
* Ens name of the sender * Ens name of the sender
*/ */
public get ensName(): string | undefined { public get ensName(): string | undefined {
return this.proto.ensName; return this.proto.ensName
} }
/** /**
@ -188,39 +184,39 @@ export class ChatMessage {
* Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order * Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order
*/ */
public get chatId(): string { public get chatId(): string {
return this.proto.chatId; return this.proto.chatId
} }
/** /**
* The type of message (public/one-to-one/private-group-chat) * The type of message (public/one-to-one/private-group-chat)
*/ */
public get messageType(): MessageType | undefined { public get messageType(): MessageType | undefined {
return this.proto.messageType; return this.proto.messageType
} }
/** /**
* The type of the content of the message * The type of the content of the message
*/ */
public get contentType(): ChatMessage_ContentType | undefined { public get contentType(): ChatMessage_ContentType | undefined {
return this.proto.contentType; return this.proto.contentType
} }
public get sticker(): StickerMessage | undefined { public get sticker(): StickerMessage | undefined {
return this.proto.sticker; return this.proto.sticker
} }
public get image(): ImageMessage | undefined { public get image(): ImageMessage | undefined {
return this.proto.image; return this.proto.image
} }
public get audio(): AudioMessage | undefined { public get audio(): AudioMessage | undefined {
return this.proto.audio; return this.proto.audio
} }
/** /**
* Used when sharing a community via a chat message. * Used when sharing a community via a chat message.
*/ */
public get community(): Uint8Array | undefined { public get community(): Uint8Array | undefined {
return this.proto.community; return this.proto.community
} }
} }

View File

@ -1,12 +1,12 @@
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import * as proto from "../proto/communities/v1/communities"; import * as proto from '../proto/communities/v1/communities'
import { import {
CommunityMember, CommunityMember,
CommunityPermissions, CommunityPermissions,
} from "../proto/communities/v1/communities"; } from '../proto/communities/v1/communities'
import { ChatIdentity } from "./chat_identity"; import { ChatIdentity } from './chat_identity'
export class CommunityChat { export class CommunityChat {
public constructor(public proto: proto.CommunityChat) {} public constructor(public proto: proto.CommunityChat) {}
@ -17,43 +17,43 @@ export class CommunityChat {
* @throws * @throws
*/ */
static decode(bytes: Uint8Array): CommunityChat { static decode(bytes: Uint8Array): CommunityChat {
const protoBuf = proto.CommunityChat.decode(Reader.create(bytes)); const protoBuf = proto.CommunityChat.decode(Reader.create(bytes))
return new CommunityChat(protoBuf); return new CommunityChat(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.CommunityChat.encode(this.proto).finish(); return proto.CommunityChat.encode(this.proto).finish()
} }
// TODO: check and document what is the key of the returned Map; // TODO: check and document what is the key of the returned Map;
public get members(): Map<string, CommunityMember> { public get members(): Map<string, CommunityMember> {
const map = new Map(); const map = new Map()
for (const key of Object.keys(this.proto.members)) { for (const key of Object.keys(this.proto.members)) {
map.set(key, this.proto.members[key]); map.set(key, this.proto.members[key])
} }
return map; return map
} }
public get permissions(): CommunityPermissions | undefined { public get permissions(): CommunityPermissions | undefined {
return this.proto.permissions; return this.proto.permissions
} }
public get identity(): ChatIdentity | undefined { public get identity(): ChatIdentity | undefined {
if (!this.proto.identity) return; if (!this.proto.identity) return
return new ChatIdentity(this.proto.identity); return new ChatIdentity(this.proto.identity)
} }
// TODO: Document this // TODO: Document this
public get categoryId(): string | undefined { public get categoryId(): string | undefined {
return this.proto.categoryId; return this.proto.categoryId
} }
// TODO: Document this // TODO: Document this
public get position(): number | undefined { public get position(): number | undefined {
return this.proto.position; return this.proto.position
} }
} }

View File

@ -1,29 +1,29 @@
import debug from "debug"; import debug from 'debug'
import { WakuMessage, WakuStore } from "js-waku"; import { WakuMessage, WakuStore } from 'js-waku'
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import { idToContentTopic } from "../contentTopic"; import { idToContentTopic } from '../contentTopic'
import { createSymKeyFromPassword } from "../encryption"; import { createSymKeyFromPassword } from '../encryption'
import * as proto from "../proto/communities/v1/communities"; import * as proto from '../proto/communities/v1/communities'
import { bufToHex } from "../utils"; import { bufToHex } from '../utils'
import { ApplicationMetadataMessage } from "./application_metadata_message"; import { ApplicationMetadataMessage } from './application_metadata_message'
import { ChatIdentity } from "./chat_identity"; import { ChatIdentity } from './chat_identity'
import { CommunityChat } from "./community_chat"; import { CommunityChat } from './community_chat'
const dbg = debug("communities:wire:community_description"); const dbg = debug('communities:wire:community_description')
export class CommunityDescription { export class CommunityDescription {
private constructor(public proto: proto.CommunityDescription) {} private constructor(public proto: proto.CommunityDescription) {}
static decode(bytes: Uint8Array): CommunityDescription { static decode(bytes: Uint8Array): CommunityDescription {
const protoBuf = proto.CommunityDescription.decode(Reader.create(bytes)); const protoBuf = proto.CommunityDescription.decode(Reader.create(bytes))
return new CommunityDescription(protoBuf); return new CommunityDescription(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.CommunityDescription.encode(this.proto).finish(); return proto.CommunityDescription.encode(this.proto).finish()
} }
/** /**
@ -33,69 +33,69 @@ export class CommunityDescription {
communityPublicKey: Uint8Array, communityPublicKey: Uint8Array,
wakuStore: WakuStore wakuStore: WakuStore
): Promise<CommunityDescription | undefined> { ): Promise<CommunityDescription | undefined> {
const hexCommunityPublicKey = bufToHex(communityPublicKey); const hexCommunityPublicKey = bufToHex(communityPublicKey)
const contentTopic = idToContentTopic(hexCommunityPublicKey); const contentTopic = idToContentTopic(hexCommunityPublicKey)
let communityDescription: CommunityDescription | undefined; let communityDescription: CommunityDescription | undefined
const callback = (messages: WakuMessage[]): void => { const callback = (messages: WakuMessage[]): void => {
// Value found, stop processing // Value found, stop processing
if (communityDescription) return; if (communityDescription) return
// Process most recent message first // Process most recent message first
const orderedMessages = messages.reverse(); const orderedMessages = messages.reverse()
orderedMessages.forEach((message: WakuMessage) => { orderedMessages.forEach((message: WakuMessage) => {
if (!message.payload) return; if (!message.payload) return
try { try {
const metadata = ApplicationMetadataMessage.decode(message.payload); const metadata = ApplicationMetadataMessage.decode(message.payload)
if (!metadata.payload) return; if (!metadata.payload) return
const _communityDescription = CommunityDescription.decode( const _communityDescription = CommunityDescription.decode(
metadata.payload metadata.payload
); )
if (!_communityDescription.identity) return; if (!_communityDescription.identity) return
communityDescription = _communityDescription; communityDescription = _communityDescription
} catch (e) { } catch (e) {
dbg( dbg(
`Failed to decode message as CommunityDescription found on content topic ${contentTopic}`, `Failed to decode message as CommunityDescription found on content topic ${contentTopic}`,
e e
); )
} }
}); })
}; }
const symKey = await createSymKeyFromPassword(hexCommunityPublicKey); const symKey = await createSymKeyFromPassword(hexCommunityPublicKey)
await wakuStore await wakuStore
.queryHistory([contentTopic], { .queryHistory([contentTopic], {
callback, callback,
decryptionKeys: [symKey], decryptionKeys: [symKey],
}) })
.catch((e) => { .catch(e => {
dbg( dbg(
`Failed to retrieve community description for ${hexCommunityPublicKey}`, `Failed to retrieve community description for ${hexCommunityPublicKey}`,
e e
); )
}); })
return communityDescription; return communityDescription
} }
get identity(): ChatIdentity | undefined { get identity(): ChatIdentity | undefined {
if (!this.proto.identity) return; if (!this.proto.identity) return
return new ChatIdentity(this.proto.identity); return new ChatIdentity(this.proto.identity)
} }
get chats(): Map<string, CommunityChat> { get chats(): Map<string, CommunityChat> {
const map = new Map(); const map = new Map()
for (const key of Object.keys(this.proto.chats)) { for (const key of Object.keys(this.proto.chats)) {
map.set(key, this.proto.chats[key]); map.set(key, this.proto.chats[key])
} }
return map; return map
} }
} }

View File

@ -1,73 +1,73 @@
import { keccak256 } from "js-sha3"; import { keccak256 } from 'js-sha3'
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import * as secp256k1 from "secp256k1"; import * as secp256k1 from 'secp256k1'
import { v4 as uuidV4 } from "uuid"; import { v4 as uuidV4 } from 'uuid'
import { Identity } from ".."; import { Identity } from '..'
import * as proto from "../proto/communities/v1/membership_update_message"; import * as proto from '../proto/communities/v1/membership_update_message'
import { bufToHex, hexToBuf } from "../utils"; import { bufToHex, hexToBuf } from '../utils'
export class MembershipUpdateEvent { export class MembershipUpdateEvent {
public constructor(public proto: proto.MembershipUpdateEvent) {} public constructor(public proto: proto.MembershipUpdateEvent) {}
static decode(bytes: Uint8Array): MembershipUpdateEvent { static decode(bytes: Uint8Array): MembershipUpdateEvent {
const protoBuf = proto.MembershipUpdateEvent.decode(Reader.create(bytes)); const protoBuf = proto.MembershipUpdateEvent.decode(Reader.create(bytes))
return new MembershipUpdateEvent(protoBuf); return new MembershipUpdateEvent(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.MembershipUpdateEvent.encode(this.proto).finish(); return proto.MembershipUpdateEvent.encode(this.proto).finish()
} }
public get members(): string[] { public get members(): string[] {
return this.proto.members; return this.proto.members
} }
public get name(): string { public get name(): string {
return this.proto.name; return this.proto.name
} }
public get clock(): number { public get clock(): number {
return this.proto.clock; return this.proto.clock
} }
public get type(): proto.MembershipUpdateEvent_EventType { public get type(): proto.MembershipUpdateEvent_EventType {
return this.proto.type; return this.proto.type
} }
} }
export class MembershipSignedEvent { export class MembershipSignedEvent {
public sig: Uint8Array; public sig: Uint8Array
public event: MembershipUpdateEvent; public event: MembershipUpdateEvent
private chatId: string; private chatId: string
public constructor( public constructor(
sig: Uint8Array, sig: Uint8Array,
event: MembershipUpdateEvent, event: MembershipUpdateEvent,
chatId: string chatId: string
) { ) {
this.sig = sig; this.sig = sig
this.event = event; this.event = event
this.chatId = chatId; this.chatId = chatId
} }
public get signer(): Uint8Array | undefined { public get signer(): Uint8Array | undefined {
const encEvent = this.event.encode(); const encEvent = this.event.encode()
const eventToSign = Buffer.concat([hexToBuf(this.chatId), encEvent]); const eventToSign = Buffer.concat([hexToBuf(this.chatId), encEvent])
if (!this.sig || !eventToSign) return; if (!this.sig || !eventToSign) return
const signature = this.sig.slice(0, 64); const signature = this.sig.slice(0, 64)
const recid = this.sig.slice(64)[0]; const recid = this.sig.slice(64)[0]
const hash = keccak256(eventToSign); const hash = keccak256(eventToSign)
return secp256k1.ecdsaRecover(signature, recid, hexToBuf(hash)); return secp256k1.ecdsaRecover(signature, recid, hexToBuf(hash))
} }
} }
export class MembershipUpdateMessage { export class MembershipUpdateMessage {
private clock: number = Date.now(); private clock: number = Date.now()
private identity: Identity = Identity.generate(); private identity: Identity = Identity.generate()
public constructor(public proto: proto.MembershipUpdateMessage) {} public constructor(public proto: proto.MembershipUpdateMessage) {}
public static create( public static create(
@ -77,18 +77,18 @@ export class MembershipUpdateMessage {
const partial = proto.MembershipUpdateMessage.fromPartial({ const partial = proto.MembershipUpdateMessage.fromPartial({
chatId, chatId,
events: [], events: [],
}); })
const newMessage = new MembershipUpdateMessage(partial); const newMessage = new MembershipUpdateMessage(partial)
newMessage.clock = Date.now(); newMessage.clock = Date.now()
newMessage.identity = identity; newMessage.identity = identity
return newMessage; return newMessage
} }
private addEvent(event: MembershipUpdateEvent): void { private addEvent(event: MembershipUpdateEvent): void {
const encEvent = event.encode(); const encEvent = event.encode()
const eventToSign = Buffer.concat([hexToBuf(this.proto.chatId), encEvent]); const eventToSign = Buffer.concat([hexToBuf(this.proto.chatId), encEvent])
const signature = this.identity.sign(eventToSign); const signature = this.identity.sign(eventToSign)
this.proto.events.push(Buffer.concat([signature, encEvent])); this.proto.events.push(Buffer.concat([signature, encEvent]))
} }
public static createChat( public static createChat(
@ -96,106 +96,106 @@ export class MembershipUpdateMessage {
members: string[], members: string[],
name?: string name?: string
): MembershipUpdateMessage { ): MembershipUpdateMessage {
const chatId = `${uuidV4()}-${bufToHex(identity.publicKey)}`; const chatId = `${uuidV4()}-${bufToHex(identity.publicKey)}`
const message = this.create(chatId, identity); const message = this.create(chatId, identity)
const type = proto.MembershipUpdateEvent_EventType.CHAT_CREATED; const type = proto.MembershipUpdateEvent_EventType.CHAT_CREATED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: message.clock, clock: message.clock,
members, members,
name: name ?? "", name: name ?? '',
type, type,
}); })
message.addEvent(event); message.addEvent(event)
return message; return message
} }
public addNameChangeEvent(name: string): void { public addNameChangeEvent(name: string): void {
const type = proto.MembershipUpdateEvent_EventType.NAME_CHANGED; const type = proto.MembershipUpdateEvent_EventType.NAME_CHANGED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: this.clock, clock: this.clock,
members: [], members: [],
name: name, name: name,
type, type,
}); })
this.addEvent(event); this.addEvent(event)
} }
public addMembersAddedEvent(members: string[]): void { public addMembersAddedEvent(members: string[]): void {
const type = proto.MembershipUpdateEvent_EventType.MEMBERS_ADDED; const type = proto.MembershipUpdateEvent_EventType.MEMBERS_ADDED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: this.clock, clock: this.clock,
members, members,
name: "", name: '',
type, type,
}); })
this.addEvent(event); this.addEvent(event)
} }
public addMemberJoinedEvent(member: string): void { public addMemberJoinedEvent(member: string): void {
const type = proto.MembershipUpdateEvent_EventType.MEMBER_JOINED; const type = proto.MembershipUpdateEvent_EventType.MEMBER_JOINED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: this.clock, clock: this.clock,
members: [member], members: [member],
name: "", name: '',
type, type,
}); })
this.addEvent(event); this.addEvent(event)
} }
public addMemberRemovedEvent(member: string): void { public addMemberRemovedEvent(member: string): void {
const type = proto.MembershipUpdateEvent_EventType.MEMBER_REMOVED; const type = proto.MembershipUpdateEvent_EventType.MEMBER_REMOVED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: this.clock, clock: this.clock,
members: [member], members: [member],
name: "", name: '',
type, type,
}); })
this.addEvent(event); this.addEvent(event)
} }
public addAdminsAddedEvent(members: string[]): void { public addAdminsAddedEvent(members: string[]): void {
const type = proto.MembershipUpdateEvent_EventType.ADMINS_ADDED; const type = proto.MembershipUpdateEvent_EventType.ADMINS_ADDED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: this.clock, clock: this.clock,
members, members,
name: "", name: '',
type, type,
}); })
this.addEvent(event); this.addEvent(event)
} }
public addAdminRemovedEvent(member: string): void { public addAdminRemovedEvent(member: string): void {
const type = proto.MembershipUpdateEvent_EventType.ADMINS_ADDED; const type = proto.MembershipUpdateEvent_EventType.ADMINS_ADDED
const event = new MembershipUpdateEvent({ const event = new MembershipUpdateEvent({
clock: this.clock, clock: this.clock,
members: [member], members: [member],
name: "", name: '',
type, type,
}); })
this.addEvent(event); this.addEvent(event)
} }
static decode(bytes: Uint8Array): MembershipUpdateMessage { static decode(bytes: Uint8Array): MembershipUpdateMessage {
const protoBuf = proto.MembershipUpdateMessage.decode(Reader.create(bytes)); const protoBuf = proto.MembershipUpdateMessage.decode(Reader.create(bytes))
return new MembershipUpdateMessage(protoBuf); return new MembershipUpdateMessage(protoBuf)
} }
public get events(): MembershipSignedEvent[] { public get events(): MembershipSignedEvent[] {
return this.proto.events.map((bufArray) => { return this.proto.events.map(bufArray => {
return new MembershipSignedEvent( return new MembershipSignedEvent(
bufArray.slice(0, 65), bufArray.slice(0, 65),
MembershipUpdateEvent.decode(bufArray.slice(65)), MembershipUpdateEvent.decode(bufArray.slice(65)),
this.chatId this.chatId
); )
}); })
} }
public get chatId(): string { public get chatId(): string {
return this.proto.chatId; return this.proto.chatId
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.MembershipUpdateMessage.encode(this.proto).finish(); return proto.MembershipUpdateMessage.encode(this.proto).finish()
} }
} }

View File

@ -1,6 +1,6 @@
import { Reader } from "protobufjs"; import { Reader } from 'protobufjs'
import * as proto from "../proto/communities/v1/status_update"; import * as proto from '../proto/communities/v1/status_update'
export class StatusUpdate { export class StatusUpdate {
public constructor(public proto: proto.StatusUpdate) {} public constructor(public proto: proto.StatusUpdate) {}
@ -9,15 +9,15 @@ export class StatusUpdate {
statusType: proto.StatusUpdate_StatusType, statusType: proto.StatusUpdate_StatusType,
customText: string customText: string
): StatusUpdate { ): StatusUpdate {
const clock = Date.now(); const clock = Date.now()
const proto = { const proto = {
clock, clock,
statusType, statusType,
customText, customText,
}; }
return new StatusUpdate(proto); return new StatusUpdate(proto)
} }
/** /**
@ -26,24 +26,24 @@ export class StatusUpdate {
* @throws * @throws
*/ */
static decode(bytes: Uint8Array): StatusUpdate { static decode(bytes: Uint8Array): StatusUpdate {
const protoBuf = proto.StatusUpdate.decode(Reader.create(bytes)); const protoBuf = proto.StatusUpdate.decode(Reader.create(bytes))
return new StatusUpdate(protoBuf); return new StatusUpdate(protoBuf)
} }
encode(): Uint8Array { encode(): Uint8Array {
return proto.StatusUpdate.encode(this.proto).finish(); return proto.StatusUpdate.encode(this.proto).finish()
} }
public get clock(): number | undefined { public get clock(): number | undefined {
return this.proto.clock; return this.proto.clock
} }
public get statusType(): proto.StatusUpdate_StatusType | undefined { public get statusType(): proto.StatusUpdate_StatusType | undefined {
return this.proto.statusType; return this.proto.statusType
} }
public get customText(): string | undefined { public get customText(): string | undefined {
return this.proto.customText; return this.proto.customText
} }
} }

View File

@ -19,11 +19,9 @@
"build:esm": "tsc --module es2020 --target es2017 --outDir dist/esm", "build:esm": "tsc --module es2020 --target es2017 --outDir dist/esm",
"build:cjs": "tsc --outDir dist/cjs", "build:cjs": "tsc --outDir dist/cjs",
"fix": "run-s 'fix:*'", "fix": "run-s 'fix:*'",
"fix:prettier": "prettier './{src,test}/**/*.{ts,tsx}' \"./*.json\" --write",
"fix:lint": "eslint './{src,test}/**/*.{ts,tsx}' --fix", "fix:lint": "eslint './{src,test}/**/*.{ts,tsx}' --fix",
"test": "run-s 'test:*'", "test": "run-s 'test:*'",
"test:lint": "eslint './{src,test}/**/*.{ts,tsx}'", "test:lint": "eslint './{src,test}/**/*.{ts,tsx}'",
"test:prettier": "prettier './{src,test}/**/*.{ts,tsx}' \"./*.json\" --list-different",
"proto": "run-s 'proto:*'", "proto": "run-s 'proto:*'",
"proto:lint": "buf lint", "proto:lint": "buf lint",
"proto:build": "buf generate" "proto:build": "buf generate"
@ -49,7 +47,6 @@
"mocha": "^9.0.3", "mocha": "^9.0.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"npm-watch": "^0.11.0", "npm-watch": "^0.11.0",
"prettier": "^2.3.2",
"qrcode.react": "^1.0.1", "qrcode.react": "^1.0.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"ts-node": "^10.1.0", "ts-node": "^10.1.0",

View File

@ -1,30 +1,30 @@
import React, { useMemo, useRef, useState } from "react"; import React, { useMemo, useRef, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useIdentity } from "../../contexts/identityProvider"; import { useIdentity } from '../../contexts/identityProvider'
import { useActivities } from "../../hooks/useActivities"; import { useActivities } from '../../hooks/useActivities'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { TopBtn } from "../Chat/ChatTopbar"; import { TopBtn } from '../Chat/ChatTopbar'
import { ActivityIcon } from "../Icons/ActivityIcon"; import { ActivityIcon } from '../Icons/ActivityIcon'
import { ActivityCenter } from "./ActivityCenter"; import { ActivityCenter } from './ActivityCenter'
interface ActivityButtonProps { interface ActivityButtonProps {
className?: string; className?: string
} }
export function ActivityButton({ className }: ActivityButtonProps) { export function ActivityButton({ className }: ActivityButtonProps) {
const { activities, activityDispatch } = useActivities(); const { activities, activityDispatch } = useActivities()
const identity = useIdentity(); const identity = useIdentity()
const disabled = useMemo(() => !identity, [identity]); const disabled = useMemo(() => !identity, [identity])
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowActivityCenter(false)); useClickOutside(ref, () => setShowActivityCenter(false))
const [showActivityCenter, setShowActivityCenter] = useState(false); const [showActivityCenter, setShowActivityCenter] = useState(false)
const badgeAmount = useMemo( const badgeAmount = useMemo(
() => activities.filter((activity) => !activity.isRead).length, () => activities.filter(activity => !activity.isRead).length,
[activities] [activities]
); )
return ( return (
<ActivityWrapper ref={ref} className={className}> <ActivityWrapper ref={ref} className={className}>
@ -37,13 +37,13 @@ export function ActivityButton({ className }: ActivityButtonProps) {
<NotificationBagde <NotificationBagde
className={ className={
badgeAmount > 99 badgeAmount > 99
? "countless" ? 'countless'
: badgeAmount > 9 : badgeAmount > 9
? "wide" ? 'wide'
: undefined : undefined
} }
> >
{badgeAmount < 100 ? badgeAmount : "∞"} {badgeAmount < 100 ? badgeAmount : '∞'}
</NotificationBagde> </NotificationBagde>
)} )}
</TopBtn> </TopBtn>
@ -55,7 +55,7 @@ export function ActivityButton({ className }: ActivityButtonProps) {
/> />
)} )}
</ActivityWrapper> </ActivityWrapper>
); )
} }
export const ActivityWrapper = styled.div` export const ActivityWrapper = styled.div`
@ -64,7 +64,7 @@ export const ActivityWrapper = styled.div`
position: relative; position: relative;
&:before { &:before {
content: ""; content: '';
position: absolute; position: absolute;
left: 0; left: 0;
top: 50%; top: 50%;
@ -85,7 +85,7 @@ export const ActivityWrapper = styled.div`
height: 0px; height: 0px;
} }
} }
`; `
const NotificationBagde = styled.div` const NotificationBagde = styled.div`
width: 18px; width: 18px;
@ -113,4 +113,4 @@ const NotificationBagde = styled.div`
&.countless { &.countless {
width: 22px; width: 22px;
} }
`; `

View File

@ -1,21 +1,21 @@
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { ActivityAction } from "../../hooks/useActivities"; import { ActivityAction } from '../../hooks/useActivities'
import { Activity } from "../../models/Activity"; import { Activity } from '../../models/Activity'
import { buttonTransparentStyles } from "../Buttons/buttonStyle"; import { buttonTransparentStyles } from '../Buttons/buttonStyle'
import { Tooltip } from "../Form/Tooltip"; import { Tooltip } from '../Form/Tooltip'
import { HideIcon } from "../Icons/HideIcon"; import { HideIcon } from '../Icons/HideIcon'
import { ReadIcon } from "../Icons/ReadIcon"; import { ReadIcon } from '../Icons/ReadIcon'
import { ShowIcon } from "../Icons/ShowIcon"; import { ShowIcon } from '../Icons/ShowIcon'
import { ActivityMessage } from "./ActivityMessage"; import { ActivityMessage } from './ActivityMessage'
interface ActivityCenterProps { interface ActivityCenterProps {
activities: Activity[]; activities: Activity[]
setShowActivityCenter: (val: boolean) => void; setShowActivityCenter: (val: boolean) => void
activityDispatch: React.Dispatch<ActivityAction>; activityDispatch: React.Dispatch<ActivityAction>
} }
export function ActivityCenter({ export function ActivityCenter({
@ -23,43 +23,43 @@ export function ActivityCenter({
setShowActivityCenter, setShowActivityCenter,
activityDispatch, activityDispatch,
}: ActivityCenterProps) { }: ActivityCenterProps) {
const { contacts } = useMessengerContext(); const { contacts } = useMessengerContext()
const shownActivities = useMemo( const shownActivities = useMemo(
() => () =>
activities.filter( activities.filter(
(activity) => !contacts?.[activity.user]?.blocked ?? true activity => !contacts?.[activity.user]?.blocked ?? true
), ),
[contacts, activities] [contacts, activities]
); )
const [hideRead, setHideRead] = useState(false); const [hideRead, setHideRead] = useState(false)
const [filter, setFilter] = useState(""); const [filter, setFilter] = useState('')
const filteredActivities = shownActivities.filter((activity) => const filteredActivities = shownActivities.filter(activity =>
filter filter
? activity.type === filter ? activity.type === filter
: hideRead : hideRead
? activity.isRead !== true ? activity.isRead !== true
: activity : activity
); )
return ( return (
<ActivityBlock> <ActivityBlock>
<ActivityFilter> <ActivityFilter>
<FlexDiv> <FlexDiv>
<FilterBtn onClick={() => setFilter("")}>All</FilterBtn> <FilterBtn onClick={() => setFilter('')}>All</FilterBtn>
<FilterBtn onClick={() => setFilter("mention")}>Mentions</FilterBtn> <FilterBtn onClick={() => setFilter('mention')}>Mentions</FilterBtn>
<FilterBtn onClick={() => setFilter("reply")}>Replies</FilterBtn> <FilterBtn onClick={() => setFilter('reply')}>Replies</FilterBtn>
<FilterBtn onClick={() => setFilter("request")}> <FilterBtn onClick={() => setFilter('request')}>
Contact requests Contact requests
</FilterBtn> </FilterBtn>
</FlexDiv> </FlexDiv>
<Btns> <Btns>
<BtnWrapper> <BtnWrapper>
<ActivityBtn <ActivityBtn
onClick={() => activityDispatch({ type: "setAllAsRead" })} onClick={() => activityDispatch({ type: 'setAllAsRead' })}
> >
<ReadIcon /> <ReadIcon />
</ActivityBtn> </ActivityBtn>
@ -69,13 +69,13 @@ export function ActivityCenter({
<ActivityBtn onClick={() => setHideRead(!hideRead)}> <ActivityBtn onClick={() => setHideRead(!hideRead)}>
{hideRead ? <ShowIcon /> : <HideIcon />} {hideRead ? <ShowIcon /> : <HideIcon />}
</ActivityBtn> </ActivityBtn>
<Tooltip tip={hideRead ? "Show read" : "Hide read"} /> <Tooltip tip={hideRead ? 'Show read' : 'Hide read'} />
</BtnWrapper> </BtnWrapper>
</Btns> </Btns>
</ActivityFilter> </ActivityFilter>
{filteredActivities.length > 0 ? ( {filteredActivities.length > 0 ? (
<Activities> <Activities>
{filteredActivities.map((activity) => ( {filteredActivities.map(activity => (
<ActivityMessage <ActivityMessage
key={activity.id} key={activity.id}
activity={activity} activity={activity}
@ -88,7 +88,7 @@ export function ActivityCenter({
<EmptyActivities>Notifications will appear here</EmptyActivities> <EmptyActivities>Notifications will appear here</EmptyActivities>
)} )}
</ActivityBlock> </ActivityBlock>
); )
} }
const ActivityBlock = styled.div` const ActivityBlock = styled.div`
@ -103,17 +103,17 @@ const ActivityBlock = styled.div`
top: calc(100% + 4px); top: calc(100% + 4px);
right: 0; right: 0;
z-index: 100; z-index: 100;
`; `
const ActivityFilter = styled.div` const ActivityFilter = styled.div`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 13px 16px; padding: 13px 16px;
`; `
export const FlexDiv = styled.div` export const FlexDiv = styled.div`
display: flex; display: flex;
`; `
const FilterBtn = styled.button` const FilterBtn = styled.button`
${buttonTransparentStyles} ${buttonTransparentStyles}
@ -121,7 +121,7 @@ const FilterBtn = styled.button`
& + & { & + & {
margin-left: 8px; margin-left: 8px;
} }
`; `
const BtnWrapper = styled.div` const BtnWrapper = styled.div`
position: relative; position: relative;
@ -129,7 +129,7 @@ const BtnWrapper = styled.div`
&:hover > div { &:hover > div {
visibility: visible; visibility: visible;
} }
`; `
export const ActivityBtn = styled.button` export const ActivityBtn = styled.button`
width: 32px; width: 32px;
@ -165,14 +165,14 @@ export const ActivityBtn = styled.button`
& + & { & + & {
margin-left: 8px; margin-left: 8px;
} }
`; `
const Activities = styled.div` const Activities = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
overflow: auto; overflow: auto;
`; `
const EmptyActivities = styled.div` const EmptyActivities = styled.div`
display: flex; display: flex;
@ -181,9 +181,9 @@ const EmptyActivities = styled.div`
flex: 1; flex: 1;
width: 100%; width: 100%;
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
`; `
const Btns = styled.div` const Btns = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
`; `

View File

@ -1,27 +1,27 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useEffect, useMemo, useRef, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useModal } from "../../contexts/modalProvider"; import { useModal } from '../../contexts/modalProvider'
import { useScrollToMessage } from "../../contexts/scrollProvider"; import { useScrollToMessage } from '../../contexts/scrollProvider'
import { ActivityAction } from "../../hooks/useActivities"; import { ActivityAction } from '../../hooks/useActivities'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { Activity } from "../../models/Activity"; import { Activity } from '../../models/Activity'
import { equalDate } from "../../utils/equalDate"; import { equalDate } from '../../utils/equalDate'
import { DownloadButton } from "../Buttons/DownloadButton"; import { DownloadButton } from '../Buttons/DownloadButton'
import { Mention } from "../Chat/ChatMessageContent"; import { Mention } from '../Chat/ChatMessageContent'
import { Logo } from "../CommunityIdentity"; import { Logo } from '../CommunityIdentity'
import { ContactMenu } from "../Form/ContactMenu"; import { ContactMenu } from '../Form/ContactMenu'
import { Tooltip } from "../Form/Tooltip"; import { Tooltip } from '../Form/Tooltip'
import { CheckIcon } from "../Icons/CheckIcon"; import { CheckIcon } from '../Icons/CheckIcon'
import { ClearSvg } from "../Icons/ClearIcon"; import { ClearSvg } from '../Icons/ClearIcon'
import { CommunityIcon } from "../Icons/CommunityIcon"; import { CommunityIcon } from '../Icons/CommunityIcon'
import { GroupIcon } from "../Icons/GroupIcon"; import { GroupIcon } from '../Icons/GroupIcon'
import { MoreIcon } from "../Icons/MoreIcon"; import { MoreIcon } from '../Icons/MoreIcon'
import { ReadMessageIcon } from "../Icons/ReadMessageIcon"; import { ReadMessageIcon } from '../Icons/ReadMessageIcon'
import { ReplyIcon } from "../Icons/ReplyActivityIcon"; import { ReplyIcon } from '../Icons/ReplyActivityIcon'
import { UntrustworthIcon } from "../Icons/UntrustworthIcon"; import { UntrustworthIcon } from '../Icons/UntrustworthIcon'
import { UserIcon } from "../Icons/UserIcon"; import { UserIcon } from '../Icons/UserIcon'
import { import {
ContentWrapper, ContentWrapper,
DateSeparator, DateSeparator,
@ -32,52 +32,52 @@ import {
UserAddress, UserAddress,
UserName, UserName,
UserNameWrapper, UserNameWrapper,
} from "../Messages/Styles"; } from '../Messages/Styles'
import { ProfileModalName } from "../Modals/ProfileModal"; import { ProfileModalName } from '../Modals/ProfileModal'
import { textMediumStyles, textSmallStyles } from "../Text"; import { textMediumStyles, textSmallStyles } from '../Text'
import { ActivityBtn, FlexDiv } from "./ActivityCenter"; import { ActivityBtn, FlexDiv } from './ActivityCenter'
const today = new Date(); const today = new Date()
type ActivityMessageProps = { type ActivityMessageProps = {
activity: Activity; activity: Activity
setShowActivityCenter: (val: boolean) => void; setShowActivityCenter: (val: boolean) => void
activityDispatch: React.Dispatch<ActivityAction>; activityDispatch: React.Dispatch<ActivityAction>
}; }
export function ActivityMessage({ export function ActivityMessage({
activity, activity,
setShowActivityCenter, setShowActivityCenter,
activityDispatch, activityDispatch,
}: ActivityMessageProps) { }: ActivityMessageProps) {
const { contacts, channelsDispatch } = useMessengerContext(); const { contacts, channelsDispatch } = useMessengerContext()
const scroll = useScrollToMessage(); const scroll = useScrollToMessage()
const { setModal } = useModal(ProfileModalName); const { setModal } = useModal(ProfileModalName)
const showChannel = () => { const showChannel = () => {
"channel" in activity && 'channel' in activity &&
channelsDispatch({ type: "ChangeActive", payload: activity.channel.id }), channelsDispatch({ type: 'ChangeActive', payload: activity.channel.id }),
setShowActivityCenter(false); setShowActivityCenter(false)
}; }
const [showMenu, setShowMenu] = useState(false); const [showMenu, setShowMenu] = useState(false)
const type = activity.type; const type = activity.type
const contact = useMemo( const contact = useMemo(
() => contacts[activity.user], () => contacts[activity.user],
[activity.user, contacts] [activity.user, contacts]
); )
const [elements, setElements] = useState< const [elements, setElements] = useState<
(string | React.ReactElement | undefined)[] (string | React.ReactElement | undefined)[]
>(["message" in activity ? activity.message?.content : undefined]); >(['message' in activity ? activity.message?.content : undefined])
useEffect(() => { useEffect(() => {
if ("message" in activity) { if ('message' in activity) {
const split = activity.message?.content.split(" "); const split = activity.message?.content.split(' ')
const newSplit = split.flatMap((element, idx) => { const newSplit = split.flatMap((element, idx) => {
if (element.startsWith("@")) { if (element.startsWith('@')) {
return [ return [
<Mention <Mention
key={idx} key={idx}
@ -85,28 +85,28 @@ export function ActivityMessage({
setMentioned={() => true} setMentioned={() => true}
className="activity" className="activity"
/>, />,
" ", ' ',
]; ]
} }
return [element, " "]; return [element, ' ']
}); })
newSplit.pop(); newSplit.pop()
setElements(newSplit); setElements(newSplit)
} }
}, [activity]); }, [activity])
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowMenu(false)); useClickOutside(ref, () => setShowMenu(false))
return ( return (
<MessageOuterWrapper> <MessageOuterWrapper>
<ActivityDate> <ActivityDate>
{equalDate(activity.date, today) {equalDate(activity.date, today)
? "Today" ? 'Today'
: activity.date.toLocaleDateString()} : activity.date.toLocaleDateString()}
</ActivityDate> </ActivityDate>
<MessageWrapper className={`${!activity.isRead && "unread"}`}> <MessageWrapper className={`${!activity.isRead && 'unread'}`}>
<> <>
<UserIcon /> <UserIcon />
<ActivityContent> <ActivityContent>
@ -118,10 +118,10 @@ export function ActivityMessage({
id: activity.user, id: activity.user,
renamingState: false, renamingState: false,
requestState: false, requestState: false,
}); })
}} }}
> >
{" "} {' '}
{contact?.customName ?? activity.user.slice(0, 10)} {contact?.customName ?? activity.user.slice(0, 10)}
</ActivityUserName> </ActivityUserName>
{contact?.customName && ( {contact?.customName && (
@ -132,22 +132,22 @@ export function ActivityMessage({
{contact.isUntrustworthy && <UntrustworthIcon />} {contact.isUntrustworthy && <UntrustworthIcon />}
</UserNameWrapper> </UserNameWrapper>
<TimeWrapper> <TimeWrapper>
{activity.date.toLocaleString("en-US", { {activity.date.toLocaleString('en-US', {
hour: "numeric", hour: 'numeric',
minute: "numeric", minute: 'numeric',
hour12: true, hour12: true,
})} })}
</TimeWrapper> </TimeWrapper>
</MessageHeaderWrapper> </MessageHeaderWrapper>
{type === "request" && ( {type === 'request' && (
<ContextHeading> <ContextHeading>
Contact request Contact request
{activity.requestType === "outcome" {activity.requestType === 'outcome'
? ` to ${activity.user.slice(0, 10)}` ? ` to ${activity.user.slice(0, 10)}`
: ": "} : ': '}
</ContextHeading> </ContextHeading>
)} )}
{type === "invitation" && ( {type === 'invitation' && (
<FlexDiv> <FlexDiv>
<ContextHeading>{`Invited you to join a community `}</ContextHeading> <ContextHeading>{`Invited you to join a community `}</ContextHeading>
<Tag> <Tag>
@ -156,7 +156,7 @@ export function ActivityMessage({
style={{ style={{
backgroundImage: activity.invitation?.icon backgroundImage: activity.invitation?.icon
? `url(${activity.invitation?.icon}` ? `url(${activity.invitation?.icon}`
: "", : '',
}} }}
> >
{activity.invitation?.icon === undefined && {activity.invitation?.icon === undefined &&
@ -167,29 +167,29 @@ export function ActivityMessage({
</FlexDiv> </FlexDiv>
)} )}
<ActivityText> <ActivityText>
{"message" in activity && activity.message?.content && ( {'message' in activity && activity.message?.content && (
<div <div
onClick={() => { onClick={() => {
scroll(activity.message, activity.channel.id); scroll(activity.message, activity.channel.id)
setShowActivityCenter(false); setShowActivityCenter(false)
}} }}
> >
{elements.map((el) => el)} {elements.map(el => el)}
</div> </div>
)} )}
{activity.type === "request" && {activity.type === 'request' &&
activity.requestType === "income" && activity.requestType === 'income' &&
activity.request} activity.request}
</ActivityText> </ActivityText>
{type === "mention" && {type === 'mention' &&
activity.channel && activity.channel &&
activity.channel.type !== "dm" && ( activity.channel.type !== 'dm' && (
<Tag onClick={showChannel}> <Tag onClick={showChannel}>
{activity.channel.type === "group" ? <GroupIcon /> : "#"}{" "} {activity.channel.type === 'group' ? <GroupIcon /> : '#'}{' '}
<span>{` ${activity.channel.name.slice(0, 10)}`}</span> <span>{` ${activity.channel.name.slice(0, 10)}`}</span>
</Tag> </Tag>
)} )}
{type === "reply" && activity.quote && ( {type === 'reply' && activity.quote && (
<ReplyWrapper> <ReplyWrapper>
{activity.quote.image && ( {activity.quote.image && (
<ContextHeading>Posted an image in</ContextHeading> <ContextHeading>Posted an image in</ContextHeading>
@ -199,7 +199,7 @@ export function ActivityMessage({
</Tag> </Tag>
</ReplyWrapper> </ReplyWrapper>
)} )}
{type === "invitation" && ( {type === 'invitation' && (
<InviteDiv> <InviteDiv>
<ContextHeading>{`To access other communities, `}</ContextHeading> <ContextHeading>{`To access other communities, `}</ContextHeading>
<DownloadButton className="activity" /> <DownloadButton className="activity" />
@ -207,16 +207,16 @@ export function ActivityMessage({
)} )}
</ActivityContent> </ActivityContent>
</> </>
{type === "request" && {type === 'request' &&
!activity.status && !activity.status &&
activity.requestType === "income" && ( activity.requestType === 'income' && (
<> <>
<ActivityBtn <ActivityBtn
onClick={() => { onClick={() => {
activityDispatch({ activityDispatch({
type: "setStatus", type: 'setStatus',
payload: { id: activity.id, status: "accepted" }, payload: { id: activity.id, status: 'accepted' },
}); })
}} }}
className="accept" className="accept"
> >
@ -225,9 +225,9 @@ export function ActivityMessage({
<ActivityBtn <ActivityBtn
onClick={() => { onClick={() => {
activityDispatch({ activityDispatch({
type: "setStatus", type: 'setStatus',
payload: { id: activity.id, status: "declined" }, payload: { id: activity.id, status: 'declined' },
}); })
}} }}
className="decline" className="decline"
> >
@ -235,7 +235,7 @@ export function ActivityMessage({
</ActivityBtn> </ActivityBtn>
<ActivityBtn <ActivityBtn
onClick={() => { onClick={() => {
setShowMenu((e) => !e); setShowMenu(e => !e)
}} }}
ref={ref} ref={ref}
> >
@ -246,22 +246,22 @@ export function ActivityMessage({
</ActivityBtn> </ActivityBtn>
</> </>
)} )}
{type === "request" && activity.status === "accepted" && ( {type === 'request' && activity.status === 'accepted' && (
<RequestStatus className="accepted">Accepted</RequestStatus> <RequestStatus className="accepted">Accepted</RequestStatus>
)} )}
{type === "request" && activity.status === "declined" && ( {type === 'request' && activity.status === 'declined' && (
<RequestStatus className="declined">Declined</RequestStatus> <RequestStatus className="declined">Declined</RequestStatus>
)} )}
{type === "request" && activity.status === "sent" && ( {type === 'request' && activity.status === 'sent' && (
<RequestStatus>Sent</RequestStatus> <RequestStatus>Sent</RequestStatus>
)} )}
{(type === "mention" || type === "reply") && ( {(type === 'mention' || type === 'reply') && (
<BtnWrapper> <BtnWrapper>
<ActivityBtn <ActivityBtn
onClick={() => onClick={() =>
activityDispatch({ type: "setAsRead", payload: activity.id }) activityDispatch({ type: 'setAsRead', payload: activity.id })
} }
className={`${activity.isRead && "read"}`} className={`${activity.isRead && 'read'}`}
> >
<ReadMessageIcon isRead={activity.isRead} /> <ReadMessageIcon isRead={activity.isRead} />
</ActivityBtn> </ActivityBtn>
@ -270,13 +270,13 @@ export function ActivityMessage({
)} )}
</MessageWrapper> </MessageWrapper>
</MessageOuterWrapper> </MessageOuterWrapper>
); )
} }
const InviteDiv = styled.div` const InviteDiv = styled.div`
display: flex; display: flex;
margin-top: -4px; margin-top: -4px;
`; `
const BtnWrapper = styled.div` const BtnWrapper = styled.div`
position: relative; position: relative;
@ -284,13 +284,13 @@ const BtnWrapper = styled.div`
&:hover > div { &:hover > div {
visibility: visible; visibility: visible;
} }
`; `
const ActivityDate = styled(DateSeparator)` const ActivityDate = styled(DateSeparator)`
justify-content: flex-start; justify-content: flex-start;
padding: 8px 16px; padding: 8px 16px;
margin: 0; margin: 0;
`; `
const MessageWrapper = styled.div` const MessageWrapper = styled.div`
width: 100%; width: 100%;
@ -301,12 +301,12 @@ const MessageWrapper = styled.div`
&.unread { &.unread {
background: ${({ theme }) => theme.buttonBgHover}; background: ${({ theme }) => theme.buttonBgHover};
} }
`; `
const ActivityText = styled(MessageText)` const ActivityText = styled(MessageText)`
white-space: unset; white-space: unset;
margin-bottom: 8px; margin-bottom: 8px;
`; `
const Tag = styled.div` const Tag = styled.div`
width: fit-content; width: fit-content;
@ -328,7 +328,7 @@ const Tag = styled.div`
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
`; `
const ContextHeading = styled.p` const ContextHeading = styled.p`
font-style: italic; font-style: italic;
@ -336,7 +336,7 @@ const ContextHeading = styled.p`
flex-shrink: 0; flex-shrink: 0;
white-space: pre-wrap; white-space: pre-wrap;
${textMediumStyles} ${textMediumStyles}
`; `
const RequestStatus = styled.p` const RequestStatus = styled.p`
font-weight: 500; font-weight: 500;
@ -352,12 +352,12 @@ const RequestStatus = styled.p`
&.declined { &.declined {
color: ${({ theme }) => theme.redColor}; color: ${({ theme }) => theme.redColor};
} }
`; `
const ActivityContent = styled(ContentWrapper)` const ActivityContent = styled(ContentWrapper)`
max-width: calc(100% - 80px); max-width: calc(100% - 80px);
flex: 1; flex: 1;
`; `
const ActivityUserName = styled(UserName)` const ActivityUserName = styled(UserName)`
cursor: pointer; cursor: pointer;
@ -365,7 +365,7 @@ const ActivityUserName = styled(UserName)`
&:hover { &:hover {
text-decoration: underline; text-decoration: underline;
} }
`; `
const ReplyWrapper = styled.div` const ReplyWrapper = styled.div`
max-width: 100%; max-width: 100%;
@ -375,7 +375,7 @@ const ReplyWrapper = styled.div`
& > p { & > p {
margin-right: 4px; margin-right: 4px;
} }
`; `
const CommunityLogo = styled(Logo)` const CommunityLogo = styled(Logo)`
width: 16px; width: 16px;
@ -383,4 +383,4 @@ const CommunityLogo = styled(Logo)`
margin: 0 2px 0 4px; margin: 0 2px 0 4px;
${textSmallStyles} ${textSmallStyles}
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { LeftIcon } from "../Icons/LeftIcon"; import { LeftIcon } from '../Icons/LeftIcon'
interface BackButtonProps { interface BackButtonProps {
onBtnClick: () => void; onBtnClick: () => void
className?: string; className?: string
} }
export function BackButton({ onBtnClick, className }: BackButtonProps) { export function BackButton({ onBtnClick, className }: BackButtonProps) {
@ -13,7 +13,7 @@ export function BackButton({ onBtnClick, className }: BackButtonProps) {
<BackBtn onClick={onBtnClick} className={className}> <BackBtn onClick={onBtnClick} className={className}>
<LeftIcon width={24} height={24} className="black" /> <LeftIcon width={24} height={24} className="black" />
</BackBtn> </BackBtn>
); )
} }
const BackBtn = styled.button` const BackBtn = styled.button`
@ -28,4 +28,4 @@ const BackBtn = styled.button`
position: static; position: static;
margin-right: 13px; margin-right: 13px;
} }
`; `

View File

@ -1,50 +1,50 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { buttonStyles } from "./buttonStyle"; import { buttonStyles } from './buttonStyle'
const userAgent = window.navigator.userAgent; const userAgent = window.navigator.userAgent
const platform = window.navigator.platform; const platform = window.navigator.platform
const macosPlatforms = ["Macintosh", "MacIntel", "MacPPC", "Mac68K"]; const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K']
const windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"]; const windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE']
const iosPlatforms = ["iPhone", "iPad", "iPod"]; const iosPlatforms = ['iPhone', 'iPad', 'iPod']
interface DownloadButtonProps { interface DownloadButtonProps {
className?: string; className?: string
} }
export const DownloadButton = ({ className }: DownloadButtonProps) => { export const DownloadButton = ({ className }: DownloadButtonProps) => {
const [link, setlink] = useState("https://status.im/get/"); const [link, setlink] = useState('https://status.im/get/')
const [os, setOs] = useState<string | null>(null); const [os, setOs] = useState<string | null>(null)
useEffect(() => { useEffect(() => {
if (macosPlatforms.includes(platform)) { if (macosPlatforms.includes(platform)) {
setlink( setlink(
"https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.dmg" 'https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.dmg'
); )
setOs("Mac"); setOs('Mac')
} else if (iosPlatforms.includes(platform)) { } else if (iosPlatforms.includes(platform)) {
setlink( setlink(
"https://apps.apple.com/us/app/status-private-communication/id1178893006" 'https://apps.apple.com/us/app/status-private-communication/id1178893006'
); )
setOs("iOS"); setOs('iOS')
} else if (windowsPlatforms.includes(platform)) { } else if (windowsPlatforms.includes(platform)) {
setlink( setlink(
"https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.exe" 'https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.exe'
); )
setOs("Windows"); setOs('Windows')
} else if (/Android/.test(userAgent)) { } else if (/Android/.test(userAgent)) {
setlink( setlink(
"https://play.google.com/store/apps/details?id=im.status.ethereum" 'https://play.google.com/store/apps/details?id=im.status.ethereum'
); )
setOs("Android"); setOs('Android')
} else if (/Linux/.test(platform)) { } else if (/Linux/.test(platform)) {
setlink( setlink(
"https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.tar.gz" 'https://status-im-files.ams3.cdn.digitaloceanspaces.com/StatusIm-Desktop-v0.3.0-beta-a8c37d.tar.gz'
); )
setOs("Linux"); setOs('Linux')
} }
}, []); }, [])
return ( return (
<Link <Link
@ -54,11 +54,11 @@ export const DownloadButton = ({ className }: DownloadButtonProps) => {
rel="noopener noreferrer" rel="noopener noreferrer"
> >
{os {os
? `${className === "activity" ? "d" : "D"}ownload Status for ${os}` ? `${className === 'activity' ? 'd' : 'D'}ownload Status for ${os}`
: `${className === "activity" ? "d" : "D"}ownload Status`} : `${className === 'activity' ? 'd' : 'D'}ownload Status`}
</Link> </Link>
); )
}; }
const Link = styled.a` const Link = styled.a`
margin-top: 24px; margin-top: 24px;
@ -81,4 +81,4 @@ const Link = styled.a`
color: ${({ theme }) => theme.tertiary}; color: ${({ theme }) => theme.tertiary};
} }
} }
`; `

View File

@ -1,7 +1,7 @@
import styled, { css } from "styled-components"; import styled, { css } from 'styled-components'
export const buttonStyles = css` export const buttonStyles = css`
font-family: "Inter"; font-family: 'Inter';
font-weight: 500; font-weight: 500;
font-size: 15px; font-size: 15px;
line-height: 22px; line-height: 22px;
@ -17,10 +17,10 @@ export const buttonStyles = css`
&:focus { &:focus {
background: ${({ theme }) => theme.buttonBg}; background: ${({ theme }) => theme.buttonBg};
} }
`; `
export const buttonTransparentStyles = css` export const buttonTransparentStyles = css`
font-family: "Inter"; font-family: 'Inter';
font-weight: 500; font-weight: 500;
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
@ -37,7 +37,7 @@ export const buttonTransparentStyles = css`
&:focus { &:focus {
background: ${({ theme }) => theme.buttonBg}; background: ${({ theme }) => theme.buttonBg};
} }
`; `
export const ButtonNo = styled.button` export const ButtonNo = styled.button`
padding: 11px 24px; padding: 11px 24px;
@ -50,10 +50,10 @@ export const ButtonNo = styled.button`
&:hover { &:hover {
background: ${({ theme }) => theme.buttonNoBgHover}; background: ${({ theme }) => theme.buttonNoBgHover};
} }
`; `
export const ButtonYes = styled.button` export const ButtonYes = styled.button`
padding: 11px 24px; padding: 11px 24px;
${buttonStyles} ${buttonStyles}
`; `

View File

@ -1,29 +1,29 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { ChannelData } from "../../models/ChannelData"; import { ChannelData } from '../../models/ChannelData'
import { ChannelMenu } from "../Form/ChannelMenu"; import { ChannelMenu } from '../Form/ChannelMenu'
import { Tooltip } from "../Form/Tooltip"; import { Tooltip } from '../Form/Tooltip'
import { GroupIcon } from "../Icons/GroupIcon"; import { GroupIcon } from '../Icons/GroupIcon'
import { MutedIcon } from "../Icons/MutedIcon"; import { MutedIcon } from '../Icons/MutedIcon'
import { textMediumStyles } from "../Text"; import { textMediumStyles } from '../Text'
import { ChannelIcon } from "./ChannelIcon"; import { ChannelIcon } from './ChannelIcon'
function RenderChannelName({ function RenderChannelName({
channel, channel,
activeView, activeView,
className, className,
}: { }: {
channel: ChannelData; channel: ChannelData
activeView?: boolean; activeView?: boolean
className?: string; className?: string
}) { }) {
const { activeChannel } = useMessengerContext(); const { activeChannel } = useMessengerContext()
switch (channel.type) { switch (channel.type) {
case "group": case 'group':
return ( return (
<div className={className}> <div className={className}>
{!activeView && ( {!activeView && (
@ -31,22 +31,22 @@ function RenderChannelName({
)} )}
{` ${channel.name}`} {` ${channel.name}`}
</div> </div>
); )
case "channel": case 'channel':
return <div className={className}>{`# ${channel.name}`}</div>; return <div className={className}>{`# ${channel.name}`}</div>
case "dm": case 'dm':
return <div className={className}>{channel.name.slice(0, 20)}</div>; return <div className={className}>{channel.name.slice(0, 20)}</div>
} }
} }
interface ChannelProps { interface ChannelProps {
channel: ChannelData; channel: ChannelData
notified?: boolean; notified?: boolean
mention?: number; mention?: number
isActive: boolean; isActive: boolean
activeView?: boolean; activeView?: boolean
onClick?: () => void; onClick?: () => void
setEditGroup?: React.Dispatch<React.SetStateAction<boolean>>; setEditGroup?: React.Dispatch<React.SetStateAction<boolean>>
} }
export function Channel({ export function Channel({
@ -58,15 +58,15 @@ export function Channel({
mention, mention,
setEditGroup, setEditGroup,
}: ChannelProps) { }: ChannelProps) {
const narrow = useNarrow(); const narrow = useNarrow()
const { channelsDispatch } = useMessengerContext(); const { channelsDispatch } = useMessengerContext()
return ( return (
<ChannelWrapper <ChannelWrapper
className={`${isActive && "active"}`} className={`${isActive && 'active'}`}
isNarrow={narrow && activeView} isNarrow={narrow && activeView}
onClick={onClick} onClick={onClick}
id={!activeView ? `${channel.id + "contextMenu"}` : ""} id={!activeView ? `${channel.id + 'contextMenu'}` : ''}
> >
<ChannelInfo activeView={activeView}> <ChannelInfo activeView={activeView}>
<ChannelIcon channel={channel} activeView={activeView} /> <ChannelIcon channel={channel} activeView={activeView} />
@ -82,7 +82,7 @@ export function Channel({
{channel?.isMuted && activeView && !narrow && ( {channel?.isMuted && activeView && !narrow && (
<MutedBtn <MutedBtn
onClick={() => onClick={() =>
channelsDispatch({ type: "ToggleMuted", payload: channel.id }) channelsDispatch({ type: 'ToggleMuted', payload: channel.id })
} }
> >
<MutedIcon /> <MutedIcon />
@ -103,15 +103,15 @@ export function Channel({
<ChannelMenu <ChannelMenu
channel={channel} channel={channel}
setEditGroup={setEditGroup} setEditGroup={setEditGroup}
className={narrow ? "sideNarrow" : "side"} className={narrow ? 'sideNarrow' : 'side'}
/> />
)} )}
</ChannelWrapper> </ChannelWrapper>
); )
} }
const ChannelWrapper = styled.div<{ isNarrow?: boolean }>` const ChannelWrapper = styled.div<{ isNarrow?: boolean }>`
width: ${({ isNarrow }) => (isNarrow ? "calc(100% - 162px)" : "100%")}; width: ${({ isNarrow }) => (isNarrow ? 'calc(100% - 162px)' : '100%')};
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@ -128,13 +128,13 @@ const ChannelWrapper = styled.div<{ isNarrow?: boolean }>`
&:hover { &:hover {
background-color: ${({ theme, isNarrow }) => isNarrow && theme.border}; background-color: ${({ theme, isNarrow }) => isNarrow && theme.border};
} }
`; `
export const ChannelInfo = styled.div<{ activeView?: boolean }>` export const ChannelInfo = styled.div<{ activeView?: boolean }>`
display: flex; display: flex;
align-items: ${({ activeView }) => (activeView ? "flex-start" : "center")}; align-items: ${({ activeView }) => (activeView ? 'flex-start' : 'center')};
overflow-x: hidden; overflow-x: hidden;
`; `
const ChannelTextInfo = styled.div<{ activeView?: boolean }>` const ChannelTextInfo = styled.div<{ activeView?: boolean }>`
display: flex; display: flex;
@ -142,33 +142,33 @@ const ChannelTextInfo = styled.div<{ activeView?: boolean }>`
text-overflow: ellipsis; text-overflow: ellipsis;
overflow-x: hidden; overflow-x: hidden;
white-space: nowrap; white-space: nowrap;
padding: ${({ activeView }) => activeView && "0 24px 24px 0"}; padding: ${({ activeView }) => activeView && '0 24px 24px 0'};
`; `
const ChannelNameWrapper = styled.div` const ChannelNameWrapper = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
`; `
export const ChannelName = styled(RenderChannelName)<{ export const ChannelName = styled(RenderChannelName)<{
muted?: boolean; muted?: boolean
notified?: boolean; notified?: boolean
active?: boolean; active?: boolean
activeView?: boolean; activeView?: boolean
}>` }>`
font-weight: ${({ notified, muted, active }) => font-weight: ${({ notified, muted, active }) =>
notified && !muted && !active ? "600" : "500"}; notified && !muted && !active ? '600' : '500'};
opacity: ${({ notified, muted, active }) => opacity: ${({ notified, muted, active }) =>
muted ? "0.4" : notified || active ? "1.0" : "0.7"}; muted ? '0.4' : notified || active ? '1.0' : '0.7'};
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
margin-right: ${({ muted, activeView }) => margin-right: ${({ muted, activeView }) =>
muted && activeView ? "8px" : ""}; muted && activeView ? '8px' : ''};
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
${textMediumStyles} ${textMediumStyles}
`; `
const ChannelDescription = styled.p` const ChannelDescription = styled.p`
font-size: 12px; font-size: 12px;
@ -178,7 +178,7 @@ const ChannelDescription = styled.p`
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
`; `
const NotificationBagde = styled.div` const NotificationBagde = styled.div`
width: 24px; width: 24px;
@ -193,7 +193,7 @@ const NotificationBagde = styled.div`
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0; flex-shrink: 0;
`; `
const MutedBtn = styled.button` const MutedBtn = styled.button`
padding: 0; padding: 0;
@ -208,4 +208,4 @@ const MutedBtn = styled.button`
&:hover > div { &:hover > div {
visibility: visible; visibility: visible;
} }
`; `

View File

@ -1,25 +1,25 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { ChannelData } from "../../models/ChannelData"; import { ChannelData } from '../../models/ChannelData'
interface ChannelIconProps { interface ChannelIconProps {
channel: ChannelData; channel: ChannelData
activeView?: boolean; activeView?: boolean
} }
export function ChannelIcon({ channel, activeView }: ChannelIconProps) { export function ChannelIcon({ channel, activeView }: ChannelIconProps) {
const narrow = useNarrow(); const narrow = useNarrow()
return ( return (
<ChannelLogo <ChannelLogo
icon={channel.icon} icon={channel.icon}
className={activeView ? "active" : narrow ? "narrow" : ""} className={activeView ? 'active' : narrow ? 'narrow' : ''}
> >
{!channel.icon && channel.name.slice(0, 1).toUpperCase()} {!channel.icon && channel.name.slice(0, 1).toUpperCase()}
</ChannelLogo> </ChannelLogo>
); )
} }
export const ChannelLogo = styled.div<{ icon?: string }>` export const ChannelLogo = styled.div<{ icon?: string }>`
@ -51,4 +51,4 @@ export const ChannelLogo = styled.div<{ icon?: string }>`
height: 40px; height: 40px;
font-size: 20px; font-size: 20px;
} }
`; `

View File

@ -1,22 +1,22 @@
import React, { useMemo } from "react"; import React, { useMemo } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { ChatState, useChatState } from "../../contexts/chatStateProvider"; import { ChatState, useChatState } from '../../contexts/chatStateProvider'
import { useIdentity } from "../../contexts/identityProvider"; import { useIdentity } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { CreateIcon } from "../Icons/CreateIcon"; import { CreateIcon } from '../Icons/CreateIcon'
import { UserCreation } from "../UserCreation/UserCreation"; import { UserCreation } from '../UserCreation/UserCreation'
import { Channel } from "./Channel"; import { Channel } from './Channel'
interface ChannelsProps { interface ChannelsProps {
onCommunityClick?: () => void; onCommunityClick?: () => void
setEditGroup?: React.Dispatch<React.SetStateAction<boolean>>; setEditGroup?: React.Dispatch<React.SetStateAction<boolean>>
} }
type GenerateChannelsProps = ChannelsProps & { type GenerateChannelsProps = ChannelsProps & {
type: string; type: string
}; }
function GenerateChannels({ function GenerateChannels({
type, type,
@ -24,16 +24,16 @@ function GenerateChannels({
setEditGroup, setEditGroup,
}: GenerateChannelsProps) { }: GenerateChannelsProps) {
const { mentions, notifications, activeChannel, channelsDispatch, channels } = const { mentions, notifications, activeChannel, channelsDispatch, channels } =
useMessengerContext(); useMessengerContext()
const channelList = useMemo(() => Object.values(channels), [channels]); const channelList = useMemo(() => Object.values(channels), [channels])
const setChatState = useChatState()[1]; const setChatState = useChatState()[1]
return ( return (
<> <>
{channelList {channelList
.filter((channel) => channel.type === type) .filter(channel => channel.type === type)
.map((channel) => ( .map(channel => (
<Channel <Channel
key={channel.id} key={channel.id}
channel={channel} channel={channel}
@ -41,26 +41,26 @@ function GenerateChannels({
notified={notifications?.[channel.id] > 0} notified={notifications?.[channel.id] > 0}
mention={mentions?.[channel.id]} mention={mentions?.[channel.id]}
onClick={() => { onClick={() => {
channelsDispatch({ type: "ChangeActive", payload: channel.id }); channelsDispatch({ type: 'ChangeActive', payload: channel.id })
if (onCommunityClick) { if (onCommunityClick) {
onCommunityClick(); onCommunityClick()
} }
setChatState(ChatState.ChatBody); setChatState(ChatState.ChatBody)
}} }}
setEditGroup={setEditGroup} setEditGroup={setEditGroup}
/> />
))} ))}
</> </>
); )
} }
type ChatsListProps = { type ChatsListProps = {
onCommunityClick?: () => void; onCommunityClick?: () => void
setEditGroup?: React.Dispatch<React.SetStateAction<boolean>>; setEditGroup?: React.Dispatch<React.SetStateAction<boolean>>
}; }
function ChatsSideBar({ onCommunityClick, setEditGroup }: ChatsListProps) { function ChatsSideBar({ onCommunityClick, setEditGroup }: ChatsListProps) {
const setChatState = useChatState()[1]; const setChatState = useChatState()[1]
return ( return (
<> <>
<ChatsBar> <ChatsBar>
@ -71,21 +71,21 @@ function ChatsSideBar({ onCommunityClick, setEditGroup }: ChatsListProps) {
</ChatsBar> </ChatsBar>
<ChatsList> <ChatsList>
<GenerateChannels <GenerateChannels
type={"group"} type={'group'}
onCommunityClick={onCommunityClick} onCommunityClick={onCommunityClick}
setEditGroup={setEditGroup} setEditGroup={setEditGroup}
/> />
<GenerateChannels type={"dm"} onCommunityClick={onCommunityClick} /> <GenerateChannels type={'dm'} onCommunityClick={onCommunityClick} />
</ChatsList> </ChatsList>
</> </>
); )
} }
export function Channels({ onCommunityClick, setEditGroup }: ChannelsProps) { export function Channels({ onCommunityClick, setEditGroup }: ChannelsProps) {
const identity = useIdentity(); const identity = useIdentity()
return ( return (
<ChannelList> <ChannelList>
<GenerateChannels type={"channel"} onCommunityClick={onCommunityClick} /> <GenerateChannels type={'channel'} onCommunityClick={onCommunityClick} />
<Chats> <Chats>
{identity ? ( {identity ? (
<ChatsSideBar <ChatsSideBar
@ -97,7 +97,7 @@ export function Channels({ onCommunityClick, setEditGroup }: ChannelsProps) {
)} )}
</Chats> </Chats>
</ChannelList> </ChannelList>
); )
} }
export const ChannelList = styled.div` export const ChannelList = styled.div`
@ -107,7 +107,7 @@ export const ChannelList = styled.div`
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 0; width: 0;
} }
`; `
const Chats = styled.div` const Chats = styled.div`
display: flex; display: flex;
@ -117,7 +117,7 @@ const Chats = styled.div`
position: relative; position: relative;
&::before { &::before {
content: ""; content: '';
position: absolute; position: absolute;
top: 0; top: 0;
left: 50%; left: 50%;
@ -127,26 +127,26 @@ const Chats = styled.div`
background-color: ${({ theme }) => theme.primary}; background-color: ${({ theme }) => theme.primary};
opacity: 0.1; opacity: 0.1;
} }
`; `
const ChatsBar = styled.div` const ChatsBar = styled.div`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 8px; margin-bottom: 8px;
`; `
const ChatsList = styled.div` const ChatsList = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
`; `
const Heading = styled.p` const Heading = styled.p`
font-weight: bold; font-weight: bold;
font-size: 17px; font-size: 17px;
line-height: 24px; line-height: 24px;
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
`; `
const EditBtn = styled.button` const EditBtn = styled.button`
width: 32px; width: 32px;
@ -161,4 +161,4 @@ const EditBtn = styled.button`
&:active { &:active {
background: ${({ theme }) => theme.sectionBackgroundColor}; background: ${({ theme }) => theme.sectionBackgroundColor};
} }
`; `

View File

@ -1,44 +1,44 @@
import React, { useMemo } from "react"; import React, { useMemo } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useUserPublicKey } from "../../contexts/identityProvider"; import { useUserPublicKey } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { ChannelData } from "../../models/ChannelData"; import { ChannelData } from '../../models/ChannelData'
import { textMediumStyles } from "../Text"; import { textMediumStyles } from '../Text'
import { ChannelInfo, ChannelName } from "./Channel"; import { ChannelInfo, ChannelName } from './Channel'
import { ChannelLogo } from "./ChannelIcon"; import { ChannelLogo } from './ChannelIcon'
type ChannelBeggingTextProps = { type ChannelBeggingTextProps = {
channel: ChannelData; channel: ChannelData
}; }
function ChannelBeggingText({ channel }: ChannelBeggingTextProps) { function ChannelBeggingText({ channel }: ChannelBeggingTextProps) {
const userPK = useUserPublicKey(); const userPK = useUserPublicKey()
const { contacts } = useMessengerContext(); const { contacts } = useMessengerContext()
const members = useMemo(() => { const members = useMemo(() => {
if (channel?.members && userPK) { if (channel?.members && userPK) {
return channel.members return channel.members
.filter((contact) => contact.id !== userPK) .filter(contact => contact.id !== userPK)
.map((member) => contacts?.[member.id] ?? member); .map(member => contacts?.[member.id] ?? member)
} }
return []; return []
}, [channel, contacts, userPK]); }, [channel, contacts, userPK])
switch (channel.type) { switch (channel.type) {
case "dm": case 'dm':
return ( return (
<EmptyText> <EmptyText>
Any messages you send here are encrypted and can only be read by you Any messages you send here are encrypted and can only be read by you
and <br /> and <br />
<span>{channel.name.slice(0, 10)}</span>. <span>{channel.name.slice(0, 10)}</span>.
</EmptyText> </EmptyText>
); )
case "group": case 'group':
return ( return (
<EmptyTextGroup> <EmptyTextGroup>
{userPK && <span>{userPK}</span>} created a group with{" "} {userPK && <span>{userPK}</span>} created a group with{' '}
{members.map((contact, idx) => ( {members.map((contact, idx) => (
<span key={contact.id}> <span key={contact.id}>
{contact?.customName ?? contact.trueName.slice(0, 10)} {contact?.customName ?? contact.trueName.slice(0, 10)}
@ -46,36 +46,36 @@ function ChannelBeggingText({ channel }: ChannelBeggingTextProps) {
</span> </span>
))} ))}
</EmptyTextGroup> </EmptyTextGroup>
); )
case "channel": case 'channel':
return ( return (
<EmptyText> <EmptyText>
Welcome to the beginning of the <span>#{channel.name}</span> channel! Welcome to the beginning of the <span>#{channel.name}</span> channel!
</EmptyText> </EmptyText>
); )
} }
return null; return null
} }
type EmptyChannelProps = { type EmptyChannelProps = {
channel: ChannelData; channel: ChannelData
}; }
export function EmptyChannel({ channel }: EmptyChannelProps) { export function EmptyChannel({ channel }: EmptyChannelProps) {
const narrow = useNarrow(); const narrow = useNarrow()
return ( return (
<Wrapper className={`${!narrow && "wide"}`}> <Wrapper className={`${!narrow && 'wide'}`}>
<ChannelInfoEmpty> <ChannelInfoEmpty>
<ChannelLogoEmpty icon={channel.icon}> <ChannelLogoEmpty icon={channel.icon}>
{" "} {' '}
{!channel.icon && channel.name.slice(0, 1).toUpperCase()} {!channel.icon && channel.name.slice(0, 1).toUpperCase()}
</ChannelLogoEmpty> </ChannelLogoEmpty>
<ChannelNameEmpty active={true} channel={channel} /> <ChannelNameEmpty active={true} channel={channel} />
</ChannelInfoEmpty> </ChannelInfoEmpty>
<ChannelBeggingText channel={channel} /> <ChannelBeggingText channel={channel} />
</Wrapper> </Wrapper>
); )
} }
const Wrapper = styled.div` const Wrapper = styled.div`
@ -87,11 +87,11 @@ const Wrapper = styled.div`
&.wide { &.wide {
margin-top: 24px; margin-top: 24px;
} }
`; `
const ChannelInfoEmpty = styled(ChannelInfo)` const ChannelInfoEmpty = styled(ChannelInfo)`
flex-direction: column; flex-direction: column;
`; `
const ChannelLogoEmpty = styled(ChannelLogo)` const ChannelLogoEmpty = styled(ChannelLogo)`
width: 120px; width: 120px;
@ -100,14 +100,14 @@ const ChannelLogoEmpty = styled(ChannelLogo)`
font-size: 51px; font-size: 51px;
line-height: 62px; line-height: 62px;
margin-bottom: 16px; margin-bottom: 16px;
`; `
const ChannelNameEmpty = styled(ChannelName)` const ChannelNameEmpty = styled(ChannelName)`
font-weight: bold; font-weight: bold;
font-size: 22px; font-size: 22px;
line-height: 30px; line-height: 30px;
margin-bottom: 16px; margin-bottom: 16px;
`; `
const EmptyText = styled.p` const EmptyText = styled.p`
display: inline-block; display: inline-block;
@ -120,10 +120,10 @@ const EmptyText = styled.p`
} }
${textMediumStyles} ${textMediumStyles}
`; `
const EmptyTextGroup = styled(EmptyText)` const EmptyTextGroup = styled(EmptyText)`
& > span { & > span {
word-break: break-all; word-break: break-all;
} }
`; `

View File

@ -1,19 +1,19 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, { useCallback, useEffect, useMemo, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { Reply } from "../../hooks/useReply"; import { Reply } from '../../hooks/useReply'
import { ChannelData } from "../../models/ChannelData"; import { ChannelData } from '../../models/ChannelData'
import { TokenRequirement } from "../Form/TokenRequirement"; import { TokenRequirement } from '../Form/TokenRequirement'
import { MessagesList } from "../Messages/MessagesList"; import { MessagesList } from '../Messages/MessagesList'
import { NarrowChannels } from "../NarrowMode/NarrowChannels"; import { NarrowChannels } from '../NarrowMode/NarrowChannels'
import { NarrowMembers } from "../NarrowMode/NarrowMembers"; import { NarrowMembers } from '../NarrowMode/NarrowMembers'
import { LoadingSkeleton } from "../Skeleton/LoadingSkeleton"; import { LoadingSkeleton } from '../Skeleton/LoadingSkeleton'
import { ChatCreation } from "./ChatCreation"; import { ChatCreation } from './ChatCreation'
import { ChatInput } from "./ChatInput"; import { ChatInput } from './ChatInput'
import { ChatTopbar, ChatTopbarLoading } from "./ChatTopbar"; import { ChatTopbar, ChatTopbarLoading } from './ChatTopbar'
export enum ChatBodyState { export enum ChatBodyState {
Chat, Chat,
@ -22,30 +22,30 @@ export enum ChatBodyState {
} }
function ChatBodyLoading() { function ChatBodyLoading() {
const narrow = useNarrow(); const narrow = useNarrow()
return ( return (
<Wrapper> <Wrapper>
<ChatBodyWrapper className={narrow ? "narrow" : ""}> <ChatBodyWrapper className={narrow ? 'narrow' : ''}>
<ChatTopbarLoading /> <ChatTopbarLoading />
<LoadingSkeleton /> <LoadingSkeleton />
<ChatInput reply={undefined} setReply={() => undefined} /> <ChatInput reply={undefined} setReply={() => undefined} />
</ChatBodyWrapper> </ChatBodyWrapper>
</Wrapper> </Wrapper>
); )
} }
type ChatBodyContentProps = { type ChatBodyContentProps = {
showState: ChatBodyState; showState: ChatBodyState
switchShowState: (state: ChatBodyState) => void; switchShowState: (state: ChatBodyState) => void
channel: ChannelData; channel: ChannelData
}; }
function ChatBodyContent({ function ChatBodyContent({
showState, showState,
switchShowState, switchShowState,
channel, channel,
}: ChatBodyContentProps) { }: ChatBodyContentProps) {
const [reply, setReply] = useState<Reply | undefined>(undefined); const [reply, setReply] = useState<Reply | undefined>(undefined)
switch (showState) { switch (showState) {
case ChatBodyState.Chat: case ChatBodyState.Chat:
@ -54,28 +54,28 @@ function ChatBodyContent({
<MessagesList setReply={setReply} channel={channel} /> <MessagesList setReply={setReply} channel={channel} />
<ChatInput reply={reply} setReply={setReply} /> <ChatInput reply={reply} setReply={setReply} />
</> </>
); )
case ChatBodyState.Channels: case ChatBodyState.Channels:
return ( return (
<NarrowChannels <NarrowChannels
setShowChannels={() => switchShowState(ChatBodyState.Channels)} setShowChannels={() => switchShowState(ChatBodyState.Channels)}
/> />
); )
case ChatBodyState.Members: case ChatBodyState.Members:
return ( return (
<NarrowMembers <NarrowMembers
switchShowMembersList={() => switchShowState(ChatBodyState.Members)} switchShowMembersList={() => switchShowState(ChatBodyState.Members)}
/> />
); )
} }
} }
interface ChatBodyProps { interface ChatBodyProps {
onClick: () => void; onClick: () => void
showMembers: boolean; showMembers: boolean
permission: boolean; permission: boolean
editGroup: boolean; editGroup: boolean
setEditGroup: React.Dispatch<React.SetStateAction<boolean>>; setEditGroup: React.Dispatch<React.SetStateAction<boolean>>
} }
export function ChatBody({ export function ChatBody({
@ -85,26 +85,26 @@ export function ChatBody({
editGroup, editGroup,
setEditGroup, setEditGroup,
}: ChatBodyProps) { }: ChatBodyProps) {
const { activeChannel, loadingMessenger } = useMessengerContext(); const { activeChannel, loadingMessenger } = useMessengerContext()
const narrow = useNarrow(); const narrow = useNarrow()
const className = useMemo(() => (narrow ? "narrow" : ""), [narrow]); const className = useMemo(() => (narrow ? 'narrow' : ''), [narrow])
const [showState, setShowState] = useState<ChatBodyState>(ChatBodyState.Chat); const [showState, setShowState] = useState<ChatBodyState>(ChatBodyState.Chat)
const switchShowState = useCallback( const switchShowState = useCallback(
(state: ChatBodyState) => { (state: ChatBodyState) => {
if (narrow) { if (narrow) {
setShowState((prev) => (prev === state ? ChatBodyState.Chat : state)); setShowState(prev => (prev === state ? ChatBodyState.Chat : state))
} }
}, },
[narrow] [narrow]
); )
useEffect(() => { useEffect(() => {
if (!narrow) { if (!narrow) {
setShowState(ChatBodyState.Chat); setShowState(ChatBodyState.Chat)
} }
}, [narrow]); }, [narrow])
if (!loadingMessenger && activeChannel) { if (!loadingMessenger && activeChannel) {
return ( return (
@ -138,10 +138,10 @@ export function ChatBody({
</BluredWrapper> </BluredWrapper>
)} )}
</Wrapper> </Wrapper>
); )
} }
return <ChatBodyLoading />; return <ChatBodyLoading />
} }
export const Wrapper = styled.div` export const Wrapper = styled.div`
@ -156,7 +156,7 @@ export const Wrapper = styled.div`
&.narrow { &.narrow {
width: 100%; width: 100%;
} }
`; `
const ChatBodyWrapper = styled.div` const ChatBodyWrapper = styled.div`
width: 100%; width: 100%;
@ -165,7 +165,7 @@ const ChatBodyWrapper = styled.div`
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
background: ${({ theme }) => theme.bodyBackgroundColor}; background: ${({ theme }) => theme.bodyBackgroundColor};
`; `
const BluredWrapper = styled.div` const BluredWrapper = styled.div`
width: 100%; width: 100%;
@ -179,4 +179,4 @@ const BluredWrapper = styled.div`
background: ${({ theme }) => theme.bodyBackgroundGradient}; background: ${({ theme }) => theme.bodyBackgroundGradient};
backdrop-filter: blur(4px); backdrop-filter: blur(4px);
z-index: 2; z-index: 2;
`; `

View File

@ -1,107 +1,107 @@
import React, { useCallback, useMemo, useState } from "react"; import React, { useCallback, useMemo, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { ChatState, useChatState } from "../../contexts/chatStateProvider"; import { ChatState, useChatState } from '../../contexts/chatStateProvider'
import { useUserPublicKey } from "../../contexts/identityProvider"; import { useUserPublicKey } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { ChannelData } from "../../models/ChannelData"; import { ChannelData } from '../../models/ChannelData'
import { ActivityButton } from "../ActivityCenter/ActivityButton"; import { ActivityButton } from '../ActivityCenter/ActivityButton'
import { BackButton } from "../Buttons/BackButton"; import { BackButton } from '../Buttons/BackButton'
import { buttonStyles } from "../Buttons/buttonStyle"; import { buttonStyles } from '../Buttons/buttonStyle'
import { CrossIcon } from "../Icons/CrossIcon"; import { CrossIcon } from '../Icons/CrossIcon'
import { Member } from "../Members/Member"; import { Member } from '../Members/Member'
import { SearchBlock } from "../SearchBlock"; import { SearchBlock } from '../SearchBlock'
import { textMediumStyles } from "../Text"; import { textMediumStyles } from '../Text'
import { ChatInput } from "./ChatInput"; import { ChatInput } from './ChatInput'
interface ChatCreationProps { interface ChatCreationProps {
setEditGroup?: (val: boolean) => void; setEditGroup?: (val: boolean) => void
activeChannel?: ChannelData; activeChannel?: ChannelData
} }
export function ChatCreation({ export function ChatCreation({
setEditGroup, setEditGroup,
activeChannel, activeChannel,
}: ChatCreationProps) { }: ChatCreationProps) {
const narrow = useNarrow(); const narrow = useNarrow()
const userPK = useUserPublicKey(); const userPK = useUserPublicKey()
const [query, setQuery] = useState(""); const [query, setQuery] = useState('')
const [groupChatMembersIds, setGroupChatMembersIds] = useState<string[]>( const [groupChatMembersIds, setGroupChatMembersIds] = useState<string[]>(
activeChannel?.members?.map((member) => member.id) ?? [] activeChannel?.members?.map(member => member.id) ?? []
); )
const { contacts, createGroupChat, addMembers } = useMessengerContext(); const { contacts, createGroupChat, addMembers } = useMessengerContext()
const groupChatMembers = useMemo( const groupChatMembers = useMemo(
() => groupChatMembersIds.map((id) => contacts[id]).filter((e) => !!e), () => groupChatMembersIds.map(id => contacts[id]).filter(e => !!e),
[groupChatMembersIds, contacts] [groupChatMembersIds, contacts]
); )
const contactsList = useMemo(() => { const contactsList = useMemo(() => {
return Object.values(contacts) return Object.values(contacts)
.filter( .filter(
(member) => member =>
member.id.includes(query) || member.id.includes(query) ||
member?.customName?.includes(query) || member?.customName?.includes(query) ||
member.trueName.includes(query) member.trueName.includes(query)
) )
.filter((member) => !groupChatMembersIds.includes(member.id)); .filter(member => !groupChatMembersIds.includes(member.id))
}, [query, groupChatMembersIds, contacts]); }, [query, groupChatMembersIds, contacts])
const setChatState = useChatState()[1]; const setChatState = useChatState()[1]
const addMember = useCallback( const addMember = useCallback(
(member: string) => { (member: string) => {
setGroupChatMembersIds((prevMembers: string[]) => { setGroupChatMembersIds((prevMembers: string[]) => {
if ( if (
prevMembers.find((mem) => mem === member) || prevMembers.find(mem => mem === member) ||
prevMembers.length >= 5 prevMembers.length >= 5
) { ) {
return prevMembers; return prevMembers
} else { } else {
return [...prevMembers, member]; return [...prevMembers, member]
} }
}); })
setQuery(""); setQuery('')
}, },
[setGroupChatMembersIds] [setGroupChatMembersIds]
); )
const removeMember = useCallback( const removeMember = useCallback(
(member: string) => { (member: string) => {
setGroupChatMembersIds((prev) => prev.filter((e) => e != member)); setGroupChatMembersIds(prev => prev.filter(e => e != member))
}, },
[setGroupChatMembersIds] [setGroupChatMembersIds]
); )
const createChat = useCallback( const createChat = useCallback(
(group: string[]) => { (group: string[]) => {
if (userPK) { if (userPK) {
const newGroup = group.slice(); const newGroup = group.slice()
newGroup.push(userPK); newGroup.push(userPK)
createGroupChat(newGroup); createGroupChat(newGroup)
setChatState(ChatState.ChatBody); setChatState(ChatState.ChatBody)
} }
}, },
[userPK, createGroupChat, setChatState] [userPK, createGroupChat, setChatState]
); )
const handleCreationClick = useCallback(() => { const handleCreationClick = useCallback(() => {
if (!activeChannel) { if (!activeChannel) {
createChat(groupChatMembers.map((member) => member.id)); createChat(groupChatMembers.map(member => member.id))
} else { } else {
addMembers( addMembers(
groupChatMembers.map((member) => member.id), groupChatMembers.map(member => member.id),
activeChannel.id activeChannel.id
); )
} }
setEditGroup?.(false); setEditGroup?.(false)
}, [activeChannel, groupChatMembers, createChat, addMembers, setEditGroup]); }, [activeChannel, groupChatMembers, createChat, addMembers, setEditGroup])
return ( return (
<CreationWrapper className={`${narrow && "narrow"}`}> <CreationWrapper className={`${narrow && 'narrow'}`}>
<CreationBar <CreationBar
className={`${groupChatMembers.length === 5 && narrow && "limit"}`} className={`${groupChatMembers.length === 5 && narrow && 'limit'}`}
> >
{narrow && ( {narrow && (
<BackButton <BackButton
@ -117,7 +117,7 @@ export function ChatCreation({
<InputBar> <InputBar>
<InputText>To:</InputText> <InputText>To:</InputText>
<StyledList> <StyledList>
{groupChatMembers.map((member) => ( {groupChatMembers.map(member => (
<StyledMember key={member.id}> <StyledMember key={member.id}>
<StyledName> <StyledName>
{member?.customName?.slice(0, 10) ?? {member?.customName?.slice(0, 10) ??
@ -133,7 +133,7 @@ export function ChatCreation({
<SearchMembers> <SearchMembers>
<Input <Input
value={query} value={query}
onInput={(e) => setQuery(e.currentTarget.value)} onInput={e => setQuery(e.currentTarget.value)}
/> />
</SearchMembers> </SearchMembers>
)} )}
@ -166,7 +166,7 @@ export function ChatCreation({
<ContactsHeading>Contacts</ContactsHeading> <ContactsHeading>Contacts</ContactsHeading>
<ContactsList> <ContactsList>
{userPK && narrow {userPK && narrow
? contactsList.map((contact) => ( ? contactsList.map(contact => (
<Contact key={contact.id}> <Contact key={contact.id}>
<Member <Member
contact={contact} contact={contact}
@ -177,10 +177,9 @@ export function ChatCreation({
)) ))
: Object.values(contacts) : Object.values(contacts)
.filter( .filter(
(e) => e => e.id != userPK && !groupChatMembersIds.includes(e.id)
e.id != userPK && !groupChatMembersIds.includes(e.id)
) )
.map((contact) => ( .map(contact => (
<Contact key={contact.id}> <Contact key={contact.id}>
<Member <Member
contact={contact} contact={contact}
@ -195,10 +194,10 @@ export function ChatCreation({
{!setEditGroup && Object.keys(contacts).length === 0 && ( {!setEditGroup && Object.keys(contacts).length === 0 && (
<EmptyContacts> <EmptyContacts>
<EmptyContactsHeading> <EmptyContactsHeading>
You only can send direct messages to your Contacts.{" "} You only can send direct messages to your Contacts.{' '}
</EmptyContactsHeading> </EmptyContactsHeading>
<EmptyContactsHeading> <EmptyContactsHeading>
{" "} {' '}
Send a contact request to the person you would like to chat with, Send a contact request to the person you would like to chat with,
you will be able to chat with them once they have accepted your you will be able to chat with them once they have accepted your
contact request. contact request.
@ -209,11 +208,11 @@ export function ChatCreation({
{!activeChannel && ( {!activeChannel && (
<ChatInput <ChatInput
createChat={createChat} createChat={createChat}
group={groupChatMembers.map((member) => member.id)} group={groupChatMembers.map(member => member.id)}
/> />
)} )}
</CreationWrapper> </CreationWrapper>
); )
} }
const CreationWrapper = styled.div` const CreationWrapper = styled.div`
@ -229,7 +228,7 @@ const CreationWrapper = styled.div`
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
} }
`; `
const CreationBar = styled.div` const CreationBar = styled.div`
display: flex; display: flex;
@ -240,7 +239,7 @@ const CreationBar = styled.div`
&.limit { &.limit {
align-items: flex-start; align-items: flex-start;
} }
`; `
const Column = styled.div` const Column = styled.div`
display: flex; display: flex;
@ -249,7 +248,7 @@ const Column = styled.div`
flex: 1; flex: 1;
margin-right: 16px; margin-right: 16px;
overflow-x: hidden; overflow-x: hidden;
`; `
const InputBar = styled.div` const InputBar = styled.div`
display: flex; display: flex;
@ -262,7 +261,7 @@ const InputBar = styled.div`
padding: 6px 16px; padding: 6px 16px;
${textMediumStyles} ${textMediumStyles}
`; `
const Input = styled.input` const Input = styled.input`
width: 100%; width: 100%;
@ -278,12 +277,12 @@ const Input = styled.input`
outline: none; outline: none;
caret-color: ${({ theme }) => theme.notificationColor}; caret-color: ${({ theme }) => theme.notificationColor};
} }
`; `
const InputText = styled.div` const InputText = styled.div`
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
margin-right: 8px; margin-right: 8px;
`; `
const CreationBtn = styled.button` const CreationBtn = styled.button`
padding: 11px 24px; padding: 11px 24px;
@ -293,7 +292,7 @@ const CreationBtn = styled.button`
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
} }
`; `
const StyledList = styled.div` const StyledList = styled.div`
display: flex; display: flex;
@ -303,7 +302,7 @@ const StyledList = styled.div`
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
} }
`; `
const StyledMember = styled.div` const StyledMember = styled.div`
display: flex; display: flex;
@ -316,18 +315,18 @@ const StyledMember = styled.div`
& + & { & + & {
margin-left: 8px; margin-left: 8px;
} }
`; `
const StyledName = styled.p` const StyledName = styled.p`
color: ${({ theme }) => theme.bodyBackgroundColor}; color: ${({ theme }) => theme.bodyBackgroundColor};
${textMediumStyles} ${textMediumStyles}
`; `
const CloseButton = styled.button` const CloseButton = styled.button`
width: 20px; width: 20px;
height: 20px; height: 20px;
`; `
const Contacts = styled.div` const Contacts = styled.div`
height: calc(100% - 44px); height: calc(100% - 44px);
@ -335,7 +334,7 @@ const Contacts = styled.div`
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
overflow: auto; overflow: auto;
`; `
const Contact = styled.div` const Contact = styled.div`
display: flex; display: flex;
@ -346,34 +345,34 @@ const Contact = styled.div`
&:hover { &:hover {
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
} }
`; `
const ContactsHeading = styled.p` const ContactsHeading = styled.p`
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
${textMediumStyles} ${textMediumStyles}
`; `
export const ContactsList = styled.div` export const ContactsList = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
`; `
const EmptyContacts = styled(Contacts)` const EmptyContacts = styled(Contacts)`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
`; `
const EmptyContactsHeading = styled(ContactsHeading)` const EmptyContactsHeading = styled(ContactsHeading)`
max-width: 550px; max-width: 550px;
margin-bottom: 24px; margin-bottom: 24px;
text-align: center; text-align: center;
`; `
const SearchMembers = styled.div` const SearchMembers = styled.div`
position: relative; position: relative;
flex: 1; flex: 1;
`; `
const LimitAlert = styled.p` const LimitAlert = styled.p`
text-transform: uppercase; text-transform: uppercase;
@ -384,4 +383,4 @@ const LimitAlert = styled.p`
&.narrow { &.narrow {
margin: 8px 0 0; margin: 8px 0 0;
} }
`; `

View File

@ -1,42 +1,36 @@
import { EmojiData } from "emoji-mart"; import { EmojiData } from 'emoji-mart'
import React, { import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
useCallback, import styled from 'styled-components'
useEffect,
useMemo,
useRef,
useState,
} from "react";
import styled from "styled-components";
import { ChatState, useChatState } from "../../contexts/chatStateProvider"; import { ChatState, useChatState } from '../../contexts/chatStateProvider'
import { useIdentity } from "../../contexts/identityProvider"; import { useIdentity } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useModal } from "../../contexts/modalProvider"; import { useModal } from '../../contexts/modalProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { Reply } from "../../hooks/useReply"; import { Reply } from '../../hooks/useReply'
import { uintToImgUrl } from "../../utils/uintToImgUrl"; import { uintToImgUrl } from '../../utils/uintToImgUrl'
import { ClearBtn } from "../Form/inputStyles"; import { ClearBtn } from '../Form/inputStyles'
import { ClearSvg } from "../Icons/ClearIcon"; import { ClearSvg } from '../Icons/ClearIcon'
import { ClearSvgFull } from "../Icons/ClearIconFull"; import { ClearSvgFull } from '../Icons/ClearIconFull'
import { EmojiIcon } from "../Icons/EmojiIcon"; import { EmojiIcon } from '../Icons/EmojiIcon'
import { GifIcon } from "../Icons/GifIcon"; import { GifIcon } from '../Icons/GifIcon'
import { PictureIcon } from "../Icons/PictureIcon"; import { PictureIcon } from '../Icons/PictureIcon'
import { ReplySvg } from "../Icons/ReplyIcon"; import { ReplySvg } from '../Icons/ReplyIcon'
import { StickerIcon } from "../Icons/StickerIcon"; import { StickerIcon } from '../Icons/StickerIcon'
import "emoji-mart/css/emoji-mart.css"; import 'emoji-mart/css/emoji-mart.css'
import { SizeLimitModal, SizeLimitModalName } from "../Modals/SizeLimitModal"; import { SizeLimitModal, SizeLimitModalName } from '../Modals/SizeLimitModal'
import { UserCreationStartModalName } from "../Modals/UserCreationStartModal"; import { UserCreationStartModalName } from '../Modals/UserCreationStartModal'
import { SearchBlock } from "../SearchBlock"; import { SearchBlock } from '../SearchBlock'
import { textMediumStyles, textSmallStyles } from "../Text"; import { textMediumStyles, textSmallStyles } from '../Text'
import { EmojiPicker } from "./EmojiPicker"; import { EmojiPicker } from './EmojiPicker'
interface ChatInputProps { interface ChatInputProps {
reply?: Reply | undefined; reply?: Reply | undefined
setReply?: (val: Reply | undefined) => void; setReply?: (val: Reply | undefined) => void
createChat?: (group: string[]) => void; createChat?: (group: string[]) => void
group?: string[]; group?: string[]
} }
export function ChatInput({ export function ChatInput({
@ -45,109 +39,109 @@ export function ChatInput({
createChat, createChat,
group, group,
}: ChatInputProps) { }: ChatInputProps) {
const narrow = useNarrow(); const narrow = useNarrow()
const identity = useIdentity(); const identity = useIdentity()
const setChatState = useChatState()[1]; const setChatState = useChatState()[1]
const disabled = useMemo(() => !identity, [identity]); const disabled = useMemo(() => !identity, [identity])
const { sendMessage, contacts } = useMessengerContext(); const { sendMessage, contacts } = useMessengerContext()
const [content, setContent] = useState(""); const [content, setContent] = useState('')
const [clearComponent, setClearComponent] = useState(""); const [clearComponent, setClearComponent] = useState('')
const [showEmoji, setShowEmoji] = useState(false); const [showEmoji, setShowEmoji] = useState(false)
const [inputHeight, setInputHeight] = useState(40); const [inputHeight, setInputHeight] = useState(40)
const [imageUint, setImageUint] = useState<undefined | Uint8Array>(undefined); const [imageUint, setImageUint] = useState<undefined | Uint8Array>(undefined)
const { setModal } = useModal(SizeLimitModalName); const { setModal } = useModal(SizeLimitModalName)
const { setModal: setCreationStartModal } = useModal( const { setModal: setCreationStartModal } = useModal(
UserCreationStartModalName UserCreationStartModalName
); )
const [query, setQuery] = useState(""); const [query, setQuery] = useState('')
const inputRef = useRef<HTMLDivElement>(null); const inputRef = useRef<HTMLDivElement>(null)
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowEmoji(false)); useClickOutside(ref, () => setShowEmoji(false))
const image = useMemo( const image = useMemo(
() => (imageUint ? uintToImgUrl(imageUint) : ""), () => (imageUint ? uintToImgUrl(imageUint) : ''),
[imageUint] [imageUint]
); )
const addEmoji = useCallback( const addEmoji = useCallback(
(e: EmojiData) => { (e: EmojiData) => {
if ("unified" in e) { if ('unified' in e) {
const sym = e.unified.split("-"); const sym = e.unified.split('-')
const codesArray: string[] = []; const codesArray: string[] = []
sym.forEach((el: string) => codesArray.push("0x" + el)); sym.forEach((el: string) => codesArray.push('0x' + el))
const emoji = String.fromCodePoint( const emoji = String.fromCodePoint(
...(codesArray as unknown as number[]) ...(codesArray as unknown as number[])
); )
if (inputRef.current) { if (inputRef.current) {
inputRef.current.appendChild(document.createTextNode(emoji)); inputRef.current.appendChild(document.createTextNode(emoji))
} }
setContent((p) => p + emoji); setContent(p => p + emoji)
} }
}, },
[setContent] [setContent]
); )
const resizeTextArea = useCallback((target: HTMLDivElement) => { const resizeTextArea = useCallback((target: HTMLDivElement) => {
target.style.height = "40px"; target.style.height = '40px'
target.style.height = `${Math.min(target.scrollHeight, 438)}px`; target.style.height = `${Math.min(target.scrollHeight, 438)}px`
setInputHeight(target.scrollHeight); setInputHeight(target.scrollHeight)
}, []); }, [])
const rowHeight = inputHeight + (image ? 73 : 0); const rowHeight = inputHeight + (image ? 73 : 0)
const onInputChange = useCallback( const onInputChange = useCallback(
(e: React.ChangeEvent<HTMLDivElement>) => { (e: React.ChangeEvent<HTMLDivElement>) => {
const element = document.getSelection(); const element = document.getSelection()
const inputElement = inputRef.current; const inputElement = inputRef.current
if (inputElement && element && element.rangeCount > 0) { if (inputElement && element && element.rangeCount > 0) {
const selection = element?.getRangeAt(0)?.startOffset; const selection = element?.getRangeAt(0)?.startOffset
const parentElement = element.anchorNode?.parentElement; const parentElement = element.anchorNode?.parentElement
if (parentElement && parentElement.tagName === "B") { if (parentElement && parentElement.tagName === 'B') {
parentElement.outerHTML = parentElement.innerText; parentElement.outerHTML = parentElement.innerText
const range = document.createRange(); const range = document.createRange()
const sel = window.getSelection(); const sel = window.getSelection()
if (element.anchorNode.firstChild) { if (element.anchorNode.firstChild) {
const childNumber = const childNumber =
element.focusOffset === 0 ? 0 : element.focusOffset - 1; element.focusOffset === 0 ? 0 : element.focusOffset - 1
range.setStart( range.setStart(
element.anchorNode.childNodes[childNumber], element.anchorNode.childNodes[childNumber],
selection selection
); )
} }
range.collapse(true); range.collapse(true)
sel?.removeAllRanges(); sel?.removeAllRanges()
sel?.addRange(range); sel?.addRange(range)
} }
} }
const target = e.target; const target = e.target
resizeTextArea(target); resizeTextArea(target)
setContent(target.textContent ?? ""); setContent(target.textContent ?? '')
}, },
[resizeTextArea] [resizeTextArea]
); )
const onInputKeyPress = useCallback( const onInputKeyPress = useCallback(
(e: React.KeyboardEvent<HTMLDivElement>) => { (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.key == "Enter" && !e.getModifierState("Shift")) { if (e.key == 'Enter' && !e.getModifierState('Shift')) {
e.preventDefault(); e.preventDefault()
(e.target as HTMLDivElement).style.height = "40px"; ;(e.target as HTMLDivElement).style.height = '40px'
setInputHeight(40); setInputHeight(40)
sendMessage(content, imageUint, reply?.id); sendMessage(content, imageUint, reply?.id)
setImageUint(undefined); setImageUint(undefined)
setClearComponent(""); setClearComponent('')
if (inputRef.current) { if (inputRef.current) {
inputRef.current.innerHTML = ""; inputRef.current.innerHTML = ''
} }
setContent(""); setContent('')
if (setReply) setReply(undefined); if (setReply) setReply(undefined)
if (createChat && group) { if (createChat && group) {
createChat(group); createChat(group)
setChatState(ChatState.ChatBody); setChatState(ChatState.ChatBody)
} }
} }
}, },
@ -161,88 +155,88 @@ export function ChatInput({
setChatState, setChatState,
setReply, setReply,
] ]
); )
const [selectedElement, setSelectedElement] = useState<{ const [selectedElement, setSelectedElement] = useState<{
element: Selection | null; element: Selection | null
start: number; start: number
end: number; end: number
text: string; text: string
node: Node | null; node: Node | null
}>({ element: null, start: 0, end: 0, text: "", node: null }); }>({ element: null, start: 0, end: 0, text: '', node: null })
const handleCursorChange = useCallback(() => { const handleCursorChange = useCallback(() => {
const element = document.getSelection(); const element = document.getSelection()
if (element && element.rangeCount > 0) { if (element && element.rangeCount > 0) {
const selection = element?.getRangeAt(0)?.startOffset; const selection = element?.getRangeAt(0)?.startOffset
const text = element?.anchorNode?.textContent; const text = element?.anchorNode?.textContent
if (selection && text) { if (selection && text) {
const end = text.indexOf(" ", selection); const end = text.indexOf(' ', selection)
const start = text.lastIndexOf(" ", selection - 1); const start = text.lastIndexOf(' ', selection - 1)
setSelectedElement({ setSelectedElement({
element, element,
start, start,
end, end,
text, text,
node: element.anchorNode, node: element.anchorNode,
}); })
const substring = text.substring( const substring = text.substring(
start > -1 ? start + 1 : 0, start > -1 ? start + 1 : 0,
end > -1 ? end : undefined end > -1 ? end : undefined
); )
if (substring.startsWith("@")) { if (substring.startsWith('@')) {
setQuery(substring.slice(1)); setQuery(substring.slice(1))
} else { } else {
setQuery(""); setQuery('')
} }
} }
} }
}, []); }, [])
useEffect(handleCursorChange, [content, handleCursorChange]); useEffect(handleCursorChange, [content, handleCursorChange])
const addMention = useCallback( const addMention = useCallback(
(contact: string) => { (contact: string) => {
if (inputRef?.current) { if (inputRef?.current) {
const { element, start, end, text, node } = selectedElement; const { element, start, end, text, node } = selectedElement
if (element && text && node) { if (element && text && node) {
const firstSlice = text.slice(0, start > -1 ? start : 0); const firstSlice = text.slice(0, start > -1 ? start : 0)
const secondSlice = text.slice(end > -1 ? end : content.length); const secondSlice = text.slice(end > -1 ? end : content.length)
const replaceContent = `${firstSlice} @${contact}${secondSlice}`; const replaceContent = `${firstSlice} @${contact}${secondSlice}`
const spaceElement = document.createTextNode(" "); const spaceElement = document.createTextNode(' ')
const contactElement = document.createElement("span"); const contactElement = document.createElement('span')
contactElement.innerText = `@${contact}`; contactElement.innerText = `@${contact}`
if (contactElement && element.rangeCount > 0) { if (contactElement && element.rangeCount > 0) {
const range = element.getRangeAt(0); const range = element.getRangeAt(0)
range.setStart(node, start > -1 ? start : 0); range.setStart(node, start > -1 ? start : 0)
if (end === -1 || end > text.length) { if (end === -1 || end > text.length) {
range.setEnd(node, text.length); range.setEnd(node, text.length)
} else { } else {
range.setEnd(node, end); range.setEnd(node, end)
} }
range.deleteContents(); range.deleteContents()
if (end === -1) { if (end === -1) {
range.insertNode(spaceElement.cloneNode()); range.insertNode(spaceElement.cloneNode())
} }
range.insertNode(contactElement); range.insertNode(contactElement)
if (start > -1) { if (start > -1) {
range.insertNode(spaceElement.cloneNode()); range.insertNode(spaceElement.cloneNode())
} }
range.collapse(); range.collapse()
} }
inputRef.current.focus(); inputRef.current.focus()
setQuery(""); setQuery('')
setContent(replaceContent); setContent(replaceContent)
resizeTextArea(inputRef.current); resizeTextArea(inputRef.current)
} }
} }
}, },
[inputRef, content, selectedElement, resizeTextArea] [inputRef, content, selectedElement, resizeTextArea]
); )
return ( return (
<View className={`${createChat && "creation"}`}> <View className={`${createChat && 'creation'}`}>
<SizeLimitModal /> <SizeLimitModal />
<AddPictureInputWrapper> <AddPictureInputWrapper>
<PictureIcon /> <PictureIcon />
@ -251,18 +245,18 @@ export function ChatInput({
type="file" type="file"
multiple={true} multiple={true}
accept="image/png, image/jpeg" accept="image/png, image/jpeg"
onChange={(e) => { onChange={e => {
const fileReader = new FileReader(); const fileReader = new FileReader()
fileReader.onloadend = (s) => { fileReader.onloadend = s => {
const arr = new Uint8Array(s.target?.result as ArrayBuffer); const arr = new Uint8Array(s.target?.result as ArrayBuffer)
setImageUint(arr); setImageUint(arr)
}; }
if (e?.target?.files?.[0]) { if (e?.target?.files?.[0]) {
if (e.target.files[0].size < 1024 * 1024) { if (e.target.files[0].size < 1024 * 1024) {
fileReader.readAsArrayBuffer(e.target.files[0]); fileReader.readAsArrayBuffer(e.target.files[0])
} else { } else {
setModal(true); setModal(true)
} }
} }
}} }}
@ -272,8 +266,8 @@ export function ChatInput({
{reply && ( {reply && (
<ReplyWrapper> <ReplyWrapper>
<ReplyTo> <ReplyTo>
{" "} {' '}
<ReplySvg width={18} height={18} className="input" />{" "} <ReplySvg width={18} height={18} className="input" />{' '}
{contacts[reply.sender]?.customName ?? {contacts[reply.sender]?.customName ??
contacts[reply.sender].trueName} contacts[reply.sender].trueName}
</ReplyTo> </ReplyTo>
@ -281,10 +275,10 @@ export function ChatInput({
{reply.image && <ImagePreview src={reply.image} />} {reply.image && <ImagePreview src={reply.image} />}
<CloseButton <CloseButton
onClick={() => { onClick={() => {
if (setReply) setReply(undefined); if (setReply) setReply(undefined)
}} }}
> >
{" "} {' '}
<ClearSvg width={20} height={20} className="input" /> <ClearSvg width={20} height={20} className="input" />
</CloseButton> </CloseButton>
</ReplyWrapper> </ReplyWrapper>
@ -314,10 +308,10 @@ export function ChatInput({
onClick={handleCursorChange} onClick={handleCursorChange}
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: disabled __html: disabled
? "You need to join this community to send messages" ? 'You need to join this community to send messages'
: clearComponent, : clearComponent,
}} }}
className={`${disabled && "disabled"} `} className={`${disabled && 'disabled'} `}
/> />
)} )}
{query && ( {query && (
@ -333,7 +327,7 @@ export function ChatInput({
<EmojiWrapper ref={ref}> <EmojiWrapper ref={ref}>
<ChatButton <ChatButton
onClick={() => { onClick={() => {
if (!disabled) setShowEmoji(!showEmoji); if (!disabled) setShowEmoji(!showEmoji)
}} }}
disabled={disabled} disabled={disabled}
> >
@ -355,7 +349,7 @@ export function ChatInput({
</Row> </Row>
</InputArea> </InputArea>
</View> </View>
); )
} }
const InputWrapper = styled.div` const InputWrapper = styled.div`
@ -363,11 +357,11 @@ const InputWrapper = styled.div`
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
position: relative; position: relative;
`; `
const EmojiWrapper = styled.div` const EmojiWrapper = styled.div`
position: relative; position: relative;
`; `
const View = styled.div` const View = styled.div`
display: flex; display: flex;
@ -378,7 +372,7 @@ const View = styled.div`
&.creation { &.creation {
padding: 0; padding: 0;
} }
`; `
const InputArea = styled.div` const InputArea = styled.div`
position: relative; position: relative;
@ -389,7 +383,7 @@ const InputArea = styled.div`
padding: 2px; padding: 2px;
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
border-radius: 16px 16px 4px 16px; border-radius: 16px 16px 4px 16px;
`; `
const Row = styled.div` const Row = styled.div`
position: relative; position: relative;
@ -400,7 +394,7 @@ const Row = styled.div`
padding-right: 6px; padding-right: 6px;
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
border-radius: 16px 16px 4px 16px; border-radius: 16px 16px 4px 16px;
`; `
const InputButtons = styled.div` const InputButtons = styled.div`
display: flex; display: flex;
@ -409,19 +403,19 @@ const InputButtons = styled.div`
button + button { button + button {
margin-left: 4px; margin-left: 4px;
} }
`; `
const ImageWrapper = styled.div` const ImageWrapper = styled.div`
width: 64px; width: 64px;
position: relative; position: relative;
`; `
const ImagePreview = styled.img` const ImagePreview = styled.img`
width: 64px; width: 64px;
height: 64px; height: 64px;
border-radius: 16px 16px 4px 16px; border-radius: 16px 16px 4px 16px;
margin-left: 8px; margin-left: 8px;
margin-top: 9px; margin-top: 9px;
`; `
const ClearImgBtn = styled(ClearBtn)` const ClearImgBtn = styled(ClearBtn)`
width: 24px; width: 24px;
@ -432,7 +426,7 @@ const ClearImgBtn = styled(ClearBtn)`
padding: 0; padding: 0;
border: 2px solid ${({ theme }) => theme.inputColor}; border: 2px solid ${({ theme }) => theme.inputColor};
background-color: ${({ theme }) => theme.inputColor}; background-color: ${({ theme }) => theme.inputColor};
`; `
const Input = styled.div` const Input = styled.div`
display: block; display: block;
@ -480,7 +474,7 @@ const Input = styled.div`
cursor: default; cursor: default;
} }
} }
`; `
const AddPictureInputWrapper = styled.div` const AddPictureInputWrapper = styled.div`
position: relative; position: relative;
@ -491,14 +485,14 @@ const AddPictureInputWrapper = styled.div`
height: 32px; height: 32px;
margin-right: 4px; margin-right: 4px;
& > input[type="file"]::-webkit-file-upload-button { & > input[type='file']::-webkit-file-upload-button {
cursor: pointer; cursor: pointer;
} }
& > input:disabled::-webkit-file-upload-button { & > input:disabled::-webkit-file-upload-button {
cursor: default; cursor: default;
} }
`; `
const AddPictureInput = styled.input` const AddPictureInput = styled.input`
position: absolute; position: absolute;
@ -507,7 +501,7 @@ const AddPictureInput = styled.input`
width: 100%; width: 100%;
height: 100%; height: 100%;
opacity: 0; opacity: 0;
`; `
const ChatButton = styled.button` const ChatButton = styled.button`
width: 32px; width: 32px;
@ -516,13 +510,13 @@ const ChatButton = styled.button`
&:disabled { &:disabled {
cursor: default; cursor: default;
} }
`; `
const CloseButton = styled(ChatButton)` const CloseButton = styled(ChatButton)`
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
`; `
const ReplyWrapper = styled.div` const ReplyWrapper = styled.div`
display: flex; display: flex;
@ -533,14 +527,14 @@ const ReplyWrapper = styled.div`
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
border-radius: 14px 14px 4px 14px; border-radius: 14px 14px 4px 14px;
position: relative; position: relative;
`; `
export const ReplyTo = styled.div` export const ReplyTo = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
font-weight: 500; font-weight: 500;
${textSmallStyles}; ${textSmallStyles};
`; `
export const ReplyOn = styled.div` export const ReplyOn = styled.div`
width: 100%; width: 100%;
@ -548,7 +542,7 @@ export const ReplyOn = styled.div`
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
${textSmallStyles}; ${textSmallStyles};
`; `
const JoinBtn = styled.button` const JoinBtn = styled.button`
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
@ -559,4 +553,4 @@ const JoinBtn = styled.button`
text-align: start; text-align: start;
${textMediumStyles}; ${textMediumStyles};
`; `

View File

@ -1,39 +1,39 @@
import { decode } from "html-entities"; import { decode } from 'html-entities'
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useEffect, useMemo, useRef, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useFetchMetadata } from "../../contexts/fetchMetadataProvider"; import { useFetchMetadata } from '../../contexts/fetchMetadataProvider'
import { useUserPublicKey } from "../../contexts/identityProvider"; import { useUserPublicKey } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { ChatMessage } from "../../models/ChatMessage"; import { ChatMessage } from '../../models/ChatMessage'
import { Metadata } from "../../models/Metadata"; import { Metadata } from '../../models/Metadata'
import { ContactMenu } from "../Form/ContactMenu"; import { ContactMenu } from '../Form/ContactMenu'
import { ImageMenu } from "../Form/ImageMenu"; import { ImageMenu } from '../Form/ImageMenu'
import { textMediumStyles, textSmallStyles } from "../Text"; import { textMediumStyles, textSmallStyles } from '../Text'
interface MentionProps { interface MentionProps {
id: string; id: string
setMentioned: (val: boolean) => void; setMentioned: (val: boolean) => void
className?: string; className?: string
} }
export function Mention({ id, setMentioned, className }: MentionProps) { export function Mention({ id, setMentioned, className }: MentionProps) {
const { contacts } = useMessengerContext(); const { contacts } = useMessengerContext()
const contact = useMemo(() => contacts[id.slice(1)], [id, contacts]); const contact = useMemo(() => contacts[id.slice(1)], [id, contacts])
const [showMenu, setShowMenu] = useState(false); const [showMenu, setShowMenu] = useState(false)
const userPK = useUserPublicKey(); const userPK = useUserPublicKey()
useEffect(() => { useEffect(() => {
if (userPK && contact) { if (userPK && contact) {
if (contact.id === userPK) setMentioned(true); if (contact.id === userPK) setMentioned(true)
} }
}, [contact, userPK, setMentioned]); }, [contact, userPK, setMentioned])
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowMenu(false)); useClickOutside(ref, () => setShowMenu(false))
if (!contact) return <>{id}</>; if (!contact) return <>{id}</>
return ( return (
<MentionBLock <MentionBLock
onClick={() => setShowMenu(!showMenu)} onClick={() => setShowMenu(!showMenu)}
@ -43,15 +43,15 @@ export function Mention({ id, setMentioned, className }: MentionProps) {
{`@${contact?.customName ?? contact.trueName}`} {`@${contact?.customName ?? contact.trueName}`}
{showMenu && <ContactMenu id={id.slice(1)} setShowMenu={setShowMenu} />} {showMenu && <ContactMenu id={id.slice(1)} setShowMenu={setShowMenu} />}
</MentionBLock> </MentionBLock>
); )
} }
type ChatMessageContentProps = { type ChatMessageContentProps = {
message: ChatMessage; message: ChatMessage
setImage: (image: string) => void; setImage: (image: string) => void
setLinkOpen: (link: string) => void; setLinkOpen: (link: string) => void
setMentioned: (val: boolean) => void; setMentioned: (val: boolean) => void
}; }
export function ChatMessageContent({ export function ChatMessageContent({
message, message,
@ -59,82 +59,82 @@ export function ChatMessageContent({
setLinkOpen, setLinkOpen,
setMentioned, setMentioned,
}: ChatMessageContentProps) { }: ChatMessageContentProps) {
const fetchMetadata = useFetchMetadata(); const fetchMetadata = useFetchMetadata()
const { content, image } = useMemo(() => message, [message]); const { content, image } = useMemo(() => message, [message])
const [elements, setElements] = useState<(string | React.ReactElement)[]>([ const [elements, setElements] = useState<(string | React.ReactElement)[]>([
content, content,
]); ])
const [link, setLink] = useState<string | undefined>(undefined); const [link, setLink] = useState<string | undefined>(undefined)
const [openGraph, setOpenGraph] = useState<Metadata | undefined>(undefined); const [openGraph, setOpenGraph] = useState<Metadata | undefined>(undefined)
useEffect(() => { useEffect(() => {
let link; let link
const split = content.split(" "); const split = content.split(' ')
const newSplit = split.flatMap((element, idx) => { const newSplit = split.flatMap((element, idx) => {
if (element.startsWith("http://") || element.startsWith("https://")) { if (element.startsWith('http://') || element.startsWith('https://')) {
link = element; link = element
return [ return [
<Link key={idx} onClick={() => setLinkOpen(element)}> <Link key={idx} onClick={() => setLinkOpen(element)}>
{element} {element}
</Link>, </Link>,
" ", ' ',
]; ]
} }
if (element.startsWith("@")) { if (element.startsWith('@')) {
return [ return [
<Mention key={idx} id={element} setMentioned={setMentioned} />, <Mention key={idx} id={element} setMentioned={setMentioned} />,
" ", ' ',
]; ]
} }
return [element, " "]; return [element, ' ']
}); })
newSplit.pop(); newSplit.pop()
setLink(link); setLink(link)
setElements(newSplit); setElements(newSplit)
}, [content, setLink, setMentioned, setElements, setLinkOpen]); }, [content, setLink, setMentioned, setElements, setLinkOpen])
useEffect(() => { useEffect(() => {
const updatePreview = async () => { const updatePreview = async () => {
if (link && fetchMetadata) { if (link && fetchMetadata) {
try { try {
const metadata = await fetchMetadata(link); const metadata = await fetchMetadata(link)
if (metadata) { if (metadata) {
setOpenGraph(metadata); setOpenGraph(metadata)
} }
} catch { } catch {
return; return
} }
} }
}; }
updatePreview(); updatePreview()
}, [link, fetchMetadata]); }, [link, fetchMetadata])
return ( return (
<ContentWrapper> <ContentWrapper>
<div>{elements.map((el) => el)}</div> <div>{elements.map(el => el)}</div>
{image && ( {image && (
<MessageImageWrapper> <MessageImageWrapper>
<MessageImage <MessageImage
src={image} src={image}
id={image} id={image}
onClick={() => { onClick={() => {
setImage(image); setImage(image)
}} }}
/> />
<ImageMenu imageId={image} /> <ImageMenu imageId={image} />
</MessageImageWrapper> </MessageImageWrapper>
)} )}
{openGraph && ( {openGraph && (
<PreviewWrapper onClick={() => setLinkOpen(link ?? "")}> <PreviewWrapper onClick={() => setLinkOpen(link ?? '')}>
<PreviewImage src={decodeURI(decode(openGraph["og:image"]))} /> <PreviewImage src={decodeURI(decode(openGraph['og:image']))} />
<PreviewTitleWrapper>{openGraph["og:title"]}</PreviewTitleWrapper> <PreviewTitleWrapper>{openGraph['og:title']}</PreviewTitleWrapper>
<PreviewSiteNameWrapper> <PreviewSiteNameWrapper>
{openGraph["og:site_name"]} {openGraph['og:site_name']}
</PreviewSiteNameWrapper> </PreviewSiteNameWrapper>
</PreviewWrapper> </PreviewWrapper>
)} )}
</ContentWrapper> </ContentWrapper>
); )
} }
const MessageImageWrapper = styled.div` const MessageImageWrapper = styled.div`
@ -142,7 +142,7 @@ const MessageImageWrapper = styled.div`
height: 196px; height: 196px;
margin-top: 8px; margin-top: 8px;
position: relative; position: relative;
`; `
const MessageImage = styled.img` const MessageImage = styled.img`
width: 100%; width: 100%;
@ -150,10 +150,10 @@ const MessageImage = styled.img`
object-fit: cover; object-fit: cover;
border-radius: 16px; border-radius: 16px;
cursor: pointer; cursor: pointer;
`; `
const PreviewSiteNameWrapper = styled.div` const PreviewSiteNameWrapper = styled.div`
font-family: "Inter"; font-family: 'Inter';
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
font-size: 12px; font-size: 12px;
@ -162,7 +162,7 @@ const PreviewSiteNameWrapper = styled.div`
margin-top: 2px; margin-top: 2px;
color: #939ba1; color: #939ba1;
margin-left: 12px; margin-left: 12px;
`; `
const PreviewTitleWrapper = styled.div` const PreviewTitleWrapper = styled.div`
margin-top: 7px; margin-top: 7px;
@ -176,13 +176,13 @@ const PreviewTitleWrapper = styled.div`
margin-left: 12px; margin-left: 12px;
${textSmallStyles} ${textSmallStyles}
`; `
const PreviewImage = styled.img` const PreviewImage = styled.img`
border-radius: 15px 15px 15px 4px; border-radius: 15px 15px 15px 4px;
width: 305px; width: 305px;
height: 170px; height: 170px;
`; `
const PreviewWrapper = styled.div` const PreviewWrapper = styled.div`
margin-top: 9px; margin-top: 9px;
@ -195,12 +195,12 @@ const PreviewWrapper = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0px; padding: 0px;
`; `
const ContentWrapper = styled.div` const ContentWrapper = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
`; `
const MentionBLock = styled.div` const MentionBLock = styled.div`
display: inline-flex; display: inline-flex;
@ -224,10 +224,10 @@ const MentionBLock = styled.div`
} }
${textMediumStyles} ${textMediumStyles}
`; `
const Link = styled.a` const Link = styled.a`
text-decoration: underline; text-decoration: underline;
cursor: pointer; cursor: pointer;
color: ${({ theme }) => theme.memberNameColor}; color: ${({ theme }) => theme.memberNameColor};
`; `

View File

@ -1,30 +1,30 @@
import React, { useRef, useState } from "react"; import React, { useRef, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { import {
ActivityButton, ActivityButton,
ActivityWrapper, ActivityWrapper,
} from "../ActivityCenter/ActivityButton"; } from '../ActivityCenter/ActivityButton'
import { Channel } from "../Channels/Channel"; import { Channel } from '../Channels/Channel'
import { Community } from "../Community"; import { Community } from '../Community'
import { ChannelMenu } from "../Form/ChannelMenu"; import { ChannelMenu } from '../Form/ChannelMenu'
import { ActivityIcon } from "../Icons/ActivityIcon"; import { ActivityIcon } from '../Icons/ActivityIcon'
import { MembersIcon } from "../Icons/MembersIcon"; import { MembersIcon } from '../Icons/MembersIcon'
import { MoreIcon } from "../Icons/MoreIcon"; import { MoreIcon } from '../Icons/MoreIcon'
import { CommunitySkeleton } from "../Skeleton/CommunitySkeleton"; import { CommunitySkeleton } from '../Skeleton/CommunitySkeleton'
import { Loading } from "../Skeleton/Loading"; import { Loading } from '../Skeleton/Loading'
import { ChatBodyState } from "./ChatBody"; import { ChatBodyState } from './ChatBody'
export function ChatTopbarLoading() { export function ChatTopbarLoading() {
const narrow = useNarrow(); const narrow = useNarrow()
return ( return (
<Topbar className={narrow ? "narrow" : ""}> <Topbar className={narrow ? 'narrow' : ''}>
<ChannelWrapper className={narrow ? "narrow" : ""}> <ChannelWrapper className={narrow ? 'narrow' : ''}>
<SkeletonWrapper> <SkeletonWrapper>
<CommunitySkeleton /> <CommunitySkeleton />
</SkeletonWrapper> </SkeletonWrapper>
@ -46,16 +46,16 @@ export function ChatTopbarLoading() {
</MenuWrapper> </MenuWrapper>
<Loading /> <Loading />
</Topbar> </Topbar>
); )
} }
type ChatTopbarProps = { type ChatTopbarProps = {
showState: ChatBodyState; showState: ChatBodyState
onClick: () => void; onClick: () => void
switchShowState: (state: ChatBodyState) => void; switchShowState: (state: ChatBodyState) => void
showMembers: boolean; showMembers: boolean
setEditGroup: React.Dispatch<React.SetStateAction<boolean>>; setEditGroup: React.Dispatch<React.SetStateAction<boolean>>
}; }
export function ChatTopbar({ export function ChatTopbar({
showState, showState,
@ -64,27 +64,27 @@ export function ChatTopbar({
showMembers, showMembers,
setEditGroup, setEditGroup,
}: ChatTopbarProps) { }: ChatTopbarProps) {
const { activeChannel, loadingMessenger } = useMessengerContext(); const { activeChannel, loadingMessenger } = useMessengerContext()
const narrow = useNarrow(); const narrow = useNarrow()
const [showChannelMenu, setShowChannelMenu] = useState(false); const [showChannelMenu, setShowChannelMenu] = useState(false)
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowChannelMenu(false)); useClickOutside(ref, () => setShowChannelMenu(false))
if (!activeChannel) { if (!activeChannel) {
return <ChatTopbarLoading />; return <ChatTopbarLoading />
} }
return ( return (
<Topbar <Topbar
className={narrow && showState !== ChatBodyState.Chat ? "narrow" : ""} className={narrow && showState !== ChatBodyState.Chat ? 'narrow' : ''}
> >
<ChannelWrapper className={narrow ? "narrow" : ""}> <ChannelWrapper className={narrow ? 'narrow' : ''}>
{!loadingMessenger ? ( {!loadingMessenger ? (
<> <>
{narrow && ( {narrow && (
<CommunityWrap className={narrow ? "narrow" : ""}> <CommunityWrap className={narrow ? 'narrow' : ''}>
<Community /> <Community />
</CommunityWrap> </CommunityWrap>
)} )}
@ -104,8 +104,8 @@ export function ChatTopbar({
</ChannelWrapper> </ChannelWrapper>
<MenuWrapper> <MenuWrapper>
{!narrow && activeChannel.type !== "dm" && ( {!narrow && activeChannel.type !== 'dm' && (
<TopBtn onClick={onClick} className={showMembers ? "active" : ""}> <TopBtn onClick={onClick} className={showMembers ? 'active' : ''}>
<MembersIcon /> <MembersIcon />
</TopBtn> </TopBtn>
)} )}
@ -119,7 +119,7 @@ export function ChatTopbar({
switchMemberList={() => switchShowState(ChatBodyState.Members)} switchMemberList={() => switchShowState(ChatBodyState.Members)}
setShowChannelMenu={setShowChannelMenu} setShowChannelMenu={setShowChannelMenu}
setEditGroup={setEditGroup} setEditGroup={setEditGroup}
className={`${narrow && "narrow"}`} className={`${narrow && 'narrow'}`}
/> />
)} )}
</TopBtn> </TopBtn>
@ -128,7 +128,7 @@ export function ChatTopbar({
</MenuWrapper> </MenuWrapper>
{loadingMessenger && <Loading />} {loadingMessenger && <Loading />}
</Topbar> </Topbar>
); )
} }
const Topbar = styled.div` const Topbar = styled.div`
@ -142,7 +142,7 @@ const Topbar = styled.div`
&.narrow { &.narrow {
width: 100%; width: 100%;
} }
`; `
const ChannelWrapper = styled.div` const ChannelWrapper = styled.div`
display: flex; display: flex;
@ -152,11 +152,11 @@ const ChannelWrapper = styled.div`
&.narrow { &.narrow {
width: calc(100% - 46px); width: calc(100% - 46px);
} }
`; `
const SkeletonWrapper = styled.div` const SkeletonWrapper = styled.div`
padding: 8px; padding: 8px;
`; `
const CommunityWrap = styled.div` const CommunityWrap = styled.div`
padding-right: 10px; padding-right: 10px;
@ -168,7 +168,7 @@ const CommunityWrap = styled.div`
} }
&:after { &:after {
content: ""; content: '';
position: absolute; position: absolute;
right: 0; right: 0;
top: 50%; top: 50%;
@ -179,13 +179,13 @@ const CommunityWrap = styled.div`
background: ${({ theme }) => theme.primary}; background: ${({ theme }) => theme.primary};
opacity: 0.1; opacity: 0.1;
} }
`; `
const MenuWrapper = styled.div` const MenuWrapper = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
padding: 8px 0; padding: 8px 0;
`; `
export const TopBtn = styled.button` export const TopBtn = styled.button`
width: 32px; width: 32px;
@ -206,4 +206,4 @@ export const TopBtn = styled.button`
&:disabled { &:disabled {
cursor: default; cursor: default;
} }
`; `

View File

@ -1,41 +1,41 @@
import { EmojiData, Picker } from "emoji-mart"; import { EmojiData, Picker } from 'emoji-mart'
import React from "react"; import React from 'react'
import { useTheme } from "styled-components"; import { useTheme } from 'styled-components'
import { useLow } from "../../contexts/narrowProvider"; import { useLow } from '../../contexts/narrowProvider'
import { lightTheme, Theme } from "../../styles/themes"; import { lightTheme, Theme } from '../../styles/themes'
type EmojiPickerProps = { type EmojiPickerProps = {
showEmoji: boolean; showEmoji: boolean
addEmoji: (e: EmojiData) => void; addEmoji: (e: EmojiData) => void
bottom: number; bottom: number
}; }
export function EmojiPicker({ showEmoji, addEmoji, bottom }: EmojiPickerProps) { export function EmojiPicker({ showEmoji, addEmoji, bottom }: EmojiPickerProps) {
const theme = useTheme() as Theme; const theme = useTheme() as Theme
const low = useLow(); const low = useLow()
if (showEmoji) { if (showEmoji) {
return ( return (
<Picker <Picker
onSelect={addEmoji} onSelect={addEmoji}
theme={theme === lightTheme ? "light" : "dark"} theme={theme === lightTheme ? 'light' : 'dark'}
set="twitter" set="twitter"
color={theme.tertiary} color={theme.tertiary}
emojiSize={26} emojiSize={26}
style={{ style={{
position: "absolute", position: 'absolute',
bottom: `calc(100% + ${bottom}px)`, bottom: `calc(100% + ${bottom}px)`,
right: "-76px", right: '-76px',
color: theme.secondary, color: theme.secondary,
height: low ? "200px" : "355px", height: low ? '200px' : '355px',
overflow: "auto", overflow: 'auto',
}} }}
showPreview={false} showPreview={false}
showSkinTones={false} showSkinTones={false}
title={""} title={''}
/> />
); )
} }
return null; return null
} }

View File

@ -1,27 +1,27 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../contexts/messengerProvider"; import { useMessengerContext } from '../contexts/messengerProvider'
import { useModal } from "../contexts/modalProvider"; import { useModal } from '../contexts/modalProvider'
import { CommunityIdentity } from "./CommunityIdentity"; import { CommunityIdentity } from './CommunityIdentity'
import { CommunityModalName } from "./Modals/CommunityModal"; import { CommunityModalName } from './Modals/CommunityModal'
import { CommunitySkeleton } from "./Skeleton/CommunitySkeleton"; import { CommunitySkeleton } from './Skeleton/CommunitySkeleton'
interface CommunityProps { interface CommunityProps {
className?: string; className?: string
} }
export function Community({ className }: CommunityProps) { export function Community({ className }: CommunityProps) {
const { communityData } = useMessengerContext(); const { communityData } = useMessengerContext()
const { setModal } = useModal(CommunityModalName); const { setModal } = useModal(CommunityModalName)
if (!communityData) { if (!communityData) {
return ( return (
<SkeletonWrapper> <SkeletonWrapper>
<CommunitySkeleton /> <CommunitySkeleton />
</SkeletonWrapper> </SkeletonWrapper>
); )
} }
return ( return (
@ -30,9 +30,9 @@ export function Community({ className }: CommunityProps) {
<CommunityIdentity subtitle={`${communityData.members} members`} /> <CommunityIdentity subtitle={`${communityData.members} members`} />
</button> </button>
</> </>
); )
} }
const SkeletonWrapper = styled.div` const SkeletonWrapper = styled.div`
margin-bottom: 16px; margin-bottom: 16px;
`; `

View File

@ -1,28 +1,28 @@
import React, { useRef } from "react"; import React, { useRef } from 'react'
import { ThemeProvider } from "styled-components"; import { ThemeProvider } from 'styled-components'
import styled from "styled-components"; import styled from 'styled-components'
import { ConfigType } from ".."; import { ConfigType } from '..'
import { ChatStateProvider } from "../contexts/chatStateProvider"; import { ChatStateProvider } from '../contexts/chatStateProvider'
import { ConfigProvider } from "../contexts/configProvider"; import { ConfigProvider } from '../contexts/configProvider'
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider"; import { FetchMetadataProvider } from '../contexts/fetchMetadataProvider'
import { IdentityProvider } from "../contexts/identityProvider"; import { IdentityProvider } from '../contexts/identityProvider'
import { MessengerProvider } from "../contexts/messengerProvider"; import { MessengerProvider } from '../contexts/messengerProvider'
import { ModalProvider } from "../contexts/modalProvider"; import { ModalProvider } from '../contexts/modalProvider'
import { NarrowProvider } from "../contexts/narrowProvider"; import { NarrowProvider } from '../contexts/narrowProvider'
import { ScrollProvider } from "../contexts/scrollProvider"; import { ScrollProvider } from '../contexts/scrollProvider'
import { ToastProvider } from "../contexts/toastProvider"; import { ToastProvider } from '../contexts/toastProvider'
import { Metadata } from "../models/Metadata"; import { Metadata } from '../models/Metadata'
import { GlobalStyle } from "../styles/GlobalStyle"; import { GlobalStyle } from '../styles/GlobalStyle'
import { Theme } from "../styles/themes"; import { Theme } from '../styles/themes'
import { CommunityChatRoom } from "./CommunityChatRoom"; import { CommunityChatRoom } from './CommunityChatRoom'
interface CommunityChatProps { interface CommunityChatProps {
theme: Theme; theme: Theme
communityKey: string; communityKey: string
config: ConfigType; config: ConfigType
fetchMetadata?: (url: string) => Promise<Metadata | undefined>; fetchMetadata?: (url: string) => Promise<Metadata | undefined>
} }
export function CommunityChat({ export function CommunityChat({
@ -31,7 +31,7 @@ export function CommunityChat({
fetchMetadata, fetchMetadata,
communityKey, communityKey,
}: CommunityChatProps) { }: CommunityChatProps) {
const ref = useRef<HTMLHeadingElement>(null); const ref = useRef<HTMLHeadingElement>(null)
return ( return (
<ConfigProvider config={config}> <ConfigProvider config={config}>
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
@ -58,10 +58,10 @@ export function CommunityChat({
</NarrowProvider> </NarrowProvider>
</ThemeProvider> </ThemeProvider>
</ConfigProvider> </ConfigProvider>
); )
} }
const Wrapper = styled.div` const Wrapper = styled.div`
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
`; `

View File

@ -1,29 +1,29 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { ChatState, useChatState } from "../contexts/chatStateProvider"; import { ChatState, useChatState } from '../contexts/chatStateProvider'
import { useMessengerContext } from "../contexts/messengerProvider"; import { useMessengerContext } from '../contexts/messengerProvider'
import { useNarrow } from "../contexts/narrowProvider"; import { useNarrow } from '../contexts/narrowProvider'
import { Channels } from "./Channels/Channels"; import { Channels } from './Channels/Channels'
import { ChatBody } from "./Chat/ChatBody"; import { ChatBody } from './Chat/ChatBody'
import { ChatCreation } from "./Chat/ChatCreation"; import { ChatCreation } from './Chat/ChatCreation'
import { Community } from "./Community"; import { Community } from './Community'
import { Members } from "./Members/Members"; import { Members } from './Members/Members'
import { AgreementModal } from "./Modals/AgreementModal"; import { AgreementModal } from './Modals/AgreementModal'
import { CoinbaseModal } from "./Modals/CoinbaseModal"; import { CoinbaseModal } from './Modals/CoinbaseModal'
import { CommunityModal } from "./Modals/CommunityModal"; import { CommunityModal } from './Modals/CommunityModal'
import { EditModal } from "./Modals/EditModal"; import { EditModal } from './Modals/EditModal'
import { LeavingModal } from "./Modals/LeavingModal"; import { LeavingModal } from './Modals/LeavingModal'
import { LogoutModal } from "./Modals/LogoutModal"; import { LogoutModal } from './Modals/LogoutModal'
import { ProfileFoundModal } from "./Modals/ProfileFoundModal"; import { ProfileFoundModal } from './Modals/ProfileFoundModal'
import { ProfileModal } from "./Modals/ProfileModal"; import { ProfileModal } from './Modals/ProfileModal'
import { StatusModal } from "./Modals/StatusModal"; import { StatusModal } from './Modals/StatusModal'
import { UserCreationModal } from "./Modals/UserCreationModal"; import { UserCreationModal } from './Modals/UserCreationModal'
import { UserCreationStartModal } from "./Modals/UserCreationStartModal"; import { UserCreationStartModal } from './Modals/UserCreationStartModal'
import { WalletConnectModal } from "./Modals/WalletConnectModal"; import { WalletConnectModal } from './Modals/WalletConnectModal'
import { WalletModal } from "./Modals/WalletModal"; import { WalletModal } from './Modals/WalletModal'
import { ToastMessageList } from "./ToastMessages/ToastMessageList"; import { ToastMessageList } from './ToastMessages/ToastMessageList'
function Modals() { function Modals() {
return ( return (
@ -42,15 +42,15 @@ function Modals() {
<UserCreationStartModal /> <UserCreationStartModal />
<LeavingModal /> <LeavingModal />
</> </>
); )
} }
export function CommunityChatRoom() { export function CommunityChatRoom() {
const [state] = useChatState(); const [state] = useChatState()
const [showMembers, setShowMembers] = useState(false); const [showMembers, setShowMembers] = useState(false)
const [editGroup, setEditGroup] = useState(false); const [editGroup, setEditGroup] = useState(false)
const narrow = useNarrow(); const narrow = useNarrow()
const { activeChannel } = useMessengerContext(); const { activeChannel } = useMessengerContext()
return ( return (
<ChatWrapper> <ChatWrapper>
@ -73,12 +73,12 @@ export function CommunityChatRoom() {
!narrow && !narrow &&
state === ChatState.ChatBody && state === ChatState.ChatBody &&
activeChannel && activeChannel &&
activeChannel.type !== "dm" && <Members />} activeChannel.type !== 'dm' && <Members />}
{state === ChatState.ChatCreation && <ChatCreation />} {state === ChatState.ChatCreation && <ChatCreation />}
<Modals /> <Modals />
<ToastMessageList /> <ToastMessageList />
</ChatWrapper> </ChatWrapper>
); )
} }
const ChatWrapper = styled.div` const ChatWrapper = styled.div`
@ -86,7 +86,7 @@ const ChatWrapper = styled.div`
height: 100%; height: 100%;
display: flex; display: flex;
position: relative; position: relative;
`; `
const ChannelsWrapper = styled.div` const ChannelsWrapper = styled.div`
width: 21%; width: 21%;
@ -96,9 +96,9 @@ const ChannelsWrapper = styled.div`
padding: 10px 16px; padding: 10px 16px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
`; `
const StyledCommunity = styled(Community)` const StyledCommunity = styled(Community)`
padding: 0 0 0 8px; padding: 0 0 0 8px;
margin: 0 0 16px; margin: 0 0 16px;
`; `

View File

@ -1,20 +1,20 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../contexts/messengerProvider"; import { useMessengerContext } from '../contexts/messengerProvider'
import { textMediumStyles } from "./Text"; import { textMediumStyles } from './Text'
export interface CommunityIdentityProps { export interface CommunityIdentityProps {
subtitle: string; subtitle: string
className?: string; className?: string
} }
export const CommunityIdentity = ({ export const CommunityIdentity = ({
subtitle, subtitle,
className, className,
}: CommunityIdentityProps) => { }: CommunityIdentityProps) => {
const { communityData } = useMessengerContext(); const { communityData } = useMessengerContext()
return ( return (
<Row className={className}> <Row className={className}>
@ -22,10 +22,10 @@ export const CommunityIdentity = ({
style={{ style={{
backgroundImage: communityData?.icon backgroundImage: communityData?.icon
? `url(${communityData?.icon}` ? `url(${communityData?.icon}`
: "", : '',
}} }}
> >
{" "} {' '}
{communityData?.icon === undefined && {communityData?.icon === undefined &&
communityData?.name.slice(0, 1).toUpperCase()} communityData?.name.slice(0, 1).toUpperCase()}
</Logo> </Logo>
@ -34,18 +34,18 @@ export const CommunityIdentity = ({
<Subtitle>{subtitle}</Subtitle> <Subtitle>{subtitle}</Subtitle>
</Column> </Column>
</Row> </Row>
); )
}; }
const Row = styled.div` const Row = styled.div`
display: flex; display: flex;
`; `
export const Column = styled.div` export const Column = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
`; `
export const Logo = styled.div` export const Logo = styled.div`
width: 36px; width: 36px;
@ -63,22 +63,22 @@ export const Logo = styled.div`
font-weight: bold; font-weight: bold;
font-size: 15px; font-size: 15px;
line-height: 20px; line-height: 20px;
`; `
const Name = styled.p` const Name = styled.p`
font-family: "Inter", sans-serif; font-family: 'Inter', sans-serif;
font-weight: 500; font-weight: 500;
text-align: left; text-align: left;
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
white-space: nowrap; white-space: nowrap;
${textMediumStyles} ${textMediumStyles}
`; `
const Subtitle = styled.p` const Subtitle = styled.p`
font-family: "Inter", sans-serif; font-family: 'Inter', sans-serif;
font-size: 12px; font-size: 12px;
line-height: 16px; line-height: 16px;
letter-spacing: 0.1px; letter-spacing: 0.1px;
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
`; `

View File

@ -1,36 +1,36 @@
import React, { useMemo, useRef, useState } from "react"; import React, { useMemo, useRef, useState } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useModal } from "../../contexts/modalProvider"; import { useModal } from '../../contexts/modalProvider'
import { useNarrow } from "../../contexts/narrowProvider"; import { useNarrow } from '../../contexts/narrowProvider'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { useContextMenu } from "../../hooks/useContextMenu"; import { useContextMenu } from '../../hooks/useContextMenu'
import { ChannelData } from "../../models/ChannelData"; import { ChannelData } from '../../models/ChannelData'
import { AddMemberIcon } from "../Icons/AddMemberIcon"; import { AddMemberIcon } from '../Icons/AddMemberIcon'
import { CheckIcon } from "../Icons/CheckIcon"; import { CheckIcon } from '../Icons/CheckIcon'
import { DeleteIcon } from "../Icons/DeleteIcon"; import { DeleteIcon } from '../Icons/DeleteIcon'
import { DownloadIcon } from "../Icons/DownloadIcon"; import { DownloadIcon } from '../Icons/DownloadIcon'
import { EditIcon } from "../Icons/EditIcon"; import { EditIcon } from '../Icons/EditIcon'
import { LeftIcon } from "../Icons/LeftIcon"; import { LeftIcon } from '../Icons/LeftIcon'
import { MembersSmallIcon } from "../Icons/MembersSmallIcon"; import { MembersSmallIcon } from '../Icons/MembersSmallIcon'
import { MuteIcon } from "../Icons/MuteIcon"; import { MuteIcon } from '../Icons/MuteIcon'
import { NextIcon } from "../Icons/NextIcon"; import { NextIcon } from '../Icons/NextIcon'
import { ProfileIcon } from "../Icons/ProfileIcon"; import { ProfileIcon } from '../Icons/ProfileIcon'
import { EditModalName } from "../Modals/EditModal"; import { EditModalName } from '../Modals/EditModal'
import { LeavingModalName } from "../Modals/LeavingModal"; import { LeavingModalName } from '../Modals/LeavingModal'
import { ProfileModalName } from "../Modals/ProfileModal"; import { ProfileModalName } from '../Modals/ProfileModal'
import { DropdownMenu, MenuItem, MenuSection, MenuText } from "./DropdownMenu"; import { DropdownMenu, MenuItem, MenuSection, MenuText } from './DropdownMenu'
import { MuteMenu } from "./MuteMenu"; import { MuteMenu } from './MuteMenu'
interface ChannelMenuProps { interface ChannelMenuProps {
channel: ChannelData; channel: ChannelData
setShowChannelMenu?: (val: boolean) => void; setShowChannelMenu?: (val: boolean) => void
showNarrowMembers?: boolean; showNarrowMembers?: boolean
switchMemberList?: () => void; switchMemberList?: () => void
setEditGroup?: (val: boolean) => void; setEditGroup?: (val: boolean) => void
className?: string; className?: string
} }
export const ChannelMenu = ({ export const ChannelMenu = ({
@ -41,45 +41,45 @@ export const ChannelMenu = ({
setEditGroup, setEditGroup,
className, className,
}: ChannelMenuProps) => { }: ChannelMenuProps) => {
const narrow = useNarrow(); const narrow = useNarrow()
const { clearNotifications, channelsDispatch } = useMessengerContext(); const { clearNotifications, channelsDispatch } = useMessengerContext()
const { setModal } = useModal(EditModalName); const { setModal } = useModal(EditModalName)
const { setModal: setLeavingModal } = useModal(LeavingModalName); const { setModal: setLeavingModal } = useModal(LeavingModalName)
const { setModal: setProfileModal } = useModal(ProfileModalName); const { setModal: setProfileModal } = useModal(ProfileModalName)
const [showSubmenu, setShowSubmenu] = useState(false); const [showSubmenu, setShowSubmenu] = useState(false)
const { showMenu, setShowMenu: setShowSideMenu } = useContextMenu( const { showMenu, setShowMenu: setShowSideMenu } = useContextMenu(
channel.id + "contextMenu" channel.id + 'contextMenu'
); )
const setShowMenu = useMemo( const setShowMenu = useMemo(
() => (setShowChannelMenu ? setShowChannelMenu : setShowSideMenu), () => (setShowChannelMenu ? setShowChannelMenu : setShowSideMenu),
[setShowChannelMenu, setShowSideMenu] [setShowChannelMenu, setShowSideMenu]
); )
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowMenu(false)); useClickOutside(ref, () => setShowMenu(false))
if (showMenu || setShowChannelMenu) { if (showMenu || setShowChannelMenu) {
return ( return (
<ChannelDropdown className={className} menuRef={ref}> <ChannelDropdown className={className} menuRef={ref}>
{narrow && channel.type !== "dm" && ( {narrow && channel.type !== 'dm' && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
if (switchMemberList) switchMemberList(); if (switchMemberList) switchMemberList()
setShowMenu(false); setShowMenu(false)
}} }}
> >
<MembersSmallIcon width={16} height={16} /> <MembersSmallIcon width={16} height={16} />
<MenuText>{showNarrowMembers ? "Hide" : "View"} Members</MenuText> <MenuText>{showNarrowMembers ? 'Hide' : 'View'} Members</MenuText>
</MenuItem> </MenuItem>
)} )}
{channel.type === "group" && ( {channel.type === 'group' && (
<> <>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
if (setEditGroup) setEditGroup(true); if (setEditGroup) setEditGroup(true)
setShowMenu(false); setShowMenu(false)
}} }}
> >
<AddMemberIcon width={16} height={16} /> <AddMemberIcon width={16} height={16} />
@ -91,50 +91,50 @@ export const ChannelMenu = ({
</MenuItem> </MenuItem>
</> </>
)} )}
{channel.type === "dm" && ( {channel.type === 'dm' && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setProfileModal({ setProfileModal({
id: channel.name, id: channel.name,
renamingState: false, renamingState: false,
requestState: false, requestState: false,
}); })
setShowMenu(false); setShowMenu(false)
}} }}
> >
<ProfileIcon width={16} height={16} /> <ProfileIcon width={16} height={16} />
<MenuText>View Profile</MenuText> <MenuText>View Profile</MenuText>
</MenuItem> </MenuItem>
)} )}
<MenuSection className={`${channel.type === "channel" && "channel"}`}> <MenuSection className={`${channel.type === 'channel' && 'channel'}`}>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
if (channel.isMuted) { if (channel.isMuted) {
channelsDispatch({ channelsDispatch({
type: "ToggleMuted", type: 'ToggleMuted',
payload: channel.id, payload: channel.id,
}); })
setShowMenu(false); setShowMenu(false)
} }
}} }}
onMouseEnter={() => { onMouseEnter={() => {
if (!channel.isMuted) setShowSubmenu(true); if (!channel.isMuted) setShowSubmenu(true)
}} }}
onMouseLeave={() => { onMouseLeave={() => {
if (!channel.isMuted) setShowSubmenu(false); if (!channel.isMuted) setShowSubmenu(false)
}} }}
> >
<MuteIcon width={16} height={16} /> <MuteIcon width={16} height={16} />
{!channel.isMuted && <NextIcon />} {!channel.isMuted && <NextIcon />}
<MenuText> <MenuText>
{(channel.isMuted ? "Unmute" : "Mute") + {(channel.isMuted ? 'Unmute' : 'Mute') +
(channel.type === "group" ? " Group" : "Chat")} (channel.type === 'group' ? ' Group' : 'Chat')}
</MenuText> </MenuText>
{!channel.isMuted && showSubmenu && ( {!channel.isMuted && showSubmenu && (
<MuteMenu <MuteMenu
setIsMuted={() => setIsMuted={() =>
channelsDispatch({ channelsDispatch({
type: "ToggleMuted", type: 'ToggleMuted',
payload: channel.id, payload: channel.id,
}) })
} }
@ -151,30 +151,30 @@ export const ChannelMenu = ({
<MenuText>Fetch Messages</MenuText> <MenuText>Fetch Messages</MenuText>
</MenuItem> </MenuItem>
</MenuSection> </MenuSection>
{(channel.type === "group" || channel.type === "dm") && ( {(channel.type === 'group' || channel.type === 'dm') && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setLeavingModal(true); setLeavingModal(true)
setShowMenu(false); setShowMenu(false)
}} }}
> >
{channel.type === "group" && ( {channel.type === 'group' && (
<LeftIcon width={16} height={16} className="red" /> <LeftIcon width={16} height={16} className="red" />
)} )}
{channel.type === "dm" && ( {channel.type === 'dm' && (
<DeleteIcon width={16} height={16} className="red" /> <DeleteIcon width={16} height={16} className="red" />
)} )}
<MenuText className="red"> <MenuText className="red">
{channel.type === "group" ? "Leave Group" : "Delete Chat"} {channel.type === 'group' ? 'Leave Group' : 'Delete Chat'}
</MenuText> </MenuText>
</MenuItem> </MenuItem>
)} )}
</ChannelDropdown> </ChannelDropdown>
); )
} else { } else {
return null; return null
} }
}; }
const ChannelDropdown = styled(DropdownMenu)` const ChannelDropdown = styled(DropdownMenu)`
top: calc(100% + 4px); top: calc(100% + 4px);
@ -190,4 +190,4 @@ const ChannelDropdown = styled(DropdownMenu)`
top: 20px; top: 20px;
right: 8px; right: 8px;
} }
`; `

View File

@ -1,43 +1,43 @@
import React, { useMemo } from "react"; import React, { useMemo } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useUserPublicKey } from "../../contexts/identityProvider"; import { useUserPublicKey } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useModal } from "../../contexts/modalProvider"; import { useModal } from '../../contexts/modalProvider'
import { AddContactIcon } from "../Icons/AddContactIcon"; import { AddContactIcon } from '../Icons/AddContactIcon'
import { BlockSvg } from "../Icons/BlockIcon"; import { BlockSvg } from '../Icons/BlockIcon'
import { ChatSvg } from "../Icons/ChatIcon"; import { ChatSvg } from '../Icons/ChatIcon'
import { EditIcon } from "../Icons/EditIcon"; import { EditIcon } from '../Icons/EditIcon'
import { ProfileIcon } from "../Icons/ProfileIcon"; import { ProfileIcon } from '../Icons/ProfileIcon'
import { UntrustworthIcon } from "../Icons/UntrustworthIcon"; import { UntrustworthIcon } from '../Icons/UntrustworthIcon'
import { UserIcon } from "../Icons/UserIcon"; import { UserIcon } from '../Icons/UserIcon'
import { WarningSvg } from "../Icons/WarningIcon"; import { WarningSvg } from '../Icons/WarningIcon'
import { UserAddress } from "../Messages/Styles"; import { UserAddress } from '../Messages/Styles'
import { ProfileModalName } from "../Modals/ProfileModal"; import { ProfileModalName } from '../Modals/ProfileModal'
import { textMediumStyles } from "../Text"; import { textMediumStyles } from '../Text'
import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu"; import { DropdownMenu, MenuItem, MenuText } from './DropdownMenu'
type ContactMenuProps = { type ContactMenuProps = {
id: string; id: string
setShowMenu: (val: boolean) => void; setShowMenu: (val: boolean) => void
}; }
export function ContactMenu({ id, setShowMenu }: ContactMenuProps) { export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
const userPK = useUserPublicKey(); const userPK = useUserPublicKey()
const { contacts, contactsDispatch } = useMessengerContext(); const { contacts, contactsDispatch } = useMessengerContext()
const contact = useMemo(() => contacts[id], [id, contacts]); const contact = useMemo(() => contacts[id], [id, contacts])
const isUser = useMemo(() => { const isUser = useMemo(() => {
if (userPK) { if (userPK) {
return id === userPK; return id === userPK
} else { } else {
return false; return false
} }
}, [id, userPK]); }, [id, userPK])
const { setModal } = useModal(ProfileModalName); const { setModal } = useModal(ProfileModalName)
if (!contact) return null; if (!contact) return null
return ( return (
<ContactDropdown> <ContactDropdown>
<ContactInfo> <ContactInfo>
@ -56,7 +56,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
<MenuSection> <MenuSection>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setModal({ id, renamingState: false, requestState: false }); setModal({ id, renamingState: false, requestState: false })
}} }}
> >
<ProfileIcon width={16} height={16} /> <ProfileIcon width={16} height={16} />
@ -65,7 +65,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
{!contact.isFriend && ( {!contact.isFriend && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setModal({ id, requestState: true }); setModal({ id, requestState: true })
}} }}
> >
<AddContactIcon width={16} height={16} /> <AddContactIcon width={16} height={16} />
@ -80,7 +80,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
)} )}
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setModal({ id, renamingState: true }); setModal({ id, renamingState: true })
}} }}
> >
<EditIcon width={16} height={16} /> <EditIcon width={16} height={16} />
@ -90,69 +90,69 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
<MenuSection> <MenuSection>
<MenuItem <MenuItem
onClick={() => onClick={() =>
contactsDispatch({ type: "toggleTrustworthy", payload: { id } }) contactsDispatch({ type: 'toggleTrustworthy', payload: { id } })
} }
> >
<WarningSvg <WarningSvg
width={16} width={16}
height={16} height={16}
className={contact.isUntrustworthy ? "" : "red"} className={contact.isUntrustworthy ? '' : 'red'}
/> />
<MenuText className={contact.isUntrustworthy ? "" : "red"}> <MenuText className={contact.isUntrustworthy ? '' : 'red'}>
{contact.isUntrustworthy {contact.isUntrustworthy
? "Remove Untrustworthy Mark" ? 'Remove Untrustworthy Mark'
: "Mark as Untrustworthy"} : 'Mark as Untrustworthy'}
</MenuText> </MenuText>
</MenuItem> </MenuItem>
{!contact.isFriend && !isUser && ( {!contact.isFriend && !isUser && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
contactsDispatch({ type: "toggleBlocked", payload: { id } }); contactsDispatch({ type: 'toggleBlocked', payload: { id } })
setShowMenu(false); setShowMenu(false)
}} }}
> >
<BlockSvg width={16} height={16} className="red" /> <BlockSvg width={16} height={16} className="red" />
<MenuText className="red"> <MenuText className="red">
{contact.blocked ? "Unblock User" : "Block User"} {contact.blocked ? 'Unblock User' : 'Block User'}
</MenuText> </MenuText>
</MenuItem> </MenuItem>
)} )}
</MenuSection> </MenuSection>
</ContactDropdown> </ContactDropdown>
); )
} }
const ContactDropdown = styled(DropdownMenu)` const ContactDropdown = styled(DropdownMenu)`
top: 20px; top: 20px;
left: 0px; left: 0px;
width: 222px; width: 222px;
`; `
const ContactInfo = styled.div` const ContactInfo = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
`; `
const MenuSection = styled.div` const MenuSection = styled.div`
margin-top: 5px; margin-top: 5px;
padding-top: 5px; padding-top: 5px;
border-top: 1px solid ${({ theme }) => theme.inputColor}; border-top: 1px solid ${({ theme }) => theme.inputColor};
`; `
const UserNameWrapper = styled.div` const UserNameWrapper = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 4px; margin-bottom: 4px;
`; `
const UserName = styled.p` const UserName = styled.p`
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
margin-right: 4px; margin-right: 4px;
${textMediumStyles} ${textMediumStyles}
`; `
const UserTrueName = styled.p` const UserTrueName = styled.p`
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
@ -160,4 +160,4 @@ const UserTrueName = styled.p`
line-height: 16px; line-height: 16px;
letter-spacing: 0.1px; letter-spacing: 0.1px;
margin-top: 4px; margin-top: 4px;
`; `

View File

@ -1,7 +1,7 @@
import React from "react"; import React from 'react'
import { copy } from "../../utils/copy"; import { copy } from '../../utils/copy'
import { reduceString } from "../../utils/reduceString"; import { reduceString } from '../../utils/reduceString'
import { import {
ButtonWrapper, ButtonWrapper,
@ -10,11 +10,11 @@ import {
Label, Label,
Text, Text,
Wrapper, Wrapper,
} from "./inputStyles"; } from './inputStyles'
interface CopyInputProps { interface CopyInputProps {
label?: string; label?: string
value: string; value: string
} }
export const CopyInput = ({ label, value }: CopyInputProps) => ( export const CopyInput = ({ label, value }: CopyInputProps) => (
@ -27,4 +27,4 @@ export const CopyInput = ({ label, value }: CopyInputProps) => (
</ButtonWrapper> </ButtonWrapper>
</Wrapper> </Wrapper>
</InputWrapper> </InputWrapper>
); )

View File

@ -1,15 +1,15 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { textSmallStyles } from "../Text"; import { textSmallStyles } from '../Text'
type DropdownMenuProps = { type DropdownMenuProps = {
children: ReactNode; children: ReactNode
className?: string; className?: string
style?: { top: number; left: number }; style?: { top: number; left: number }
menuRef?: React.MutableRefObject<null>; menuRef?: React.MutableRefObject<null>
id?: string; id?: string
}; }
export function DropdownMenu({ export function DropdownMenu({
children, children,
@ -22,7 +22,7 @@ export function DropdownMenu({
<MenuBlock className={className} style={style} ref={menuRef} id={id}> <MenuBlock className={className} style={style} ref={menuRef} id={id}>
<MenuList>{children}</MenuList> <MenuList>{children}</MenuList>
</MenuBlock> </MenuBlock>
); )
} }
const MenuBlock = styled.div` const MenuBlock = styled.div`
@ -34,11 +34,11 @@ const MenuBlock = styled.div`
padding: 8px 0; padding: 8px 0;
position: absolute; position: absolute;
z-index: 2; z-index: 2;
`; `
const MenuList = styled.ul` const MenuList = styled.ul`
list-style: none; list-style: none;
`; `
export const MenuItem = styled.li` export const MenuItem = styled.li`
width: 100%; width: 100%;
@ -61,7 +61,7 @@ export const MenuItem = styled.li`
& > svg.red { & > svg.red {
fill: ${({ theme }) => theme.redColor}; fill: ${({ theme }) => theme.redColor};
} }
`; `
export const MenuText = styled.span` export const MenuText = styled.span`
margin-left: 6px; margin-left: 6px;
@ -72,7 +72,7 @@ export const MenuText = styled.span`
} }
${textSmallStyles} ${textSmallStyles}
`; `
export const MenuSection = styled.div` export const MenuSection = styled.div`
padding: 4px 0; padding: 4px 0;
@ -91,4 +91,4 @@ export const MenuSection = styled.div`
margin: 4px 0 0; margin: 4px 0 0;
border-bottom: none; border-bottom: none;
} }
`; `

View File

@ -1,24 +1,24 @@
import React, { useRef } from "react"; import React, { useRef } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { useContextMenu } from "../../hooks/useContextMenu"; import { useContextMenu } from '../../hooks/useContextMenu'
import { copyImg } from "../../utils/copyImg"; import { copyImg } from '../../utils/copyImg'
import { downloadImg } from "../../utils/downloadImg"; import { downloadImg } from '../../utils/downloadImg'
import { CopyIcon } from "../Icons/CopyIcon"; import { CopyIcon } from '../Icons/CopyIcon'
import { DownloadIcon } from "../Icons/DownloadIcon"; import { DownloadIcon } from '../Icons/DownloadIcon'
import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu"; import { DropdownMenu, MenuItem, MenuText } from './DropdownMenu'
interface ImageMenuProps { interface ImageMenuProps {
imageId: string; imageId: string
} }
export const ImageMenu = ({ imageId }: ImageMenuProps) => { export const ImageMenu = ({ imageId }: ImageMenuProps) => {
const { showMenu, setShowMenu } = useContextMenu(imageId); const { showMenu, setShowMenu } = useContextMenu(imageId)
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowMenu(false)); useClickOutside(ref, () => setShowMenu(false))
return showMenu ? ( return showMenu ? (
<ImageDropdown menuRef={ref}> <ImageDropdown menuRef={ref}>
@ -32,11 +32,11 @@ export const ImageMenu = ({ imageId }: ImageMenuProps) => {
</ImageDropdown> </ImageDropdown>
) : ( ) : (
<></> <></>
); )
}; }
const ImageDropdown = styled(DropdownMenu)` const ImageDropdown = styled(DropdownMenu)`
width: 176px; width: 176px;
left: 120px; left: 120px;
top: 46px; top: 46px;
`; `

View File

@ -1,52 +1,52 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { MobileIcon } from "../Icons/MobileIcon"; import { MobileIcon } from '../Icons/MobileIcon'
import { ProfileIcon } from "../Icons/ProfileIcon"; import { ProfileIcon } from '../Icons/ProfileIcon'
import { ScanIcon } from "../Icons/ScanIcon"; import { ScanIcon } from '../Icons/ScanIcon'
import { textMediumStyles } from "../Text"; import { textMediumStyles } from '../Text'
interface LoginInstructionsProps { interface LoginInstructionsProps {
mobileFlow: boolean; mobileFlow: boolean
} }
export function LoginInstructions({ mobileFlow }: LoginInstructionsProps) { export function LoginInstructions({ mobileFlow }: LoginInstructionsProps) {
return ( return (
<Instructions> <Instructions>
<InstructionStep> <InstructionStep>
Open Status App on your {mobileFlow ? "mobile" : "desktop"} Open Status App on your {mobileFlow ? 'mobile' : 'desktop'}
</InstructionStep> </InstructionStep>
<InstructionStep> <InstructionStep>
Navigate yourself to{" "} Navigate yourself to{' '}
<InstructionIcon> <InstructionIcon>
{" "} {' '}
<ProfileIcon width={13} height={13} /> <span>Profile</span> <ProfileIcon width={13} height={13} /> <span>Profile</span>
</InstructionIcon>{" "} </InstructionIcon>{' '}
tab tab
</InstructionStep> </InstructionStep>
<InstructionStep> <InstructionStep>
Select{" "} Select{' '}
<InstructionIcon> <InstructionIcon>
<MobileIcon /> <MobileIcon />
</InstructionIcon>{" "} </InstructionIcon>{' '}
<span>Sync Settings</span> <span>Sync Settings</span>
</InstructionStep> </InstructionStep>
<InstructionStep> <InstructionStep>
Tap{" "} Tap{' '}
<InstructionIcon> <InstructionIcon>
{" "} {' '}
<ScanIcon />{" "} <ScanIcon />{' '}
</InstructionIcon>{" "} </InstructionIcon>{' '}
<span>{mobileFlow ? "Scan" : "Display"} sync code</span> <span>{mobileFlow ? 'Scan' : 'Display'} sync code</span>
</InstructionStep> </InstructionStep>
<InstructionStep> <InstructionStep>
{mobileFlow {mobileFlow
? "Scan the sync code from this screen" ? 'Scan the sync code from this screen'
: "Paste the sync code above"}{" "} : 'Paste the sync code above'}{' '}
</InstructionStep> </InstructionStep>
</Instructions> </Instructions>
); )
} }
const Instructions = styled.ol` const Instructions = styled.ol`
@ -56,7 +56,7 @@ const Instructions = styled.ol`
counter-reset: ollist; counter-reset: ollist;
${textMediumStyles} ${textMediumStyles}
`; `
const InstructionStep = styled.li` const InstructionStep = styled.li`
display: flex; display: flex;
@ -72,10 +72,10 @@ const InstructionStep = styled.li`
&::before { &::before {
counter-increment: ollist; counter-increment: ollist;
content: counter(ollist) "."; content: counter(ollist) '.';
margin-right: 4px; margin-right: 4px;
} }
`; `
const InstructionIcon = styled.div` const InstructionIcon = styled.div`
width: 40px; width: 40px;
@ -90,4 +90,4 @@ const InstructionIcon = styled.div`
font-size: 8px; font-size: 8px;
line-height: 10px; line-height: 10px;
margin: 0 6px; margin: 0 6px;
`; `

View File

@ -1,28 +1,28 @@
import { BaseEmoji } from "emoji-mart"; import { BaseEmoji } from 'emoji-mart'
import React, { useMemo, useRef } from "react"; import React, { useMemo, useRef } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useUserPublicKey } from "../../contexts/identityProvider"; import { useUserPublicKey } from '../../contexts/identityProvider'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { useClickOutside } from "../../hooks/useClickOutside"; import { useClickOutside } from '../../hooks/useClickOutside'
import { useClickPosition } from "../../hooks/useClickPosition"; import { useClickPosition } from '../../hooks/useClickPosition'
import { useContextMenu } from "../../hooks/useContextMenu"; import { useContextMenu } from '../../hooks/useContextMenu'
import { Reply } from "../../hooks/useReply"; import { Reply } from '../../hooks/useReply'
import { ChatMessage } from "../../models/ChatMessage"; import { ChatMessage } from '../../models/ChatMessage'
import { DeleteIcon } from "../Icons/DeleteIcon"; import { DeleteIcon } from '../Icons/DeleteIcon'
import { EditIcon } from "../Icons/EditIcon"; import { EditIcon } from '../Icons/EditIcon'
import { PinIcon } from "../Icons/PinIcon"; import { PinIcon } from '../Icons/PinIcon'
import { ReplySvg } from "../Icons/ReplyIcon"; import { ReplySvg } from '../Icons/ReplyIcon'
import { ReactionPicker } from "../Reactions/ReactionPicker"; import { ReactionPicker } from '../Reactions/ReactionPicker'
import { DropdownMenu, MenuItem, MenuSection, MenuText } from "./DropdownMenu"; import { DropdownMenu, MenuItem, MenuSection, MenuText } from './DropdownMenu'
interface MessageMenuProps { interface MessageMenuProps {
message: ChatMessage; message: ChatMessage
messageReactions: BaseEmoji[]; messageReactions: BaseEmoji[]
setMessageReactions: React.Dispatch<React.SetStateAction<BaseEmoji[]>>; setMessageReactions: React.Dispatch<React.SetStateAction<BaseEmoji[]>>
setReply: (val: Reply | undefined) => void; setReply: (val: Reply | undefined) => void
messageRef: React.MutableRefObject<null>; messageRef: React.MutableRefObject<null>
} }
export const MessageMenu = ({ export const MessageMenu = ({
@ -32,25 +32,25 @@ export const MessageMenu = ({
setReply, setReply,
messageRef, messageRef,
}: MessageMenuProps) => { }: MessageMenuProps) => {
const userPK = useUserPublicKey(); const userPK = useUserPublicKey()
const { activeChannel } = useMessengerContext(); const { activeChannel } = useMessengerContext()
const { showMenu, setShowMenu } = useContextMenu(message.id); const { showMenu, setShowMenu } = useContextMenu(message.id)
const { topPosition, leftPosition } = useClickPosition(messageRef); const { topPosition, leftPosition } = useClickPosition(messageRef)
const menuStyle = useMemo(() => { const menuStyle = useMemo(() => {
return { return {
top: topPosition, top: topPosition,
left: leftPosition, left: leftPosition,
}; }
}, [topPosition, leftPosition]); }, [topPosition, leftPosition])
const ref = useRef(null); const ref = useRef(null)
useClickOutside(ref, () => setShowMenu(false)); useClickOutside(ref, () => setShowMenu(false))
const userMessage = useMemo( const userMessage = useMemo(
() => !!userPK && message.sender === userPK, () => !!userPK && message.sender === userPK,
[userPK, message] [userPK, message]
); )
return userPK && showMenu ? ( return userPK && showMenu ? (
<MessageDropdown style={menuStyle} menuRef={ref} id="messageDropdown"> <MessageDropdown style={menuStyle} menuRef={ref} id="messageDropdown">
@ -61,7 +61,7 @@ export const MessageMenu = ({
className="menu" className="menu"
/> />
</MenuItem> </MenuItem>
<MenuSection className={`${!userMessage && "message"}`}> <MenuSection className={`${!userMessage && 'message'}`}>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setReply({ setReply({
@ -69,8 +69,8 @@ export const MessageMenu = ({
content: message.content, content: message.content,
image: message.image, image: message.image,
id: message.id, id: message.id,
}); })
setShowMenu(false); setShowMenu(false)
}} }}
> >
<ReplySvg width={16} height={16} className="menu" /> <ReplySvg width={16} height={16} className="menu" />
@ -80,17 +80,17 @@ export const MessageMenu = ({
{userMessage && ( {userMessage && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setShowMenu(false); setShowMenu(false)
}} }}
> >
<EditIcon width={16} height={16} /> <EditIcon width={16} height={16} />
<MenuText>Edit</MenuText> <MenuText>Edit</MenuText>
</MenuItem> </MenuItem>
)} )}
{activeChannel?.type !== "channel" && ( {activeChannel?.type !== 'channel' && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setShowMenu(false); setShowMenu(false)
}} }}
> >
<PinIcon width={16} height={16} className="menu" /> <PinIcon width={16} height={16} className="menu" />
@ -101,7 +101,7 @@ export const MessageMenu = ({
{userMessage && ( {userMessage && (
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setShowMenu(false); setShowMenu(false)
}} }}
> >
<DeleteIcon width={16} height={16} className="red" /> <DeleteIcon width={16} height={16} className="red" />
@ -111,9 +111,9 @@ export const MessageMenu = ({
</MessageDropdown> </MessageDropdown>
) : ( ) : (
<></> <></>
); )
}; }
const MessageDropdown = styled(DropdownMenu)` const MessageDropdown = styled(DropdownMenu)`
width: 176px; width: 176px;
`; `

View File

@ -1,24 +1,24 @@
import React, { useCallback } from "react"; import React, { useCallback } from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { DropdownMenu, MenuItem, MenuText } from "./DropdownMenu"; import { DropdownMenu, MenuItem, MenuText } from './DropdownMenu'
interface SubMenuProps { interface SubMenuProps {
setIsMuted: (val: boolean) => void; setIsMuted: (val: boolean) => void
className?: string; className?: string
} }
export const MuteMenu = ({ setIsMuted, className }: SubMenuProps) => { export const MuteMenu = ({ setIsMuted, className }: SubMenuProps) => {
const muteChannel = useCallback( const muteChannel = useCallback(
(timeout: number) => { (timeout: number) => {
setIsMuted(true); setIsMuted(true)
const timer = setTimeout(() => setIsMuted(false), timeout * 6000000); const timer = setTimeout(() => setIsMuted(false), timeout * 6000000)
return () => { return () => {
clearTimeout(timer); clearTimeout(timer)
}; }
}, },
[setIsMuted] [setIsMuted]
); )
return ( return (
<MuteDropdown className={className}> <MuteDropdown className={className}>
@ -38,8 +38,8 @@ export const MuteMenu = ({ setIsMuted, className }: SubMenuProps) => {
<MenuText>Until I turn it back on</MenuText> <MenuText>Until I turn it back on</MenuText>
</MenuItem> </MenuItem>
</MuteDropdown> </MuteDropdown>
); )
}; }
const MuteDropdown = styled(DropdownMenu)` const MuteDropdown = styled(DropdownMenu)`
width: 176px; width: 176px;
@ -61,4 +61,4 @@ const MuteDropdown = styled(DropdownMenu)`
right: -16px; right: -16px;
z-index: 3; z-index: 3;
} }
`; `

View File

@ -1,38 +1,38 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { NameErrors } from "../../hooks/useNameError"; import { NameErrors } from '../../hooks/useNameError'
import { Hint } from "../Modals/ModalStyle"; import { Hint } from '../Modals/ModalStyle'
type NameErrorProps = { type NameErrorProps = {
error: NameErrors; error: NameErrors
}; }
export function NameError({ error }: NameErrorProps) { export function NameError({ error }: NameErrorProps) {
switch (error) { switch (error) {
case NameErrors.NoError: case NameErrors.NoError:
return null; return null
case NameErrors.NameExists: case NameErrors.NameExists:
return ( return (
<ErrorText> <ErrorText>
Sorry, the name you have chosen is not allowed, try picking another Sorry, the name you have chosen is not allowed, try picking another
username username
</ErrorText> </ErrorText>
); )
case NameErrors.BadCharacters: case NameErrors.BadCharacters:
return ( return (
<ErrorText> <ErrorText>
Only letters, numbers, underscores and hypens allowed Only letters, numbers, underscores and hypens allowed
</ErrorText> </ErrorText>
); )
case NameErrors.EndingWithEth: case NameErrors.EndingWithEth:
return ( return (
<ErrorText> <ErrorText>
Usernames ending with _eth or "-eth" are not allowed Usernames ending with _eth or "-eth" are not allowed
</ErrorText> </ErrorText>
); )
case NameErrors.TooLong: case NameErrors.TooLong:
return <ErrorText>24 character username limit</ErrorText>; return <ErrorText>24 character username limit</ErrorText>
} }
} }
@ -41,4 +41,4 @@ const ErrorText = styled(Hint)`
text-align: center; text-align: center;
width: 328px; width: 328px;
margin: 8px 0; margin: 8px 0;
`; `

View File

@ -1,7 +1,7 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { paste } from "../../utils/paste"; import { paste } from '../../utils/paste'
import { import {
ButtonWrapper, ButtonWrapper,
@ -10,10 +10,10 @@ import {
InputWrapper, InputWrapper,
Label, Label,
Wrapper, Wrapper,
} from "./inputStyles"; } from './inputStyles'
interface PasteInputProps { interface PasteInputProps {
label: string; label: string
} }
export const PasteInput = ({ label }: PasteInputProps) => ( export const PasteInput = ({ label }: PasteInputProps) => (
@ -22,11 +22,11 @@ export const PasteInput = ({ label }: PasteInputProps) => (
<Wrapper> <Wrapper>
<Input id="pasteInput" type="text" placeholder="eg. 0x2Ef19" /> <Input id="pasteInput" type="text" placeholder="eg. 0x2Ef19" />
<ButtonWrapper> <ButtonWrapper>
<InputBtn onClick={() => paste("pasteInput")}>Paste</InputBtn> <InputBtn onClick={() => paste('pasteInput')}>Paste</InputBtn>
</ButtonWrapper> </ButtonWrapper>
</Wrapper> </Wrapper>
</InputWrapper> </InputWrapper>
); )
const Input = styled.input` const Input = styled.input`
${inputStyles} ${inputStyles}
@ -37,4 +37,4 @@ const Input = styled.input`
} }
border: none; border: none;
`; `

View File

@ -1,33 +1,33 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { useMessengerContext } from "../../contexts/messengerProvider"; import { useMessengerContext } from '../../contexts/messengerProvider'
import { textMediumStyles } from "../Text"; import { textMediumStyles } from '../Text'
const communityRequirements = { const communityRequirements = {
requirements: [ requirements: [
{ {
name: "STN", name: 'STN',
amount: 10, amount: 10,
logo: "https://status.im/img/logo.svg", logo: 'https://status.im/img/logo.svg',
}, },
], ],
alternativeRequirements: [ alternativeRequirements: [
{ {
name: "ETH", name: 'ETH',
amount: 1, amount: 1,
logo: "https://ethereum.org/static/a110735dade3f354a46fc2446cd52476/db4de/eth-home-icon.webp", logo: 'https://ethereum.org/static/a110735dade3f354a46fc2446cd52476/db4de/eth-home-icon.webp',
}, },
{ {
name: "MKR", name: 'MKR',
amount: 10, amount: 10,
logo: "https://cryptologos.cc/logos/maker-mkr-logo.svg?v=017", logo: 'https://cryptologos.cc/logos/maker-mkr-logo.svg?v=017',
}, },
], ],
}; }
export function TokenRequirement() { export function TokenRequirement() {
const { communityData } = useMessengerContext(); const { communityData } = useMessengerContext()
return ( return (
<Wrapper> <Wrapper>
<Text> <Text>
@ -35,7 +35,7 @@ export function TokenRequirement() {
hold: hold:
</Text> </Text>
<Row> <Row>
{communityRequirements.requirements.map((req) => ( {communityRequirements.requirements.map(req => (
<Requirement key={req.name + req.amount}> <Requirement key={req.name + req.amount}>
<Logo <Logo
style={{ style={{
@ -43,14 +43,14 @@ export function TokenRequirement() {
}} }}
/> />
<Amount> <Amount>
{req.amount} {req.name}{" "} {req.amount} {req.name}{' '}
</Amount> </Amount>
</Requirement> </Requirement>
))} ))}
</Row> </Row>
{communityRequirements.alternativeRequirements && <Text>or</Text>} {communityRequirements.alternativeRequirements && <Text>or</Text>}
<Row> <Row>
{communityRequirements.alternativeRequirements.map((req) => ( {communityRequirements.alternativeRequirements.map(req => (
<Requirement key={req.name + req.amount}> <Requirement key={req.name + req.amount}>
<Logo <Logo
style={{ style={{
@ -58,13 +58,13 @@ export function TokenRequirement() {
}} }}
/> />
<Amount> <Amount>
{req.amount} {req.name}{" "} {req.amount} {req.name}{' '}
</Amount> </Amount>
</Requirement> </Requirement>
))} ))}
</Row> </Row>
</Wrapper> </Wrapper>
); )
} }
const Wrapper = styled.div` const Wrapper = styled.div`
@ -72,7 +72,7 @@ const Wrapper = styled.div`
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
height: 50%; height: 50%;
`; `
const Text = styled.p` const Text = styled.p`
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
@ -84,7 +84,7 @@ const Text = styled.p`
} }
${textMediumStyles} ${textMediumStyles}
`; `
const Requirement = styled.div` const Requirement = styled.div`
display: flex; display: flex;
@ -102,7 +102,7 @@ const Requirement = styled.div`
& + & { & + & {
margin-left: 18px; margin-left: 18px;
} }
`; `
const Amount = styled.p` const Amount = styled.p`
font-weight: 500; font-weight: 500;
@ -110,13 +110,13 @@ const Amount = styled.p`
margin-left: 6px; margin-left: 6px;
${textMediumStyles} ${textMediumStyles}
`; `
const Row = styled.div` const Row = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 16px; margin-bottom: 16px;
`; `
const Logo = styled.div` const Logo = styled.div`
width: 28px; width: 28px;
@ -128,4 +128,4 @@ const Logo = styled.div`
border-radius: 50%; border-radius: 50%;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
`; `

View File

@ -1,13 +1,13 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
import { TipIcon } from "../Icons/TipIcon"; import { TipIcon } from '../Icons/TipIcon'
import { textSmallStyles } from "../Text"; import { textSmallStyles } from '../Text'
type TooltipProps = { type TooltipProps = {
tip: string; tip: string
className?: string; className?: string
}; }
export function Tooltip({ tip, className }: TooltipProps) { export function Tooltip({ tip, className }: TooltipProps) {
return ( return (
@ -17,7 +17,7 @@ export function Tooltip({ tip, className }: TooltipProps) {
<TipIcon className={className} /> <TipIcon className={className} />
</TooltipBlock> </TooltipBlock>
</TooltipWrapper> </TooltipWrapper>
); )
} }
const TooltipWrapper = styled.div` const TooltipWrapper = styled.div`
@ -36,16 +36,16 @@ const TooltipWrapper = styled.div`
top: calc(100% + 8px); top: calc(100% + 8px);
z-index: 10; z-index: 10;
} }
`; `
const TooltipBlock = styled.div` const TooltipBlock = styled.div`
background: ${({ theme }) => theme.primary}; background: ${({ theme }) => theme.primary};
border-radius: 8px; border-radius: 8px;
position: relative; position: relative;
padding: 8px; padding: 8px;
`; `
const TooltipText = styled.p` const TooltipText = styled.p`
font-weight: 500; font-weight: 500;
color: ${({ theme }) => theme.bodyBackgroundColor}; color: ${({ theme }) => theme.bodyBackgroundColor};
${textSmallStyles}; ${textSmallStyles};
`; `

View File

@ -1,6 +1,6 @@
import styled, { css } from "styled-components"; import styled, { css } from 'styled-components'
import { textMediumStyles, textSmallStyles } from "../Text"; import { textMediumStyles, textSmallStyles } from '../Text'
export const inputStyles = css` export const inputStyles = css`
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
@ -15,7 +15,7 @@ export const inputStyles = css`
outline: 1px solid ${({ theme }) => theme.tertiary}; outline: 1px solid ${({ theme }) => theme.tertiary};
caret-color: ${({ theme }) => theme.notificationColor}; caret-color: ${({ theme }) => theme.notificationColor};
} }
`; `
export const Label = styled.p` export const Label = styled.p`
margin-bottom: 7px; margin-bottom: 7px;
@ -25,24 +25,24 @@ export const Label = styled.p`
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
${textSmallStyles} ${textSmallStyles}
`; `
export const InputWrapper = styled.div` export const InputWrapper = styled.div`
width: 100%; width: 100%;
`; `
export const Wrapper = styled.div` export const Wrapper = styled.div`
position: relative; position: relative;
padding: 14px 70px 14px 8px; padding: 14px 70px 14px 8px;
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
border-radius: 8px; border-radius: 8px;
`; `
export const Text = styled.p` export const Text = styled.p`
color: ${({ theme }) => theme.primary}; color: ${({ theme }) => theme.primary};
${textMediumStyles} ${textMediumStyles}
`; `
export const ButtonWrapper = styled.div` export const ButtonWrapper = styled.div`
position: absolute; position: absolute;
@ -56,7 +56,7 @@ export const ButtonWrapper = styled.div`
transform: translateY(-50%); transform: translateY(-50%);
background: ${({ theme }) => theme.inputColor}; background: ${({ theme }) => theme.inputColor};
border-radius: 8px; border-radius: 8px;
`; `
export const InputBtn = styled.button` export const InputBtn = styled.button`
padding: 6px 12px; padding: 6px 12px;
@ -67,18 +67,18 @@ export const InputBtn = styled.button`
background: ${({ theme }) => theme.buttonBg}; background: ${({ theme }) => theme.buttonBg};
border: 1px solid ${({ theme }) => theme.tertiary}; border: 1px solid ${({ theme }) => theme.tertiary};
border-radius: 6px; border-radius: 6px;
`; `
export const NameInputWrapper = styled.div` export const NameInputWrapper = styled.div`
position: relative; position: relative;
`; `
export const NameInput = styled.input` export const NameInput = styled.input`
width: 328px; width: 328px;
padding: 11px 16px; padding: 11px 16px;
${inputStyles} ${inputStyles}
`; `
export const ClearBtn = styled.button` export const ClearBtn = styled.button`
position: absolute; position: absolute;
@ -90,4 +90,4 @@ export const ClearBtn = styled.button`
& > svg { & > svg {
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
} }
`; `

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
export const ActivityIcon = () => { export const ActivityIcon = () => {
return ( return (
@ -16,9 +16,9 @@ export const ActivityIcon = () => {
d="M15.2815 19C14.9452 19 14.7036 19.3279 14.7349 19.6628C14.7449 19.7703 14.7504 19.8827 14.7504 20C14.7504 21.3889 13.5441 22.75 12.0004 22.75C10.4568 22.75 9.25041 21.3889 9.25041 20C9.25041 19.8827 9.25591 19.7703 9.26596 19.6628C9.29725 19.3279 9.05564 19 8.71934 19H5.52151C3.78523 19 2.87368 16.9394 4.04163 15.6547L5.21849 14.3601C5.72921 13.7983 6.06949 13.1028 6.19958 12.3548L7.31505 5.94085C7.71121 3.66293 9.6883 2 12.0004 2C14.3125 2 16.2896 3.66293 16.6858 5.94085L17.8012 12.3548C17.9313 13.1028 18.2716 13.7983 18.7823 14.3601L19.9592 15.6547C21.1271 16.9394 20.2156 19 18.4793 19H15.2815ZM11.0327 19.0283L11.0318 19.0293L11.0395 19.0214L11.0419 19.0188C11.0432 19.0175 11.0438 19.0168 11.0439 19.0167C11.0443 19.0163 11.0439 19.0167 11.0439 19.0167L11.0419 19.0188C11.0529 19.0073 11.0685 19 11.0845 19H12.9164C12.9323 19 12.9474 19.0068 12.9584 19.0183C12.9612 19.0217 12.9684 19.0302 12.9785 19.0438C13.0015 19.0744 13.0394 19.13 13.0796 19.2104C13.1587 19.3687 13.2504 19.6296 13.2504 20C13.2504 20.6111 12.6659 21.25 12.0004 21.25C11.3349 21.25 10.7504 20.6111 10.7504 20C10.7504 19.6296 10.8421 19.3687 10.9212 19.2104C10.9614 19.13 10.9993 19.0744 11.0223 19.0438C11.0325 19.0302 11.0391 19.0222 11.0419 19.0188L11.0395 19.0214L11.0377 19.0233L11.0345 19.0265L11.0327 19.0283ZM5.15154 16.6637L6.3284 15.3691C7.03064 14.5967 7.49853 13.6403 7.6774 12.6118L8.79286 6.19786C9.06407 4.63842 10.4176 3.5 12.0004 3.5C13.5833 3.5 14.9368 4.63842 15.208 6.19786L16.3234 12.6118C16.5023 13.6403 16.9702 14.5967 17.6724 15.3691L18.8493 16.6637C19.1413 16.9849 18.9134 17.5 18.4793 17.5H5.52151C5.08744 17.5 4.85956 16.9849 5.15154 16.6637Z" d="M15.2815 19C14.9452 19 14.7036 19.3279 14.7349 19.6628C14.7449 19.7703 14.7504 19.8827 14.7504 20C14.7504 21.3889 13.5441 22.75 12.0004 22.75C10.4568 22.75 9.25041 21.3889 9.25041 20C9.25041 19.8827 9.25591 19.7703 9.26596 19.6628C9.29725 19.3279 9.05564 19 8.71934 19H5.52151C3.78523 19 2.87368 16.9394 4.04163 15.6547L5.21849 14.3601C5.72921 13.7983 6.06949 13.1028 6.19958 12.3548L7.31505 5.94085C7.71121 3.66293 9.6883 2 12.0004 2C14.3125 2 16.2896 3.66293 16.6858 5.94085L17.8012 12.3548C17.9313 13.1028 18.2716 13.7983 18.7823 14.3601L19.9592 15.6547C21.1271 16.9394 20.2156 19 18.4793 19H15.2815ZM11.0327 19.0283L11.0318 19.0293L11.0395 19.0214L11.0419 19.0188C11.0432 19.0175 11.0438 19.0168 11.0439 19.0167C11.0443 19.0163 11.0439 19.0167 11.0439 19.0167L11.0419 19.0188C11.0529 19.0073 11.0685 19 11.0845 19H12.9164C12.9323 19 12.9474 19.0068 12.9584 19.0183C12.9612 19.0217 12.9684 19.0302 12.9785 19.0438C13.0015 19.0744 13.0394 19.13 13.0796 19.2104C13.1587 19.3687 13.2504 19.6296 13.2504 20C13.2504 20.6111 12.6659 21.25 12.0004 21.25C11.3349 21.25 10.7504 20.6111 10.7504 20C10.7504 19.6296 10.8421 19.3687 10.9212 19.2104C10.9614 19.13 10.9993 19.0744 11.0223 19.0438C11.0325 19.0302 11.0391 19.0222 11.0419 19.0188L11.0395 19.0214L11.0377 19.0233L11.0345 19.0265L11.0327 19.0283ZM5.15154 16.6637L6.3284 15.3691C7.03064 14.5967 7.49853 13.6403 7.6774 12.6118L8.79286 6.19786C9.06407 4.63842 10.4176 3.5 12.0004 3.5C13.5833 3.5 14.9368 4.63842 15.208 6.19786L16.3234 12.6118C16.5023 13.6403 16.9702 14.5967 17.6724 15.3691L18.8493 16.6637C19.1413 16.9849 18.9134 17.5 18.4793 17.5H5.52151C5.08744 17.5 4.85956 16.9849 5.15154 16.6637Z"
/> />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.primary}; fill: ${({ theme }) => theme.primary};
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type AddContactIconProps = { type AddContactIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function AddContactIcon({ export function AddContactIcon({
width, width,
@ -29,9 +29,9 @@ export function AddContactIcon({
<path d="M8.07357 11.6671C8.35289 11.6707 8.60016 11.4677 8.62336 11.1893C8.64601 10.9175 8.44624 10.6758 8.17357 10.6689C8.11597 10.6674 8.05818 10.6667 8.00022 10.6667C5.97321 10.6667 4.15749 11.5713 2.93477 12.9989C2.77487 13.1856 2.79579 13.4622 2.96961 13.636C3.18548 13.8519 3.54282 13.8208 3.74449 13.5916C4.78296 12.4114 6.30462 11.6667 8.00022 11.6667C8.02471 11.6667 8.04916 11.6668 8.07357 11.6671Z" /> <path d="M8.07357 11.6671C8.35289 11.6707 8.60016 11.4677 8.62336 11.1893C8.64601 10.9175 8.44624 10.6758 8.17357 10.6689C8.11597 10.6674 8.05818 10.6667 8.00022 10.6667C5.97321 10.6667 4.15749 11.5713 2.93477 12.9989C2.77487 13.1856 2.79579 13.4622 2.96961 13.636C3.18548 13.8519 3.54282 13.8208 3.74449 13.5916C4.78296 12.4114 6.30462 11.6667 8.00022 11.6667C8.02471 11.6667 8.04916 11.6668 8.07357 11.6671Z" />
<path d="M10.167 11.1667C10.167 10.8905 10.3908 10.6667 10.667 10.6667H11.5003C11.6844 10.6667 11.8337 10.5174 11.8337 10.3333V9.5C11.8337 9.22386 12.0575 9 12.3337 9C12.6098 9 12.8337 9.22386 12.8337 9.5V10.3333C12.8337 10.5174 12.9829 10.6667 13.167 10.6667H14.0003C14.2765 10.6667 14.5003 10.8905 14.5003 11.1667C14.5003 11.4428 14.2765 11.6667 14.0003 11.6667H13.167C12.9829 11.6667 12.8337 11.8159 12.8337 12V12.8333C12.8337 13.1095 12.6098 13.3333 12.3337 13.3333C12.0575 13.3333 11.8337 13.1095 11.8337 12.8333V12C11.8337 11.8159 11.6844 11.6667 11.5003 11.6667H10.667C10.3908 11.6667 10.167 11.4428 10.167 11.1667Z" /> <path d="M10.167 11.1667C10.167 10.8905 10.3908 10.6667 10.667 10.6667H11.5003C11.6844 10.6667 11.8337 10.5174 11.8337 10.3333V9.5C11.8337 9.22386 12.0575 9 12.3337 9C12.6098 9 12.8337 9.22386 12.8337 9.5V10.3333C12.8337 10.5174 12.9829 10.6667 13.167 10.6667H14.0003C14.2765 10.6667 14.5003 10.8905 14.5003 11.1667C14.5003 11.4428 14.2765 11.6667 14.0003 11.6667H13.167C12.9829 11.6667 12.8337 11.8159 12.8337 12V12.8333C12.8337 13.1095 12.6098 13.3333 12.3337 13.3333C12.0575 13.3333 11.8337 13.1095 11.8337 12.8333V12C11.8337 11.8159 11.6844 11.6667 11.5003 11.6667H10.667C10.3908 11.6667 10.167 11.4428 10.167 11.1667Z" />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
export const AddIcon = () => { export const AddIcon = () => {
return ( return (
@ -12,11 +12,11 @@ export const AddIcon = () => {
> >
<path d="M12 5.25C12.4142 5.25 12.75 5.58579 12.75 6V10.75C12.75 11.0261 12.9739 11.25 13.25 11.25H18C18.4142 11.25 18.75 11.5858 18.75 12C18.75 12.4142 18.4142 12.75 18 12.75H13.25C12.9739 12.75 12.75 12.9739 12.75 13.25V18C12.75 18.4142 12.4142 18.75 12 18.75C11.5858 18.75 11.25 18.4142 11.25 18V13.25C11.25 12.9739 11.0261 12.75 10.75 12.75H6C5.58579 12.75 5.25 12.4142 5.25 12C5.25 11.5858 5.58579 11.25 6 11.25H10.75C11.0261 11.25 11.25 11.0261 11.25 10.75V6C11.25 5.58579 11.5858 5.25 12 5.25Z" /> <path d="M12 5.25C12.4142 5.25 12.75 5.58579 12.75 6V10.75C12.75 11.0261 12.9739 11.25 13.25 11.25H18C18.4142 11.25 18.75 11.5858 18.75 12C18.75 12.4142 18.4142 12.75 18 12.75H13.25C12.9739 12.75 12.75 12.9739 12.75 13.25V18C12.75 18.4142 12.4142 18.75 12 18.75C11.5858 18.75 11.25 18.4142 11.25 18V13.25C11.25 12.9739 11.0261 12.75 10.75 12.75H6C5.58579 12.75 5.25 12.4142 5.25 12C5.25 11.5858 5.58579 11.25 6 11.25H10.75C11.0261 11.25 11.25 11.0261 11.25 10.75V6C11.25 5.58579 11.5858 5.25 12 5.25Z" />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
fill: ${({ theme }) => theme.bodyBackgroundColor}; fill: ${({ theme }) => theme.bodyBackgroundColor};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type AddMemberIconProps = { type AddMemberIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function AddMemberIcon({ export function AddMemberIcon({
width, width,
@ -31,9 +31,9 @@ export function AddMemberIcon({
<path d="M8.07357 11.6671C8.35289 11.6707 8.60016 11.4677 8.62336 11.1893C8.64601 10.9175 8.44624 10.6758 8.17357 10.6689C8.11597 10.6674 8.05818 10.6667 8.00022 10.6667C5.97321 10.6667 4.15749 11.5713 2.93477 12.9989C2.77487 13.1856 2.79579 13.4622 2.96961 13.636C3.18548 13.8519 3.54282 13.8208 3.74449 13.5916C4.78296 12.4114 6.30462 11.6667 8.00022 11.6667C8.02471 11.6667 8.04916 11.6668 8.07357 11.6671Z" /> <path d="M8.07357 11.6671C8.35289 11.6707 8.60016 11.4677 8.62336 11.1893C8.64601 10.9175 8.44624 10.6758 8.17357 10.6689C8.11597 10.6674 8.05818 10.6667 8.00022 10.6667C5.97321 10.6667 4.15749 11.5713 2.93477 12.9989C2.77487 13.1856 2.79579 13.4622 2.96961 13.636C3.18548 13.8519 3.54282 13.8208 3.74449 13.5916C4.78296 12.4114 6.30462 11.6667 8.00022 11.6667C8.02471 11.6667 8.04916 11.6668 8.07357 11.6671Z" />
<path d="M10.167 11.1667C10.167 10.8905 10.3908 10.6667 10.667 10.6667H11.5003C11.6844 10.6667 11.8337 10.5174 11.8337 10.3333V9.5C11.8337 9.22386 12.0575 9 12.3337 9C12.6098 9 12.8337 9.22386 12.8337 9.5V10.3333C12.8337 10.5174 12.9829 10.6667 13.167 10.6667H14.0003C14.2765 10.6667 14.5003 10.8905 14.5003 11.1667C14.5003 11.4428 14.2765 11.6667 14.0003 11.6667H13.167C12.9829 11.6667 12.8337 11.8159 12.8337 12V12.8333C12.8337 13.1095 12.6098 13.3333 12.3337 13.3333C12.0575 13.3333 11.8337 13.1095 11.8337 12.8333V12C11.8337 11.8159 11.6844 11.6667 11.5003 11.6667H10.667C10.3908 11.6667 10.167 11.4428 10.167 11.1667Z" /> <path d="M10.167 11.1667C10.167 10.8905 10.3908 10.6667 10.667 10.6667H11.5003C11.6844 10.6667 11.8337 10.5174 11.8337 10.3333V9.5C11.8337 9.22386 12.0575 9 12.3337 9C12.6098 9 12.8337 9.22386 12.8337 9.5V10.3333C12.8337 10.5174 12.9829 10.6667 13.167 10.6667H14.0003C14.2765 10.6667 14.5003 10.8905 14.5003 11.1667C14.5003 11.4428 14.2765 11.6667 14.0003 11.6667H13.167C12.9829 11.6667 12.8337 11.8159 12.8337 12V12.8333C12.8337 13.1095 12.6098 13.3333 12.3337 13.3333C12.0575 13.3333 11.8337 13.1095 11.8337 12.8333V12C11.8337 11.8159 11.6844 11.6667 11.5003 11.6667H10.667C10.3908 11.6667 10.167 11.4428 10.167 11.1667Z" />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type BlockSvgProps = { type BlockSvgProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function BlockSvg({ width, height, className }: BlockSvgProps) { export function BlockSvg({ width, height, className }: BlockSvgProps) {
return ( return (
@ -23,12 +23,12 @@ export function BlockSvg({ width, height, className }: BlockSvgProps) {
d="M8.00065 14.6673C4.31875 14.6673 1.33398 11.6825 1.33398 8.00065C1.33398 4.31875 4.31875 1.33398 8.00065 1.33398C11.6826 1.33398 14.6673 4.31875 14.6673 8.00065C14.6673 11.6826 11.6825 14.6673 8.00065 14.6673ZM3.91306 11.3811C3.77473 11.5195 3.54679 11.5099 3.43096 11.3523C2.74134 10.4136 2.33398 9.2547 2.33398 8.00065C2.33398 4.87104 4.87104 2.33398 8.00065 2.33398C9.2547 2.33398 10.4136 2.74135 11.3523 3.43096C11.5099 3.54679 11.5195 3.77473 11.3811 3.91306L3.91306 11.3811ZM4.62017 12.0882C4.48183 12.2266 4.49138 12.4545 4.64904 12.5703C5.58769 13.26 6.7466 13.6673 8.00065 13.6673C11.1303 13.6673 13.6673 11.1303 13.6673 8.00065C13.6673 6.7466 13.26 5.58769 12.5703 4.64904C12.4545 4.49138 12.2266 4.48183 12.0882 4.62017L4.62017 12.0882Z" d="M8.00065 14.6673C4.31875 14.6673 1.33398 11.6825 1.33398 8.00065C1.33398 4.31875 4.31875 1.33398 8.00065 1.33398C11.6826 1.33398 14.6673 4.31875 14.6673 8.00065C14.6673 11.6826 11.6825 14.6673 8.00065 14.6673ZM3.91306 11.3811C3.77473 11.5195 3.54679 11.5099 3.43096 11.3523C2.74134 10.4136 2.33398 9.2547 2.33398 8.00065C2.33398 4.87104 4.87104 2.33398 8.00065 2.33398C9.2547 2.33398 10.4136 2.74135 11.3523 3.43096C11.5099 3.54679 11.5195 3.77473 11.3811 3.91306L3.91306 11.3811ZM4.62017 12.0882C4.48183 12.2266 4.49138 12.4545 4.64904 12.5703C5.58769 13.26 6.7466 13.6673 8.00065 13.6673C11.1303 13.6673 13.6673 11.1303 13.6673 8.00065C13.6673 6.7466 13.26 5.58769 12.5703 4.64904C12.4545 4.49138 12.2266 4.48183 12.0882 4.62017L4.62017 12.0882Z"
/> />
</svg> </svg>
); )
} }
export const BlockIcon = () => { export const BlockIcon = () => {
return <Icon width={16} height={16} />; return <Icon width={16} height={16} />
}; }
const Icon = styled(BlockSvg)` const Icon = styled(BlockSvg)`
& > path { & > path {
@ -38,4 +38,4 @@ const Icon = styled(BlockSvg)`
&:hover > path { &:hover > path {
fill: ${({ theme }) => theme.bodyBackgroundColor}; fill: ${({ theme }) => theme.bodyBackgroundColor};
} }
`; `

View File

@ -1,8 +1,8 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
interface ChainIconProps { interface ChainIconProps {
className?: string; className?: string
} }
export const ChainIcon = ({ className }: ChainIconProps) => { export const ChainIcon = ({ className }: ChainIconProps) => {
@ -17,8 +17,8 @@ export const ChainIcon = ({ className }: ChainIconProps) => {
> >
<path d="M20.4919 24.7159C20.8389 24.3784 21.0941 23.9583 21.2306 23.4878C21.4369 22.7771 21.3498 22.0383 20.9854 21.4075L19.409 18.6769C19.0542 18.0624 18.4794 17.6245 17.7859 17.4387C17.7672 17.4337 17.7484 17.4289 17.7296 17.4242C17.2537 17.3072 16.7622 17.318 16.2963 17.4498L16.0648 17.0489C16.4119 16.7113 16.6672 16.2913 16.8038 15.8207C17.01 15.11 16.9229 14.371 16.5583 13.7399L14.9818 11.0093C14.6175 10.3783 14.0207 9.93364 13.3026 9.75668C12.8268 9.63968 12.3354 9.6507 11.8696 9.78247L11.6383 9.38174C11.9854 9.04419 12.2406 8.62397 12.3771 8.15336C12.5833 7.44267 12.4961 6.70371 12.1317 6.07268L10.5555 3.34242C9.92796 2.25533 8.63218 1.78173 7.44346 2.11579L6.77962 0.966562L5.55141 1.67598L6.21505 2.82497C5.33134 3.6873 5.09343 5.04607 5.72069 6.13334L7.29678 8.86349C7.65152 9.47804 8.22631 9.91611 8.91998 10.1019C8.93866 10.1069 8.95759 10.1118 8.97645 10.1164C9.4525 10.2334 9.94405 10.2225 10.41 10.0907L10.6413 10.4915C10.2942 10.829 10.0389 11.2492 9.90228 11.7198C9.69599 12.4305 9.78306 13.1695 10.1474 13.8005L11.7239 16.5311C12.0787 17.1456 12.6535 17.5836 13.3469 17.7693C13.3656 17.7743 13.3844 17.7792 13.4032 17.7838C13.8793 17.9009 14.3708 17.8899 14.8366 17.7581L15.068 18.1587C14.7209 18.4963 14.4657 18.9166 14.3292 19.3873C14.1231 20.0981 14.2102 20.837 14.5746 21.4677L16.1507 24.1983C16.5166 24.8315 17.1093 25.2567 17.7754 25.4351C18.2525 25.5629 18.7673 25.5642 19.2634 25.4247L19.9272 26.5746L21.1557 25.8658L20.4919 24.7159ZM10.881 8.06957L10.283 7.03348L9.05454 7.74257L9.65273 8.77879C9.53961 8.77949 9.42646 8.76647 9.31528 8.73914C8.97586 8.6576 8.69461 8.44787 8.52523 8.15445L6.94922 5.42435C6.71569 5.01958 6.74147 4.53136 6.97287 4.1369L7.17981 4.49521L8.40806 3.7858L8.20171 3.42851C8.32536 3.42779 8.44744 3.44307 8.56435 3.4744C8.87937 3.5588 9.15698 3.75669 9.32721 4.05159L10.9034 6.782C11.0729 7.07532 11.1125 7.422 11.015 7.75814C10.9831 7.86787 10.938 7.97221 10.881 8.06957ZM15.3074 15.7371L14.709 14.7008L13.4807 15.4101L14.079 16.4463C13.9662 16.447 13.8531 16.4339 13.7421 16.4066C13.4017 16.3224 13.1216 16.1153 12.9523 15.8221L11.3758 13.0914C11.2065 12.7982 11.1669 12.4515 11.2645 12.1153C11.2964 12.0055 11.3416 11.901 11.3987 11.8036L11.9967 12.8396L13.2252 12.1305L12.627 11.0943C12.7398 11.0936 12.8529 11.1067 12.9638 11.134C12.9729 11.1362 12.982 11.1385 12.991 11.1409C13.3186 11.2287 13.5886 11.4329 13.7534 11.7184L15.3299 14.449L15.33 14.4491C15.4995 14.7425 15.5391 15.0891 15.4415 15.4253C15.4098 15.5352 15.3645 15.6396 15.3074 15.7371ZM19.7344 23.4038L19.5279 23.0461L18.2996 23.7553L18.5057 24.1125C18.0485 24.1155 17.6129 23.8936 17.3791 23.4891L15.8029 20.7587C15.6336 20.4655 15.594 20.1188 15.6915 19.7825C15.7234 19.6727 15.7685 19.5682 15.8256 19.4708L16.424 20.5071L17.6523 19.7978L17.054 18.7618C17.1668 18.7611 17.2796 18.7742 17.3907 18.8015C17.3997 18.8037 17.4087 18.806 17.4177 18.8084C17.7455 18.8963 18.0157 19.1006 18.1805 19.3861L19.757 22.1167L19.7571 22.1169C19.9264 22.4099 19.966 22.7564 19.8684 23.0924C19.8366 23.2021 19.7914 23.3064 19.7344 23.4038Z" /> <path d="M20.4919 24.7159C20.8389 24.3784 21.0941 23.9583 21.2306 23.4878C21.4369 22.7771 21.3498 22.0383 20.9854 21.4075L19.409 18.6769C19.0542 18.0624 18.4794 17.6245 17.7859 17.4387C17.7672 17.4337 17.7484 17.4289 17.7296 17.4242C17.2537 17.3072 16.7622 17.318 16.2963 17.4498L16.0648 17.0489C16.4119 16.7113 16.6672 16.2913 16.8038 15.8207C17.01 15.11 16.9229 14.371 16.5583 13.7399L14.9818 11.0093C14.6175 10.3783 14.0207 9.93364 13.3026 9.75668C12.8268 9.63968 12.3354 9.6507 11.8696 9.78247L11.6383 9.38174C11.9854 9.04419 12.2406 8.62397 12.3771 8.15336C12.5833 7.44267 12.4961 6.70371 12.1317 6.07268L10.5555 3.34242C9.92796 2.25533 8.63218 1.78173 7.44346 2.11579L6.77962 0.966562L5.55141 1.67598L6.21505 2.82497C5.33134 3.6873 5.09343 5.04607 5.72069 6.13334L7.29678 8.86349C7.65152 9.47804 8.22631 9.91611 8.91998 10.1019C8.93866 10.1069 8.95759 10.1118 8.97645 10.1164C9.4525 10.2334 9.94405 10.2225 10.41 10.0907L10.6413 10.4915C10.2942 10.829 10.0389 11.2492 9.90228 11.7198C9.69599 12.4305 9.78306 13.1695 10.1474 13.8005L11.7239 16.5311C12.0787 17.1456 12.6535 17.5836 13.3469 17.7693C13.3656 17.7743 13.3844 17.7792 13.4032 17.7838C13.8793 17.9009 14.3708 17.8899 14.8366 17.7581L15.068 18.1587C14.7209 18.4963 14.4657 18.9166 14.3292 19.3873C14.1231 20.0981 14.2102 20.837 14.5746 21.4677L16.1507 24.1983C16.5166 24.8315 17.1093 25.2567 17.7754 25.4351C18.2525 25.5629 18.7673 25.5642 19.2634 25.4247L19.9272 26.5746L21.1557 25.8658L20.4919 24.7159ZM10.881 8.06957L10.283 7.03348L9.05454 7.74257L9.65273 8.77879C9.53961 8.77949 9.42646 8.76647 9.31528 8.73914C8.97586 8.6576 8.69461 8.44787 8.52523 8.15445L6.94922 5.42435C6.71569 5.01958 6.74147 4.53136 6.97287 4.1369L7.17981 4.49521L8.40806 3.7858L8.20171 3.42851C8.32536 3.42779 8.44744 3.44307 8.56435 3.4744C8.87937 3.5588 9.15698 3.75669 9.32721 4.05159L10.9034 6.782C11.0729 7.07532 11.1125 7.422 11.015 7.75814C10.9831 7.86787 10.938 7.97221 10.881 8.06957ZM15.3074 15.7371L14.709 14.7008L13.4807 15.4101L14.079 16.4463C13.9662 16.447 13.8531 16.4339 13.7421 16.4066C13.4017 16.3224 13.1216 16.1153 12.9523 15.8221L11.3758 13.0914C11.2065 12.7982 11.1669 12.4515 11.2645 12.1153C11.2964 12.0055 11.3416 11.901 11.3987 11.8036L11.9967 12.8396L13.2252 12.1305L12.627 11.0943C12.7398 11.0936 12.8529 11.1067 12.9638 11.134C12.9729 11.1362 12.982 11.1385 12.991 11.1409C13.3186 11.2287 13.5886 11.4329 13.7534 11.7184L15.3299 14.449L15.33 14.4491C15.4995 14.7425 15.5391 15.0891 15.4415 15.4253C15.4098 15.5352 15.3645 15.6396 15.3074 15.7371ZM19.7344 23.4038L19.5279 23.0461L18.2996 23.7553L18.5057 24.1125C18.0485 24.1155 17.6129 23.8936 17.3791 23.4891L15.8029 20.7587C15.6336 20.4655 15.594 20.1188 15.6915 19.7825C15.7234 19.6727 15.7685 19.5682 15.8256 19.4708L16.424 20.5071L17.6523 19.7978L17.054 18.7618C17.1668 18.7611 17.2796 18.7742 17.3907 18.8015C17.3997 18.8037 17.4087 18.806 17.4177 18.8084C17.7455 18.8963 18.0157 19.1006 18.1805 19.3861L19.757 22.1167L19.7571 22.1169C19.9264 22.4099 19.966 22.7564 19.8684 23.0924C19.8366 23.2021 19.7914 23.3064 19.7344 23.4038Z" />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
@ -27,4 +27,4 @@ const Icon = styled.svg`
&.transformed { &.transformed {
transform: matrix(-0.97, 0.26, 0.26, 0.97, 0, 0); transform: matrix(-0.97, 0.26, 0.26, 0.97, 0, 0);
} }
`; `

View File

@ -1,10 +1,10 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type ChatSvgProps = { type ChatSvgProps = {
width: number; width: number
height: number; height: number
}; }
export function ChatSvg({ width, height }: ChatSvgProps) { export function ChatSvg({ width, height }: ChatSvgProps) {
return ( return (
@ -20,12 +20,12 @@ export function ChatSvg({ width, height }: ChatSvgProps) {
d="M1.69922 7.99922C1.69922 4.51983 4.51983 1.69922 7.99922 1.69922C11.4786 1.69922 14.2992 4.51983 14.2992 7.99922V11.9992C14.2992 13.2695 13.2695 14.2992 11.9992 14.2992H7.99922C4.51983 14.2992 1.69922 11.4786 1.69922 7.99922ZM7.99922 3.19922C5.34825 3.19922 3.19922 5.34825 3.19922 7.99922C3.19922 10.6502 5.34825 12.7992 7.99922 12.7992H11.9992C12.441 12.7992 12.7992 12.441 12.7992 11.9992V7.99922C12.7992 5.34825 10.6502 3.19922 7.99922 3.19922Z" d="M1.69922 7.99922C1.69922 4.51983 4.51983 1.69922 7.99922 1.69922C11.4786 1.69922 14.2992 4.51983 14.2992 7.99922V11.9992C14.2992 13.2695 13.2695 14.2992 11.9992 14.2992H7.99922C4.51983 14.2992 1.69922 11.4786 1.69922 7.99922ZM7.99922 3.19922C5.34825 3.19922 3.19922 5.34825 3.19922 7.99922C3.19922 10.6502 5.34825 12.7992 7.99922 12.7992H11.9992C12.441 12.7992 12.7992 12.441 12.7992 11.9992V7.99922C12.7992 5.34825 10.6502 3.19922 7.99922 3.19922Z"
/> />
</svg> </svg>
); )
} }
export const ChatIcon = () => { export const ChatIcon = () => {
return <Icon width={16} height={16} />; return <Icon width={16} height={16} />
}; }
const Icon = styled(ChatSvg)` const Icon = styled(ChatSvg)`
& > path { & > path {
@ -35,4 +35,4 @@ const Icon = styled(ChatSvg)`
&:hover > path { &:hover > path {
fill: ${({ theme }) => theme.bodyBackgroundColor}; fill: ${({ theme }) => theme.bodyBackgroundColor};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type CheckIconProps = { type CheckIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function CheckIcon({ width, height, className }: CheckIconProps) { export function CheckIcon({ width, height, className }: CheckIconProps) {
return ( return (
@ -23,7 +23,7 @@ export function CheckIcon({ width, height, className }: CheckIconProps) {
d="M7.99992 14.6668C4.31802 14.6668 1.33325 11.6821 1.33325 8.00016C1.33325 4.31826 4.31802 1.3335 7.99992 1.3335C11.6818 1.3335 14.6666 4.31826 14.6666 8.00016C14.6666 11.6821 11.6818 14.6668 7.99992 14.6668ZM7.99992 13.6668C4.8703 13.6668 2.33325 11.1298 2.33325 8.00016C2.33325 4.87055 4.8703 2.3335 7.99992 2.3335C11.1295 2.3335 13.6666 4.87055 13.6666 8.00016C13.6666 11.1298 11.1295 13.6668 7.99992 13.6668Z" d="M7.99992 14.6668C4.31802 14.6668 1.33325 11.6821 1.33325 8.00016C1.33325 4.31826 4.31802 1.3335 7.99992 1.3335C11.6818 1.3335 14.6666 4.31826 14.6666 8.00016C14.6666 11.6821 11.6818 14.6668 7.99992 14.6668ZM7.99992 13.6668C4.8703 13.6668 2.33325 11.1298 2.33325 8.00016C2.33325 4.87055 4.8703 2.3335 7.99992 2.3335C11.1295 2.3335 13.6666 4.87055 13.6666 8.00016C13.6666 11.1298 11.1295 13.6668 7.99992 13.6668Z"
/> />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
@ -32,4 +32,4 @@ const Icon = styled.svg`
&.green { &.green {
fill: ${({ theme }) => theme.greenColor}; fill: ${({ theme }) => theme.greenColor};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type ClearSvgProps = { type ClearSvgProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function ClearSvg({ height, width, className }: ClearSvgProps) { export function ClearSvg({ height, width, className }: ClearSvgProps) {
return ( return (
@ -23,10 +23,10 @@ export function ClearSvg({ height, width, className }: ClearSvgProps) {
d="M7.99992 14.6668C11.6818 14.6668 14.6666 11.6821 14.6666 8.00016C14.6666 4.31826 11.6818 1.3335 7.99992 1.3335C4.31802 1.3335 1.33325 4.31826 1.33325 8.00016C1.33325 11.6821 4.31802 14.6668 7.99992 14.6668ZM7.99992 13.6668C11.1295 13.6668 13.6666 11.1298 13.6666 8.00016C13.6666 4.87055 11.1295 2.3335 7.99992 2.3335C4.87031 2.3335 2.33325 4.87055 2.33325 8.00016C2.33325 11.1298 4.87031 13.6668 7.99992 13.6668Z" d="M7.99992 14.6668C11.6818 14.6668 14.6666 11.6821 14.6666 8.00016C14.6666 4.31826 11.6818 1.3335 7.99992 1.3335C4.31802 1.3335 1.33325 4.31826 1.33325 8.00016C1.33325 11.6821 4.31802 14.6668 7.99992 14.6668ZM7.99992 13.6668C11.1295 13.6668 13.6666 11.1298 13.6666 8.00016C13.6666 4.87055 11.1295 2.3335 7.99992 2.3335C4.87031 2.3335 2.33325 4.87055 2.33325 8.00016C2.33325 11.1298 4.87031 13.6668 7.99992 13.6668Z"
/> />
</Icon> </Icon>
); )
} }
<svg ;<svg
width="16" width="16"
height="16" height="16"
viewBox="0 0 16 16" viewBox="0 0 16 16"
@ -39,11 +39,11 @@ export function ClearSvg({ height, width, className }: ClearSvgProps) {
d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM11 5C11.2441 5.24408 11.2441 5.63981 11 5.88388L8.88393 8L11 10.1161C11.2441 10.3602 11.2441 10.7559 11 11C10.756 11.2441 10.3602 11.2441 10.1162 11L8.00005 8.88389L5.88393 11C5.63985 11.2441 5.24412 11.2441 5.00005 11C4.75597 10.7559 4.75597 10.3602 5.00005 10.1161L7.11616 8L5.00005 5.88389C4.75597 5.63981 4.75597 5.24408 5.00005 5C5.24412 4.75593 5.63985 4.75593 5.88393 5L8.00005 7.11612L10.1162 5C10.3602 4.75592 10.756 4.75592 11 5Z" d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM11 5C11.2441 5.24408 11.2441 5.63981 11 5.88388L8.88393 8L11 10.1161C11.2441 10.3602 11.2441 10.7559 11 11C10.756 11.2441 10.3602 11.2441 10.1162 11L8.00005 8.88389L5.88393 11C5.63985 11.2441 5.24412 11.2441 5.00005 11C4.75597 10.7559 4.75597 10.3602 5.00005 10.1161L7.11616 8L5.00005 5.88389C4.75597 5.63981 4.75597 5.24408 5.00005 5C5.24412 4.75593 5.63985 4.75593 5.88393 5L8.00005 7.11612L10.1162 5C10.3602 4.75592 10.756 4.75592 11 5Z"
fill="#939BA1" fill="#939BA1"
/> />
</svg>; </svg>
export const ClearIcon = () => { export const ClearIcon = () => {
return <Icon width={16} height={16} />; return <Icon width={16} height={16} />
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
@ -63,4 +63,4 @@ const Icon = styled.svg`
&.decline { &.decline {
fill: ${({ theme }) => theme.redColor}; fill: ${({ theme }) => theme.redColor};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type ClearSvgFullProps = { type ClearSvgFullProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function ClearSvgFull({ height, width, className }: ClearSvgFullProps) { export function ClearSvgFull({ height, width, className }: ClearSvgFullProps) {
return ( return (
@ -23,7 +23,7 @@ export function ClearSvgFull({ height, width, className }: ClearSvgFullProps) {
d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM11 5C11.2441 5.24408 11.2441 5.63981 11 5.88388L8.88393 8L11 10.1161C11.2441 10.3602 11.2441 10.7559 11 11C10.756 11.2441 10.3602 11.2441 10.1162 11L8.00005 8.88389L5.88393 11C5.63985 11.2441 5.24412 11.2441 5.00005 11C4.75597 10.7559 4.75597 10.3602 5.00005 10.1161L7.11616 8L5.00005 5.88389C4.75597 5.63981 4.75597 5.24408 5.00005 5C5.24412 4.75593 5.63985 4.75593 5.88393 5L8.00005 7.11612L10.1162 5C10.3602 4.75592 10.756 4.75592 11 5Z" d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM11 5C11.2441 5.24408 11.2441 5.63981 11 5.88388L8.88393 8L11 10.1161C11.2441 10.3602 11.2441 10.7559 11 11C10.756 11.2441 10.3602 11.2441 10.1162 11L8.00005 8.88389L5.88393 11C5.63985 11.2441 5.24412 11.2441 5.00005 11C4.75597 10.7559 4.75597 10.3602 5.00005 10.1161L7.11616 8L5.00005 5.88389C4.75597 5.63981 4.75597 5.24408 5.00005 5C5.24412 4.75593 5.63985 4.75593 5.88393 5L8.00005 7.11612L10.1162 5C10.3602 4.75592 10.756 4.75592 11 5Z"
/> />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
@ -32,4 +32,4 @@ const Icon = styled.svg`
&:hover { &:hover {
fill: ${({ theme }) => theme.primary}; fill: ${({ theme }) => theme.primary};
} }
`; `

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
export const CoinbaseLogo = () => { export const CoinbaseLogo = () => {
return ( return (
@ -46,5 +46,5 @@ export const CoinbaseLogo = () => {
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>
); )
}; }

View File

@ -1,10 +1,10 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type ColorChatSvgProps = { type ColorChatSvgProps = {
width: number; width: number
height: number; height: number
}; }
export function ColorChatSvg({ width, height }: ColorChatSvgProps) { export function ColorChatSvg({ width, height }: ColorChatSvgProps) {
return ( return (
@ -130,12 +130,12 @@ export function ColorChatSvg({ width, height }: ColorChatSvgProps) {
</clipPath> </clipPath>
</defs> </defs>
</svg> </svg>
); )
} }
export const ColorChatIcon = () => { export const ColorChatIcon = () => {
return <Icon width={64} height={64} />; return <Icon width={64} height={64} />
}; }
const Icon = styled(ColorChatSvg)` const Icon = styled(ColorChatSvg)`
& > path { & > path {
@ -145,4 +145,4 @@ const Icon = styled(ColorChatSvg)`
&:hover > path { &:hover > path {
fill: ${({ theme }) => theme.bodyBackgroundColor}; fill: ${({ theme }) => theme.bodyBackgroundColor};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type CommunityIconProps = { type CommunityIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export const CommunityIcon = ({ export const CommunityIcon = ({
width, width,
@ -27,8 +27,8 @@ export const CommunityIcon = ({
d="M10.6641 14C11.7686 14 12.6641 13.1046 12.6641 12C13.7686 12 14.6641 11.1046 14.6641 10V4C14.6641 2.89543 13.7686 2 12.6641 2C7.14121 2 2.66406 6.47715 2.66406 12C2.66406 13.1046 3.55949 14 4.66406 14H10.6641ZM5.16406 12C4.88792 12 4.66244 11.7755 4.67944 11.4999C4.92738 7.47997 8.14404 4.26332 12.164 4.01538C12.4396 3.99838 12.6641 4.22386 12.6641 4.5V5.5C12.6641 5.77614 12.4394 5.99783 12.1642 6.02052C9.24919 6.26094 6.925 8.58513 6.68459 11.5002C6.66189 11.7754 6.4402 12 6.16406 12H5.16406ZM12.6641 8.5C12.6641 8.22386 12.4391 7.99672 12.1651 8.03082C10.3549 8.25609 8.92015 9.69083 8.69489 11.501C8.66078 11.775 8.88792 12 9.16406 12H10.1641C10.4402 12 10.6576 11.7727 10.7258 11.5051C10.9057 10.7982 11.4622 10.2417 12.1691 10.0617C12.4367 9.99359 12.6641 9.77614 12.6641 9.5V8.5Z" d="M10.6641 14C11.7686 14 12.6641 13.1046 12.6641 12C13.7686 12 14.6641 11.1046 14.6641 10V4C14.6641 2.89543 13.7686 2 12.6641 2C7.14121 2 2.66406 6.47715 2.66406 12C2.66406 13.1046 3.55949 14 4.66406 14H10.6641ZM5.16406 12C4.88792 12 4.66244 11.7755 4.67944 11.4999C4.92738 7.47997 8.14404 4.26332 12.164 4.01538C12.4396 3.99838 12.6641 4.22386 12.6641 4.5V5.5C12.6641 5.77614 12.4394 5.99783 12.1642 6.02052C9.24919 6.26094 6.925 8.58513 6.68459 11.5002C6.66189 11.7754 6.4402 12 6.16406 12H5.16406ZM12.6641 8.5C12.6641 8.22386 12.4391 7.99672 12.1651 8.03082C10.3549 8.25609 8.92015 9.69083 8.69489 11.501C8.66078 11.775 8.88792 12 9.16406 12H10.1641C10.4402 12 10.6576 11.7727 10.7258 11.5051C10.9057 10.7982 11.4622 10.2417 12.1691 10.0617C12.4367 9.99359 12.6641 9.77614 12.6641 9.5V8.5Z"
/> />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
@ -40,4 +40,4 @@ const Icon = styled.svg`
&.red { &.red {
fill: ${({ theme }) => theme.redColor}; fill: ${({ theme }) => theme.redColor};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type CopyIconProps = { type CopyIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function CopyIcon({ width, height, className }: CopyIconProps) { export function CopyIcon({ width, height, className }: CopyIconProps) {
return ( return (
@ -23,9 +23,9 @@ export function CopyIcon({ width, height, className }: CopyIconProps) {
d="M6.00016 4.00065C6.00016 2.52789 7.19407 1.33398 8.66683 1.33398H12.0002C13.4729 1.33398 14.6668 2.52789 14.6668 4.00065V7.33398C14.6668 8.80674 13.4729 10.0007 12.0002 10.0007H8.66683C7.19407 10.0007 6.00016 8.80674 6.00016 7.33398V4.00065ZM8.66683 2.33398H12.0002C12.9206 2.33398 13.6668 3.08018 13.6668 4.00065V7.33398C13.6668 8.25446 12.9206 9.00065 12.0002 9.00065H8.66683C7.74636 9.00065 7.00016 8.25446 7.00016 7.33398V4.00065C7.00016 3.08018 7.74636 2.33398 8.66683 2.33398Z" d="M6.00016 4.00065C6.00016 2.52789 7.19407 1.33398 8.66683 1.33398H12.0002C13.4729 1.33398 14.6668 2.52789 14.6668 4.00065V7.33398C14.6668 8.80674 13.4729 10.0007 12.0002 10.0007H8.66683C7.19407 10.0007 6.00016 8.80674 6.00016 7.33398V4.00065ZM8.66683 2.33398H12.0002C12.9206 2.33398 13.6668 3.08018 13.6668 4.00065V7.33398C13.6668 8.25446 12.9206 9.00065 12.0002 9.00065H8.66683C7.74636 9.00065 7.00016 8.25446 7.00016 7.33398V4.00065C7.00016 3.08018 7.74636 2.33398 8.66683 2.33398Z"
/> />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
export const CreateIcon = () => { export const CreateIcon = () => {
return ( return (
@ -17,11 +17,11 @@ export const CreateIcon = () => {
d="M21.2803 2.71986C20.2971 1.73661 18.7029 1.73661 17.7197 2.71986L9.33613 11.1034C9.00567 11.4339 8.76487 11.8431 8.63648 12.2925L7.77886 15.2941C7.70403 15.556 7.77707 15.8379 7.96967 16.0305C8.16227 16.2231 8.44415 16.2962 8.70604 16.2213L11.7077 15.3637C12.1571 15.2353 12.5663 14.9945 12.8968 14.6641L21.2803 6.28052C22.2636 5.29727 22.2636 3.70311 21.2803 2.71986ZM18.7803 3.78052C19.1778 3.38306 19.8222 3.38306 20.2197 3.78052C20.6171 4.17798 20.6171 4.8224 20.2197 5.21986L11.8361 13.6034C11.6859 13.7536 11.4999 13.8631 11.2956 13.9214C10.5531 14.1336 9.86662 13.4471 10.0788 12.7045C10.1371 12.5003 10.2466 12.3143 10.3968 12.1641L18.7803 3.78052Z" d="M21.2803 2.71986C20.2971 1.73661 18.7029 1.73661 17.7197 2.71986L9.33613 11.1034C9.00567 11.4339 8.76487 11.8431 8.63648 12.2925L7.77886 15.2941C7.70403 15.556 7.77707 15.8379 7.96967 16.0305C8.16227 16.2231 8.44415 16.2962 8.70604 16.2213L11.7077 15.3637C12.1571 15.2353 12.5663 14.9945 12.8968 14.6641L21.2803 6.28052C22.2636 5.29727 22.2636 3.70311 21.2803 2.71986ZM18.7803 3.78052C19.1778 3.38306 19.8222 3.38306 20.2197 3.78052C20.6171 4.17798 20.6171 4.8224 20.2197 5.21986L11.8361 13.6034C11.6859 13.7536 11.4999 13.8631 11.2956 13.9214C10.5531 14.1336 9.86662 13.4471 10.0788 12.7045C10.1371 12.5003 10.2466 12.3143 10.3968 12.1641L18.7803 3.78052Z"
/> />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
fill: ${({ theme }) => theme.primary}; fill: ${({ theme }) => theme.primary};
} }
`; `

View File

@ -1,8 +1,8 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
interface CrossIconProps { interface CrossIconProps {
memberView?: boolean; memberView?: boolean
} }
export const CrossIcon = ({ memberView }: CrossIconProps) => ( export const CrossIcon = ({ memberView }: CrossIconProps) => (
@ -12,7 +12,7 @@ export const CrossIcon = ({ memberView }: CrossIconProps) => (
viewBox="0 0 12 12" viewBox="0 0 12 12"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
className={memberView ? "white" : ""} className={memberView ? 'white' : ''}
> >
<path <path
fillRule="evenodd" fillRule="evenodd"
@ -20,7 +20,7 @@ export const CrossIcon = ({ memberView }: CrossIconProps) => (
d="M6 4.57404L1.72275 0.296796C1.32616 -0.0997918 0.689941 -0.0975927 0.296174 0.296174C-0.100338 0.692686 -0.0973145 1.32864 0.296796 1.72275L4.57404 6L0.296796 10.2772C-0.0997918 10.6738 -0.0975927 11.3101 0.296174 11.7038C0.692686 12.1003 1.32864 12.0973 1.72275 11.7032L6 7.42596L10.2772 11.7032C10.6738 12.0998 11.3101 12.0976 11.7038 11.7038C12.1003 11.3073 12.0973 10.6714 11.7032 10.2772L7.42596 6L11.7032 1.72275C12.0998 1.32616 12.0976 0.689941 11.7038 0.296174C11.3073 -0.100338 10.6714 -0.0973145 10.2772 0.296796L6 4.57404Z" d="M6 4.57404L1.72275 0.296796C1.32616 -0.0997918 0.689941 -0.0975927 0.296174 0.296174C-0.100338 0.692686 -0.0973145 1.32864 0.296796 1.72275L4.57404 6L0.296796 10.2772C-0.0997918 10.6738 -0.0975927 11.3101 0.296174 11.7038C0.692686 12.1003 1.32864 12.0973 1.72275 11.7032L6 7.42596L10.2772 11.7032C10.6738 12.0998 11.3101 12.0976 11.7038 11.7038C12.1003 11.3073 12.0973 10.6714 11.7032 10.2772L7.42596 6L11.7032 1.72275C12.0998 1.32616 12.0976 0.689941 11.7038 0.296174C11.3073 -0.100338 10.6714 -0.0973145 10.2772 0.296796L6 4.57404Z"
/> />
</Icon> </Icon>
); )
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
@ -32,4 +32,4 @@ const Icon = styled.svg`
fill: ${({ theme }) => theme.bodyBackgroundColor}; fill: ${({ theme }) => theme.bodyBackgroundColor};
} }
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type DeleteIconProps = { type DeleteIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export const DeleteIcon = ({ width, height, className }: DeleteIconProps) => { export const DeleteIcon = ({ width, height, className }: DeleteIconProps) => {
return ( return (
@ -22,8 +22,8 @@ export const DeleteIcon = ({ width, height, className }: DeleteIconProps) => {
d="M6.26191 1.5C5.47293 1.5 4.83333 2.13959 4.83333 2.92857C4.83333 3.33621 4.50288 3.66667 4.09524 3.66667H2C1.72386 3.66667 1.5 3.89052 1.5 4.16667C1.5 4.44281 1.72386 4.66667 2 4.66667H2.49251C2.66109 4.66667 2.80314 4.79253 2.82342 4.95989L3.71566 12.3209C3.87795 13.6597 5.0143 14.6667 6.36295 14.6667H9.63705C10.9857 14.6667 12.1221 13.6597 12.2843 12.3209L13.1766 4.95989C13.1969 4.79253 13.3389 4.66667 13.5075 4.66667H14C14.2761 4.66667 14.5 4.44281 14.5 4.16667C14.5 3.89052 14.2761 3.66667 14 3.66667H11.9048C11.4971 3.66667 11.1667 3.33621 11.1667 2.92857C11.1667 2.13959 10.5271 1.5 9.7381 1.5L6.26191 1.5ZM9.80586 3.66667C10.0501 3.66667 10.2156 3.40724 10.1826 3.16524C10.1721 3.08786 10.1667 3.00885 10.1667 2.92857C10.1667 2.69188 9.97479 2.5 9.7381 2.5L6.2619 2.5C6.02521 2.5 5.83333 2.69188 5.83333 2.92857C5.83333 3.00885 5.82789 3.08786 5.81736 3.16524C5.78441 3.40725 5.9499 3.66667 6.19414 3.66667L9.80586 3.66667ZM11.9048 4.66667C12.0643 4.66667 12.1879 4.80617 12.1687 4.96453L11.2916 12.2006C11.1902 13.0373 10.48 13.6667 9.63705 13.6667H6.36295C5.52004 13.6667 4.80983 13.0373 4.7084 12.2006L3.8313 4.96453C3.81211 4.80616 3.93572 4.66667 4.09524 4.66667L11.9048 4.66667Z" d="M6.26191 1.5C5.47293 1.5 4.83333 2.13959 4.83333 2.92857C4.83333 3.33621 4.50288 3.66667 4.09524 3.66667H2C1.72386 3.66667 1.5 3.89052 1.5 4.16667C1.5 4.44281 1.72386 4.66667 2 4.66667H2.49251C2.66109 4.66667 2.80314 4.79253 2.82342 4.95989L3.71566 12.3209C3.87795 13.6597 5.0143 14.6667 6.36295 14.6667H9.63705C10.9857 14.6667 12.1221 13.6597 12.2843 12.3209L13.1766 4.95989C13.1969 4.79253 13.3389 4.66667 13.5075 4.66667H14C14.2761 4.66667 14.5 4.44281 14.5 4.16667C14.5 3.89052 14.2761 3.66667 14 3.66667H11.9048C11.4971 3.66667 11.1667 3.33621 11.1667 2.92857C11.1667 2.13959 10.5271 1.5 9.7381 1.5L6.26191 1.5ZM9.80586 3.66667C10.0501 3.66667 10.2156 3.40724 10.1826 3.16524C10.1721 3.08786 10.1667 3.00885 10.1667 2.92857C10.1667 2.69188 9.97479 2.5 9.7381 2.5L6.2619 2.5C6.02521 2.5 5.83333 2.69188 5.83333 2.92857C5.83333 3.00885 5.82789 3.08786 5.81736 3.16524C5.78441 3.40725 5.9499 3.66667 6.19414 3.66667L9.80586 3.66667ZM11.9048 4.66667C12.0643 4.66667 12.1879 4.80617 12.1687 4.96453L11.2916 12.2006C11.1902 13.0373 10.48 13.6667 9.63705 13.6667H6.36295C5.52004 13.6667 4.80983 13.0373 4.7084 12.2006L3.8313 4.96453C3.81211 4.80616 3.93572 4.66667 4.09524 4.66667L11.9048 4.66667Z"
/> />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
@ -35,4 +35,4 @@ const Icon = styled.svg`
&.grey { &.grey {
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type DownloadIconProps = { type DownloadIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function DownloadIcon({ width, height, className }: DownloadIconProps) { export function DownloadIcon({ width, height, className }: DownloadIconProps) {
return ( return (
@ -19,9 +19,9 @@ export function DownloadIcon({ width, height, className }: DownloadIconProps) {
<path d="M10.6668 8.83399C10.6668 8.55784 10.8924 8.33835 11.1647 8.29286C12.5846 8.05568 13.6668 6.82121 13.6668 5.33399C13.6668 3.67713 12.3237 2.33399 10.6668 2.33399L5.3335 2.33399C3.67664 2.33399 2.3335 3.67713 2.3335 5.33399C2.3335 6.82121 3.4157 8.05568 4.83559 8.29286C5.10796 8.33835 5.3335 8.55784 5.3335 8.83399C5.3335 9.11013 5.10852 9.33726 4.83449 9.30316C2.86085 9.05755 1.3335 7.37414 1.3335 5.33399C1.3335 3.12485 3.12436 1.33398 5.3335 1.33398L10.6668 1.33399C12.876 1.33399 14.6668 3.12485 14.6668 5.33399C14.6668 7.37414 13.1395 9.05755 11.1658 9.30316C10.8918 9.33726 10.6668 9.11013 10.6668 8.83399Z" /> <path d="M10.6668 8.83399C10.6668 8.55784 10.8924 8.33835 11.1647 8.29286C12.5846 8.05568 13.6668 6.82121 13.6668 5.33399C13.6668 3.67713 12.3237 2.33399 10.6668 2.33399L5.3335 2.33399C3.67664 2.33399 2.3335 3.67713 2.3335 5.33399C2.3335 6.82121 3.4157 8.05568 4.83559 8.29286C5.10796 8.33835 5.3335 8.55784 5.3335 8.83399C5.3335 9.11013 5.10852 9.33726 4.83449 9.30316C2.86085 9.05755 1.3335 7.37414 1.3335 5.33399C1.3335 3.12485 3.12436 1.33398 5.3335 1.33398L10.6668 1.33399C12.876 1.33399 14.6668 3.12485 14.6668 5.33399C14.6668 7.37414 13.1395 9.05755 11.1658 9.30316C10.8918 9.33726 10.6668 9.11013 10.6668 8.83399Z" />
<path d="M8.00016 4.83399C8.27631 4.83399 8.50016 5.05784 8.50016 5.33399V11.9888C8.50016 12.2858 8.85921 12.4345 9.0692 12.2245L10.3133 10.9804C10.5085 10.7852 10.8251 10.7852 11.0204 10.9804C11.2156 11.1757 11.2156 11.4923 11.0204 11.6875L8.35372 14.3542C8.15845 14.5495 7.84187 14.5495 7.64661 14.3542L4.97994 11.6875C4.78468 11.4923 4.78468 11.1757 4.97994 10.9804C5.1752 10.7852 5.49179 10.7852 5.68705 10.9804L6.93113 12.2245C7.14112 12.4345 7.50016 12.2858 7.50016 11.9888V5.33399C7.50016 5.05784 7.72402 4.83399 8.00016 4.83399Z" /> <path d="M8.00016 4.83399C8.27631 4.83399 8.50016 5.05784 8.50016 5.33399V11.9888C8.50016 12.2858 8.85921 12.4345 9.0692 12.2245L10.3133 10.9804C10.5085 10.7852 10.8251 10.7852 11.0204 10.9804C11.2156 11.1757 11.2156 11.4923 11.0204 11.6875L8.35372 14.3542C8.15845 14.5495 7.84187 14.5495 7.64661 14.3542L4.97994 11.6875C4.78468 11.4923 4.78468 11.1757 4.97994 10.9804C5.1752 10.7852 5.49179 10.7852 5.68705 10.9804L6.93113 12.2245C7.14112 12.4345 7.50016 12.2858 7.50016 11.9888V5.33399C7.50016 5.05784 7.72402 4.83399 8.00016 4.83399Z" />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type EditIconProps = { type EditIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function EditIcon({ width, height, className }: EditIconProps) { export function EditIcon({ width, height, className }: EditIconProps) {
return ( return (
@ -22,7 +22,7 @@ export function EditIcon({ width, height, className }: EditIconProps) {
d="M10.7914 2.16376C11.6321 1.32302 12.9952 1.32302 13.836 2.16376C14.6767 3.00451 14.6767 4.36763 13.836 5.20838L6.0015 13.0429C5.71671 13.3276 5.36405 13.5352 4.97679 13.6458L2.1717 14.4472C1.99679 14.4972 1.80854 14.4484 1.67992 14.3198C1.55129 14.1912 1.50251 14.0029 1.55249 13.828L2.35394 11.0229C2.46459 10.6357 2.6721 10.283 2.95688 9.99823L10.7914 2.16376ZM13.1276 2.87212C12.6781 2.42258 11.9492 2.42258 11.4997 2.87212L3.66524 10.7066C3.50083 10.871 3.38103 11.0746 3.31716 11.2981C3.07579 12.1429 3.85682 12.9239 4.70159 12.6826C4.92515 12.6187 5.12874 12.4989 5.29315 12.3345L13.1276 4.50003C13.5772 4.05049 13.5772 3.32165 13.1276 2.87212Z" d="M10.7914 2.16376C11.6321 1.32302 12.9952 1.32302 13.836 2.16376C14.6767 3.00451 14.6767 4.36763 13.836 5.20838L6.0015 13.0429C5.71671 13.3276 5.36405 13.5352 4.97679 13.6458L2.1717 14.4472C1.99679 14.4972 1.80854 14.4484 1.67992 14.3198C1.55129 14.1912 1.50251 14.0029 1.55249 13.828L2.35394 11.0229C2.46459 10.6357 2.6721 10.283 2.95688 9.99823L10.7914 2.16376ZM13.1276 2.87212C12.6781 2.42258 11.9492 2.42258 11.4997 2.87212L3.66524 10.7066C3.50083 10.871 3.38103 11.0746 3.31716 11.2981C3.07579 12.1429 3.85682 12.9239 4.70159 12.6826C4.92515 12.6187 5.12874 12.4989 5.29315 12.3345L13.1276 4.50003C13.5772 4.05049 13.5772 3.32165 13.1276 2.87212Z"
/> />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
@ -31,4 +31,4 @@ const Icon = styled.svg`
&.grey { &.grey {
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
} }
`; `

View File

@ -1,8 +1,8 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
interface ThemeProps { interface ThemeProps {
isActive?: boolean; isActive?: boolean
} }
export const EmojiIcon = ({ isActive }: ThemeProps) => { export const EmojiIcon = ({ isActive }: ThemeProps) => {
@ -14,26 +14,26 @@ export const EmojiIcon = ({ isActive }: ThemeProps) => {
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
fillRule="evenodd" fillRule="evenodd"
clipRule="evenodd" clipRule="evenodd"
d="M10 18.5C14.6944 18.5 18.5 14.6944 18.5 10C18.5 5.30558 14.6944 1.5 10 1.5C5.30558 1.5 1.5 5.30558 1.5 10C1.5 14.6944 5.30558 18.5 10 18.5ZM10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20Z" d="M10 18.5C14.6944 18.5 18.5 14.6944 18.5 10C18.5 5.30558 14.6944 1.5 10 1.5C5.30558 1.5 1.5 5.30558 1.5 10C1.5 14.6944 5.30558 18.5 10 18.5ZM10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20Z"
/> />
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
d="M7.56858 13.1746C7.22903 12.9373 6.75712 12.9308 6.46422 13.2237C6.17133 13.5166 6.16876 13.996 6.49708 14.2485C7.46695 14.9946 8.68155 15.4381 9.99976 15.4381C11.318 15.4381 12.5326 14.9946 13.5024 14.2485C13.8308 13.996 13.8282 13.5166 13.5353 13.2237C13.2424 12.9308 12.7705 12.9373 12.4309 13.1746C11.742 13.6558 10.9039 13.9381 9.99976 13.9381C9.09565 13.9381 8.25747 13.6558 7.56858 13.1746Z" d="M7.56858 13.1746C7.22903 12.9373 6.75712 12.9308 6.46422 13.2237C6.17133 13.5166 6.16876 13.996 6.49708 14.2485C7.46695 14.9946 8.68155 15.4381 9.99976 15.4381C11.318 15.4381 12.5326 14.9946 13.5024 14.2485C13.8308 13.996 13.8282 13.5166 13.5353 13.2237C13.2424 12.9308 12.7705 12.9373 12.4309 13.1746C11.742 13.6558 10.9039 13.9381 9.99976 13.9381C9.09565 13.9381 8.25747 13.6558 7.56858 13.1746Z"
/> />
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
d="M15 8.5C15 9.32843 14.3284 10 13.5 10C12.6716 10 12 9.32843 12 8.5C12 7.67157 12.6716 7 13.5 7C14.3284 7 15 7.67157 15 8.5Z" d="M15 8.5C15 9.32843 14.3284 10 13.5 10C12.6716 10 12 9.32843 12 8.5C12 7.67157 12.6716 7 13.5 7C14.3284 7 15 7.67157 15 8.5Z"
/> />
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
d="M8 8.5C8 9.32843 7.32843 10 6.5 10C5.67157 10 5 9.32843 5 8.5C5 7.67157 5.67157 7 6.5 7C7.32843 7 8 7.67157 8 8.5Z" d="M8 8.5C8 9.32843 7.32843 10 6.5 10C5.67157 10 5 9.32843 5 8.5C5 7.67157 5.67157 7 6.5 7C7.32843 7 8 7.67157 8 8.5Z"
/> />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
@ -43,4 +43,4 @@ const Icon = styled.svg`
& > path.active { & > path.active {
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
} }
`; `

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
export const EthereumLogo = () => ( export const EthereumLogo = () => (
<svg <svg
@ -35,4 +35,4 @@ export const EthereumLogo = () => (
fillOpacity="0.602" fillOpacity="0.602"
/> />
</svg> </svg>
); )

View File

@ -1,8 +1,8 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
interface ThemeProps { interface ThemeProps {
isActive?: boolean; isActive?: boolean
} }
export const GifIcon = ({ isActive }: ThemeProps) => { export const GifIcon = ({ isActive }: ThemeProps) => {
@ -14,26 +14,26 @@ export const GifIcon = ({ isActive }: ThemeProps) => {
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
fillRule="evenodd" fillRule="evenodd"
clipRule="evenodd" clipRule="evenodd"
d="M16 1.5H4C2.61929 1.5 1.5 2.61929 1.5 4V16C1.5 17.3807 2.61929 18.5 4 18.5H16C17.3807 18.5 18.5 17.3807 18.5 16V4C18.5 2.61929 17.3807 1.5 16 1.5ZM4 0C1.79086 0 0 1.79086 0 4V16C0 18.2091 1.79086 20 4 20H16C18.2091 20 20 18.2091 20 16V4C20 1.79086 18.2091 0 16 0H4Z" d="M16 1.5H4C2.61929 1.5 1.5 2.61929 1.5 4V16C1.5 17.3807 2.61929 18.5 4 18.5H16C17.3807 18.5 18.5 17.3807 18.5 16V4C18.5 2.61929 17.3807 1.5 16 1.5ZM4 0C1.79086 0 0 1.79086 0 4V16C0 18.2091 1.79086 20 4 20H16C18.2091 20 20 18.2091 20 16V4C20 1.79086 18.2091 0 16 0H4Z"
/> />
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
d="M8.72261 11.4868V10.4133C8.72261 9.99528 8.38061 9.65328 7.96261 9.65328H6.22411C5.90111 9.65328 5.64461 9.90978 5.64461 10.2328C5.64461 10.5748 5.90111 10.8313 6.22411 10.8313H7.37361V11.5913C7.11711 11.8288 6.58511 12.0758 6.02461 12.0758C4.87511 12.0758 4.03911 11.1923 4.03911 9.99528C4.03911 8.79828 4.87511 7.91478 6.02461 7.91478C6.50911 7.91478 6.98411 8.12378 7.34511 8.47528C7.46861 8.59878 7.63961 8.66528 7.80111 8.66528C8.13361 8.66528 8.43761 8.38978 8.43761 8.05728C8.43761 7.91478 8.38061 7.76278 8.27611 7.64878C7.78211 7.11678 7.05061 6.71778 6.02461 6.71778C4.17211 6.71778 2.65211 7.99078 2.65211 9.99528C2.65211 11.9903 4.17211 13.2823 6.02461 13.2823C7.30711 13.2823 8.72261 12.6363 8.72261 11.4868Z" d="M8.72261 11.4868V10.4133C8.72261 9.99528 8.38061 9.65328 7.96261 9.65328H6.22411C5.90111 9.65328 5.64461 9.90978 5.64461 10.2328C5.64461 10.5748 5.90111 10.8313 6.22411 10.8313H7.37361V11.5913C7.11711 11.8288 6.58511 12.0758 6.02461 12.0758C4.87511 12.0758 4.03911 11.1923 4.03911 9.99528C4.03911 8.79828 4.87511 7.91478 6.02461 7.91478C6.50911 7.91478 6.98411 8.12378 7.34511 8.47528C7.46861 8.59878 7.63961 8.66528 7.80111 8.66528C8.13361 8.66528 8.43761 8.38978 8.43761 8.05728C8.43761 7.91478 8.38061 7.76278 8.27611 7.64878C7.78211 7.11678 7.05061 6.71778 6.02461 6.71778C4.17211 6.71778 2.65211 7.99078 2.65211 9.99528C2.65211 11.9903 4.17211 13.2823 6.02461 13.2823C7.30711 13.2823 8.72261 12.6363 8.72261 11.4868Z"
/> />
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
d="M11.4392 12.5603V7.43978C11.4392 7.07878 11.1352 6.77478 10.7742 6.77478C10.3942 6.77478 10.0902 7.07878 10.0902 7.43978V12.5603C10.0902 12.9213 10.3942 13.2253 10.7552 13.2253C11.1352 13.2253 11.4392 12.9213 11.4392 12.5603Z" d="M11.4392 12.5603V7.43978C11.4392 7.07878 11.1352 6.77478 10.7742 6.77478C10.3942 6.77478 10.0902 7.07878 10.0902 7.43978V12.5603C10.0902 12.9213 10.3942 13.2253 10.7552 13.2253C11.1352 13.2253 11.4392 12.9213 11.4392 12.5603Z"
/> />
<path <path
className={isActive ? "active" : ""} className={isActive ? 'active' : ''}
d="M17.3479 7.43029C17.3479 7.09778 17.0819 6.83179 16.7684 6.83179H13.5669C13.1489 6.83179 12.8069 7.17379 12.8069 7.59179V12.5603C12.8069 12.9213 13.1109 13.2253 13.4719 13.2253C13.8519 13.2253 14.1559 12.9213 14.1559 12.5603V11.0463C14.1559 10.7701 14.3797 10.5463 14.6559 10.5463H16.2425C16.556 10.5463 16.822 10.2803 16.822 9.95728C16.822 9.62478 16.556 9.35879 16.2425 9.35879H14.6559C14.3797 9.35879 14.1559 9.13493 14.1559 8.85879V8.51929C14.1559 8.24314 14.3797 8.01929 14.6559 8.01929H16.7684C17.0819 8.01929 17.3479 7.75329 17.3479 7.43029Z" d="M17.3479 7.43029C17.3479 7.09778 17.0819 6.83179 16.7684 6.83179H13.5669C13.1489 6.83179 12.8069 7.17379 12.8069 7.59179V12.5603C12.8069 12.9213 13.1109 13.2253 13.4719 13.2253C13.8519 13.2253 14.1559 12.9213 14.1559 12.5603V11.0463C14.1559 10.7701 14.3797 10.5463 14.6559 10.5463H16.2425C16.556 10.5463 16.822 10.2803 16.822 9.95728C16.822 9.62478 16.556 9.35879 16.2425 9.35879H14.6559C14.3797 9.35879 14.1559 9.13493 14.1559 8.85879V8.51929C14.1559 8.24314 14.3797 8.01929 14.6559 8.01929H16.7684C17.0819 8.01929 17.3479 7.75329 17.3479 7.43029Z"
/> />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
@ -43,4 +43,4 @@ const Icon = styled.svg`
& > path.active { & > path.active {
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
} }
`; `

View File

@ -1,8 +1,8 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
interface GroupIconProps { interface GroupIconProps {
active?: boolean; active?: boolean
} }
export const GroupIcon = ({ active }: GroupIconProps) => { export const GroupIcon = ({ active }: GroupIconProps) => {
@ -13,15 +13,15 @@ export const GroupIcon = ({ active }: GroupIconProps) => {
viewBox="0 0 14 10" viewBox="0 0 14 10"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
className={`${active && "active"}`} className={`${active && 'active'}`}
> >
<path d="M7 4.5C8.24265 4.5 9.25 3.49264 9.25 2.25C9.25 1.00736 8.24265 0 7 0C5.75736 0 4.75 1.00736 4.75 2.25C4.75 3.49264 5.75736 4.5 7 4.5Z" /> <path d="M7 4.5C8.24265 4.5 9.25 3.49264 9.25 2.25C9.25 1.00736 8.24265 0 7 0C5.75736 0 4.75 1.00736 4.75 2.25C4.75 3.49264 5.75736 4.5 7 4.5Z" />
<path d="M3.12343 9.01012C3.56395 7.27976 5.13252 6 7 6C8.86749 6 10.4361 7.27976 10.8766 9.01012C11.0128 9.54533 10.5523 10 10 10H4C3.44772 10 2.98718 9.54533 3.12343 9.01012Z" /> <path d="M3.12343 9.01012C3.56395 7.27976 5.13252 6 7 6C8.86749 6 10.4361 7.27976 10.8766 9.01012C11.0128 9.54533 10.5523 10 10 10H4C3.44772 10 2.98718 9.54533 3.12343 9.01012Z" />
<path d="M3.5 4.25C3.5 5.2165 2.7165 6 1.75 6C0.783502 6 0 5.2165 0 4.25C0 3.2835 0.783502 2.5 1.75 2.5C2.7165 2.5 3.5 3.2835 3.5 4.25Z" /> <path d="M3.5 4.25C3.5 5.2165 2.7165 6 1.75 6C0.783502 6 0 5.2165 0 4.25C0 3.2835 0.783502 2.5 1.75 2.5C2.7165 2.5 3.5 3.2835 3.5 4.25Z" />
<path d="M12.25 6C13.2165 6 14 5.2165 14 4.25C14 3.2835 13.2165 2.5 12.25 2.5C11.2835 2.5 10.5 3.2835 10.5 4.25C10.5 5.2165 11.2835 6 12.25 6Z" /> <path d="M12.25 6C13.2165 6 14 5.2165 14 4.25C14 3.2835 13.2165 2.5 12.25 2.5C11.2835 2.5 10.5 3.2835 10.5 4.25C10.5 5.2165 11.2835 6 12.25 6Z" />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
@ -29,4 +29,4 @@ const Icon = styled.svg`
&.active { &.active {
fill: ${({ theme }) => theme.primary}; fill: ${({ theme }) => theme.primary};
} }
`; `

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
export const HideIcon = () => ( export const HideIcon = () => (
<Icon <Icon
@ -17,8 +17,8 @@ export const HideIcon = () => (
<path d="M8.85753 6.41675C8.56645 6.19035 8.61339 5.73908 8.95606 5.60284C9.89767 5.22846 10.9163 5 12.0003 5C17.0371 5 20.6645 9.93293 21.6993 11.5167C21.893 11.8132 21.893 12.1868 21.6993 12.4833C21.3897 12.9571 20.8481 13.7307 20.1061 14.5822C19.9349 14.7787 19.6402 14.8032 19.4344 14.6432L19.0412 14.3374C18.8097 14.1573 18.7827 13.8179 18.9753 13.5967C19.1214 13.429 19.2592 13.2645 19.3883 13.1052C19.9119 12.459 19.9119 11.541 19.3883 10.8948C18.8556 10.2375 18.1761 9.49212 17.373 8.80219C15.8471 7.49116 14.0175 6.5 12.0003 6.5C11.2517 6.5 10.529 6.63648 9.83805 6.87515C9.672 6.93251 9.48731 6.90658 9.34863 6.79872L8.85753 6.41675Z" /> <path d="M8.85753 6.41675C8.56645 6.19035 8.61339 5.73908 8.95606 5.60284C9.89767 5.22846 10.9163 5 12.0003 5C17.0371 5 20.6645 9.93293 21.6993 11.5167C21.893 11.8132 21.893 12.1868 21.6993 12.4833C21.3897 12.9571 20.8481 13.7307 20.1061 14.5822C19.9349 14.7787 19.6402 14.8032 19.4344 14.6432L19.0412 14.3374C18.8097 14.1573 18.7827 13.8179 18.9753 13.5967C19.1214 13.429 19.2592 13.2645 19.3883 13.1052C19.9119 12.459 19.9119 11.541 19.3883 10.8948C18.8556 10.2375 18.1761 9.49212 17.373 8.80219C15.8471 7.49116 14.0175 6.5 12.0003 6.5C11.2517 6.5 10.529 6.63648 9.83805 6.87515C9.672 6.93251 9.48731 6.90658 9.34863 6.79872L8.85753 6.41675Z" />
<path d="M15.8618 10.9529C15.9709 11.3561 15.5158 11.5954 15.1862 11.339L13.7844 10.2487C13.6279 10.0894 13.4503 9.95089 13.2561 9.83783L11.8057 8.70975C11.4964 8.46923 11.6085 8 12.0002 8C13.8471 8 15.4016 9.25163 15.8618 10.9529Z" /> <path d="M15.8618 10.9529C15.9709 11.3561 15.5158 11.5954 15.1862 11.339L13.7844 10.2487C13.6279 10.0894 13.4503 9.95089 13.2561 9.83783L11.8057 8.70975C11.4964 8.46923 11.6085 8 12.0002 8C13.8471 8 15.4016 9.25163 15.8618 10.9529Z" />
</Icon> </Icon>
); )
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type LeftIconProps = { type LeftIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function LeftIcon({ width, height, className }: LeftIconProps) { export function LeftIcon({ width, height, className }: LeftIconProps) {
return ( return (
@ -18,7 +18,7 @@ export function LeftIcon({ width, height, className }: LeftIconProps) {
> >
<path d="M7.01957 4.35355C7.21483 4.15829 7.21483 3.84171 7.01957 3.64645C6.82431 3.45118 6.50772 3.45118 6.31246 3.64645L2.31246 7.64645C2.1172 7.84171 2.1172 8.15829 2.31246 8.35355L6.31246 12.3536C6.50772 12.5488 6.82431 12.5488 7.01957 12.3536C7.21483 12.1583 7.21483 11.8417 7.01957 11.6464L4.44216 9.06904C4.23217 8.85905 4.38089 8.5 4.67786 8.5H13.3327C13.6088 8.5 13.8327 8.27614 13.8327 8C13.8327 7.72386 13.6088 7.5 13.3327 7.5H4.67786C4.38089 7.5 4.23217 7.14095 4.44216 6.93096L7.01957 4.35355Z" /> <path d="M7.01957 4.35355C7.21483 4.15829 7.21483 3.84171 7.01957 3.64645C6.82431 3.45118 6.50772 3.45118 6.31246 3.64645L2.31246 7.64645C2.1172 7.84171 2.1172 8.15829 2.31246 8.35355L6.31246 12.3536C6.50772 12.5488 6.82431 12.5488 7.01957 12.3536C7.21483 12.1583 7.21483 11.8417 7.01957 11.6464L4.44216 9.06904C4.23217 8.85905 4.38089 8.5 4.67786 8.5H13.3327C13.6088 8.5 13.8327 8.27614 13.8327 8C13.8327 7.72386 13.6088 7.5 13.3327 7.5H4.67786C4.38089 7.5 4.23217 7.14095 4.44216 6.93096L7.01957 4.35355Z" />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
@ -31,4 +31,4 @@ const Icon = styled.svg`
&.red { &.red {
fill: ${({ theme }) => theme.redColor}; fill: ${({ theme }) => theme.redColor};
} }
`; `

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled, { keyframes } from "styled-components"; import styled, { keyframes } from 'styled-components'
const rotation = keyframes` const rotation = keyframes`
from { from {
@ -8,10 +8,10 @@ const rotation = keyframes`
to { to {
transform: rotate(360deg); transform: rotate(360deg);
} }
`; `
interface LoadingIconProps { interface LoadingIconProps {
className?: string; className?: string
} }
export const LoadingIcon = ({ className }: LoadingIconProps) => ( export const LoadingIcon = ({ className }: LoadingIconProps) => (
@ -28,7 +28,7 @@ export const LoadingIcon = ({ className }: LoadingIconProps) => (
d="M10.7682 5.07742C10.5667 4.18403 10.0777 3.37742 9.37244 2.77889C8.66702 2.18025 7.78327 1.8222 6.85295 1.7598C5.9226 1.69741 4.99749 1.93417 4.21597 2.43357C3.4346 2.93289 2.83935 3.66744 2.51731 4.52621C2.19533 5.38485 2.16318 6.32294 2.4255 7.20091C2.68785 8.07899 3.23118 8.85135 3.9762 9.40157C4.72137 9.95188 5.62791 10.25 6.56041 10.25L6.56041 11.75C5.30863 11.75 4.08949 11.3499 3.0851 10.6082C2.08057 9.86633 1.34435 8.82207 0.988276 7.63032C0.632173 6.43846 0.675924 5.16459 1.11282 3.99953C1.54966 2.8346 2.35554 1.84232 3.40827 1.16961C4.46086 0.496978 5.7044 0.179402 6.95332 0.263164C8.20227 0.346928 9.39145 0.827686 10.343 1.63521C11.2947 2.44286 11.9578 3.53431 12.2314 4.74738L10.7682 5.07742Z" d="M10.7682 5.07742C10.5667 4.18403 10.0777 3.37742 9.37244 2.77889C8.66702 2.18025 7.78327 1.8222 6.85295 1.7598C5.9226 1.69741 4.99749 1.93417 4.21597 2.43357C3.4346 2.93289 2.83935 3.66744 2.51731 4.52621C2.19533 5.38485 2.16318 6.32294 2.4255 7.20091C2.68785 8.07899 3.23118 8.85135 3.9762 9.40157C4.72137 9.95188 5.62791 10.25 6.56041 10.25L6.56041 11.75C5.30863 11.75 4.08949 11.3499 3.0851 10.6082C2.08057 9.86633 1.34435 8.82207 0.988276 7.63032C0.632173 6.43846 0.675924 5.16459 1.11282 3.99953C1.54966 2.8346 2.35554 1.84232 3.40827 1.16961C4.46086 0.496978 5.7044 0.179402 6.95332 0.263164C8.20227 0.346928 9.39145 0.827686 10.343 1.63521C11.2947 2.44286 11.9578 3.53431 12.2314 4.74738L10.7682 5.07742Z"
/> />
</Icon> </Icon>
); )
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
@ -41,4 +41,4 @@ const Icon = styled.svg`
fill: ${({ theme }) => theme.secondary}; fill: ${({ theme }) => theme.secondary};
} }
} }
`; `

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
export const LogoutIcon = () => { export const LogoutIcon = () => {
return ( return (
@ -13,9 +13,9 @@ export const LogoutIcon = () => {
<path d="M13.5371 6C16.1605 6 18.2871 8.12665 18.2871 10.75V12.75C18.2871 13.1642 17.9513 13.5 17.5371 13.5C17.1229 13.5 16.7871 13.1642 16.7871 12.75V10.75C16.7871 8.95507 15.332 7.5 13.5371 7.5L12.5372 7.5H11.7499L10.75 7.5C8.95507 7.5 7.5 8.95507 7.5 10.75V11.4999V12.75V18.75V19.4999V20.75C7.5 22.5449 8.95507 24 10.75 24H11.7499H12.5372H13.5371C15.332 24 16.7871 22.5449 16.7871 20.75V18.75C16.7871 18.3358 17.1229 18 17.5371 18C17.9513 18 18.2871 18.3358 18.2871 18.75V20.75C18.2871 23.3734 16.1605 25.5 13.5371 25.5H12.5372H11.7499H10.75C8.12665 25.5 6 23.3734 6 20.75V19.4999V18.75V12.75V11.4999V10.75C6 8.12665 8.12665 6 10.75 6H11.7499H12.5372H13.5371Z" /> <path d="M13.5371 6C16.1605 6 18.2871 8.12665 18.2871 10.75V12.75C18.2871 13.1642 17.9513 13.5 17.5371 13.5C17.1229 13.5 16.7871 13.1642 16.7871 12.75V10.75C16.7871 8.95507 15.332 7.5 13.5371 7.5L12.5372 7.5H11.7499L10.75 7.5C8.95507 7.5 7.5 8.95507 7.5 10.75V11.4999V12.75V18.75V19.4999V20.75C7.5 22.5449 8.95507 24 10.75 24H11.7499H12.5372H13.5371C15.332 24 16.7871 22.5449 16.7871 20.75V18.75C16.7871 18.3358 17.1229 18 17.5371 18C17.9513 18 18.2871 18.3358 18.2871 18.75V20.75C18.2871 23.3734 16.1605 25.5 13.5371 25.5H12.5372H11.7499H10.75C8.12665 25.5 6 23.3734 6 20.75V19.4999V18.75V12.75V11.4999V10.75C6 8.12665 8.12665 6 10.75 6H11.7499H12.5372H13.5371Z" />
<path d="M21.9822 16.75C22.4277 16.75 22.6508 17.2886 22.3358 17.6036L20.4697 19.4697C20.1768 19.7626 20.1768 20.2374 20.4697 20.5303C20.7626 20.8232 21.2374 20.8232 21.5303 20.5303L25.5303 16.5303C25.8232 16.2374 25.8232 15.7626 25.5303 15.4697L21.5303 11.4697C21.2374 11.1768 20.7626 11.1768 20.4697 11.4697C20.1768 11.7626 20.1768 12.2374 20.4697 12.5303L22.3358 14.3964C22.6508 14.7114 22.4277 15.25 21.9822 15.25L12 15.25C11.5858 15.25 11.25 15.5858 11.25 16C11.25 16.4142 11.5858 16.75 12 16.75L21.9822 16.75Z" /> <path d="M21.9822 16.75C22.4277 16.75 22.6508 17.2886 22.3358 17.6036L20.4697 19.4697C20.1768 19.7626 20.1768 20.2374 20.4697 20.5303C20.7626 20.8232 21.2374 20.8232 21.5303 20.5303L25.5303 16.5303C25.8232 16.2374 25.8232 15.7626 25.5303 15.4697L21.5303 11.4697C21.2374 11.1768 20.7626 11.1768 20.4697 11.4697C20.1768 11.7626 20.1768 12.2374 20.4697 12.5303L22.3358 14.3964C22.6508 14.7114 22.4277 15.25 21.9822 15.25L12 15.25C11.5858 15.25 11.25 15.5858 11.25 16C11.25 16.4142 11.5858 16.75 12 16.75L21.9822 16.75Z" />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

View File

@ -1,4 +1,4 @@
import React from "react"; import React from 'react'
export const MarkerdaoLogo = () => ( export const MarkerdaoLogo = () => (
<svg <svg
@ -30,4 +30,4 @@ export const MarkerdaoLogo = () => (
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>
); )

View File

@ -1,5 +1,5 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
export const MembersIcon = () => { export const MembersIcon = () => {
return ( return (
@ -16,11 +16,11 @@ export const MembersIcon = () => {
/> />
<path d="M9.14735 25.0368C9.53098 25.1327 9.91944 24.9141 10.0836 24.5543C11.1079 22.3099 13.3718 20.75 16 20.75C18.6684 20.75 20.9613 22.3579 21.9625 24.6577C22.1289 25.0398 22.5478 25.2663 22.9456 25.142C23.3386 25.0192 23.5622 24.6006 23.4061 24.2196C22.2119 21.3039 19.3458 19.25 16 19.25C12.704 19.25 9.8736 21.2432 8.64834 24.0901C8.47629 24.4898 8.72515 24.9313 9.14735 25.0368Z" /> <path d="M9.14735 25.0368C9.53098 25.1327 9.91944 24.9141 10.0836 24.5543C11.1079 22.3099 13.3718 20.75 16 20.75C18.6684 20.75 20.9613 22.3579 21.9625 24.6577C22.1289 25.0398 22.5478 25.2663 22.9456 25.142C23.3386 25.0192 23.5622 24.6006 23.4061 24.2196C22.2119 21.3039 19.3458 19.25 16 19.25C12.704 19.25 9.8736 21.2432 8.64834 24.0901C8.47629 24.4898 8.72515 24.9313 9.14735 25.0368Z" />
</Icon> </Icon>
); )
}; }
const Icon = styled.svg` const Icon = styled.svg`
& > path { & > path {
fill: ${({ theme }) => theme.primary}; fill: ${({ theme }) => theme.primary};
} }
`; `

View File

@ -1,11 +1,11 @@
import React from "react"; import React from 'react'
import styled from "styled-components"; import styled from 'styled-components'
type MembersSmallIconProps = { type MembersSmallIconProps = {
width: number; width: number
height: number; height: number
className?: string; className?: string
}; }
export function MembersSmallIcon({ export function MembersSmallIcon({
height, height,
@ -28,9 +28,9 @@ export function MembersSmallIcon({
/> />
<path d="M3.43173 14.5246C3.68748 14.5885 3.94646 14.4427 4.05591 14.2029C4.73877 12.7066 6.24803 11.6667 8.00019 11.6667C9.77912 11.6667 11.3077 12.7386 11.9752 14.2718C12.0861 14.5265 12.3654 14.6775 12.6306 14.5947C12.8925 14.5128 13.0416 14.2337 12.9376 13.9797C12.1414 12.0359 10.2307 10.6667 8.00019 10.6667C5.80286 10.6667 3.9159 11.9955 3.09905 13.8934C2.98436 14.1599 3.15026 14.4542 3.43173 14.5246Z" /> <path d="M3.43173 14.5246C3.68748 14.5885 3.94646 14.4427 4.05591 14.2029C4.73877 12.7066 6.24803 11.6667 8.00019 11.6667C9.77912 11.6667 11.3077 12.7386 11.9752 14.2718C12.0861 14.5265 12.3654 14.6775 12.6306 14.5947C12.8925 14.5128 13.0416 14.2337 12.9376 13.9797C12.1414 12.0359 10.2307 10.6667 8.00019 10.6667C5.80286 10.6667 3.9159 11.9955 3.09905 13.8934C2.98436 14.1599 3.15026 14.4542 3.43173 14.5246Z" />
</Icon> </Icon>
); )
} }
const Icon = styled.svg` const Icon = styled.svg`
fill: ${({ theme }) => theme.tertiary}; fill: ${({ theme }) => theme.tertiary};
`; `

Some files were not shown because too many files have changed in this diff Show More