Compare commits

...

43 Commits

Author SHA1 Message Date
AlphaX
747b555edb
Merge pull request #364 from AlphaX-Qortal/master
Fix copy to clipboard in iframe
2025-03-20 11:52:49 +01:00
AlphaX
36e7bd8ba6
Fix copy to clipboard in iframe 2025-03-20 11:51:59 +01:00
AlphaX
29965500fc
Update browser.src.js 2025-03-20 11:28:17 +01:00
AlphaX
75f923e025
Merge pull request #363 from AlphaX-Qortal/master
Update dependencies
2025-03-19 17:31:12 +01:00
AlphaX-Qortal
f12b0c9bf8 Update dependencies 2025-03-19 17:30:04 +01:00
AlphaX
0e3220eed0
Merge pull request #362 from AlphaX-Qortal/master
Update entitlements.mac.plist
2025-03-19 17:06:01 +01:00
AlphaX
f0a5eeebc8
Update entitlements.mac.plist 2025-03-19 17:02:57 +01:00
AlphaX
2ed1b08cd8
Merge pull request #361 from AlphaX-Qortal/master
Added qortal requests for wallet app
2025-03-19 09:24:23 +01:00
AlphaX-Qortal
e4eede5087 Fix response 2025-03-19 09:19:54 +01:00
AlphaX
9dbc4b085b
Fix typo 2025-03-18 19:19:00 +01:00
AlphaX-Qortal
7ca9acaf3a Added qortal requests 2025-03-18 17:20:46 +01:00
AlphaX-Qortal
e3ef24dc5e Fix parsing use-embed 2025-02-26 09:37:46 +01:00
AlphaX
9d72f4539d
Merge pull request #360 from AlphaX-Qortal/master
Fix typo and update dependencies
2025-02-25 11:52:51 +01:00
AlphaX-Qortal
060390da23 Update dependencies 2025-02-25 11:51:10 +01:00
AlphaX-Qortal
2547025d9e Fix typo 2025-02-25 10:24:18 +01:00
AlphaX
665d708563
Merge pull request #359 from AlphaX-Qortal/master
Fix sign tx json output
2025-02-18 18:06:48 +01:00
AlphaX-Qortal
c686a12c3a Fix sign tx json output 2025-02-18 18:05:57 +01:00
AlphaX
e2d6d83fd8
Merge pull request #358 from AlphaX-Qortal/master
Fixed view chat timestamp and reworked view chat dialog
2025-02-18 10:44:07 +01:00
AlphaX-Qortal
78f25607e2 Fixed view chat timestamp and reworked view chat dialog 2025-02-18 10:40:51 +01:00
AlphaX
502952550c
Merge pull request #357 from kennycud/master
Language Support for Level 0 Self Share Allowance
2025-02-15 10:26:48 +01:00
kennycud
7cae21d8ed
Merge branch 'Qortal:master' into master 2025-02-14 11:27:46 -08:00
AlphaX-Qortal
6e648ece9d Update dependencies 2025-02-14 16:52:58 +01:00
AlphaX
b74cd40cd3
Merge pull request #356 from AlphaX-Qortal/master
Fixes
2025-02-14 16:19:45 +01:00
AlphaX-Qortal
d7708259de Fixes
- Fixed reply to encrypted messages
- Fixed show replied encrypted messages
- Fixed edit encrypted messages
- Added MINTER group logo
2025-02-14 16:17:23 +01:00
AlphaX-Qortal
3837973ba8 Bump version 4.6.1 2025-02-13 17:58:44 +01:00
AlphaX
af8dcae748
Merge pull request #355 from AlphaX-Qortal/master
Various updates
2025-02-13 17:24:28 +01:00
AlphaX-Qortal
8b64c80019 Various updates
- Added level 0 can create selfshare
- Added Q-Mintership to default Q-Apps
- Changed chat lock icons
- Fixed encryption icon in PM
2025-02-13 17:23:15 +01:00
kennycud
1ded359b7a
Merge branch 'Qortal:master' into master 2025-02-13 08:15:02 -08:00
AlphaX
2e3a02458d
Merge pull request #354 from AlphaX-Qortal/master
Remove preview chat
2025-02-13 10:39:33 +01:00
AlphaX-Qortal
8b8ad3015f Remove preview chat 2025-02-13 10:37:15 +01:00
AlphaX
d16781e73b
Merge pull request #353 from AlphaX-Qortal/master
Change protocol check in trade portal and auto buy
2025-02-13 08:39:40 +01:00
AlphaX-Qortal
d6e0846d58 Change protocol check in trade portal and auto buy 2025-02-13 08:38:14 +01:00
AlphaX
003eb5c45a
Merge pull request #352 from AlphaX-Qortal/master
Change protocol check
2025-02-12 22:27:52 +01:00
AlphaX-Qortal
f7971f7026 Change protocol check 2025-02-12 22:26:49 +01:00
AlphaX
d3f9e0878b
Merge pull request #351 from AlphaX-Qortal/master
Fix message decoding
2025-02-12 21:34:23 +01:00
AlphaX-Qortal
585d133143 Fix message decoding 2025-02-12 21:33:36 +01:00
AlphaX
4457215a0e
Merge pull request #350 from AlphaX-Qortal/master
Various updates
2025-02-11 20:31:31 +01:00
AlphaX-Qortal
d915b25b47 Various updates
- Add display private messages from Qortal-Hub
- Re-add accidentally deleted qortal request SAVE_FILE
- Reworked decoding Qortal-Hub messages
- Update languages files
2025-02-11 20:29:22 +01:00
kennycud
80d4ce82f1
Merge branch 'Qortal:master' into master 2025-02-07 04:58:39 -08:00
kennycud
6ad91d6934
Merge branch 'Qortal:master' into master 2025-02-04 10:32:02 -08:00
kennycud
4fa85d4923
Merge branch 'Qortal:master' into master 2025-01-30 13:33:18 -08:00
kennycud
eade77c98b language update for dropped minimum level 1 constraint for reward share to self, self share 2025-01-12 16:26:06 -08:00
kennycud
79e9080f6e dropped minimum level 1 constraint for reward share to self 2025-01-12 14:13:44 -08:00
53 changed files with 1563 additions and 2321 deletions

View File

@ -26,8 +26,8 @@ Easiest way to install the lastest required packages on Linux is via nvm.
``` source ~/.profile ``` (For Debian based distro) <br/>
``` source ~/.bashrc ``` (For Fedora / CentOS) <br/>
``` nvm ls-remote ``` (Fetch list of available versions) <br/>
``` nvm install v20.18.1 ``` (Latest LTS: Iron supported by Electron V34) <br/>
``` npm --location=global install npm@11.1.0 ``` <br/>
``` nvm install v20.16.0 ``` (Latest LTS: Iron supported by Electron V32) <br/>
``` npm --location=global install npm@10.9.2 ``` <br/>
Adding via binary package mirror will only work if you have set the package path. You can do a node or java build via ports instead by downloading ports with portsnap fetch method.

View File

@ -2,7 +2,23 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.device.bluetooth</key>
<true/>
</dict>
</plist>

View File

@ -468,7 +468,7 @@
"rchange6": "Empfänger",
"rchange7": "Aktion",
"rchange8": "Typ",
"rchange9": "Die Stufen 14 können nur Self-Share-(Minting-)Schlüssel erstellen. Nur Level 5 oder höher kann einen Prämienanteil erstellen!",
"rchange9": "Die Stufen 04 können nur Self-Share-(Minting-)Schlüssel erstellen. Nur Level 5 oder höher kann einen Prämienanteil erstellen!",
"rchange10": "Öffentlicher Schlüssel des Empfängers",
"rchange11": "Belohnungsanteil in Prozent",
"rchange12": "Angeforderter Befehl wird ausgeführt...",
@ -1417,6 +1417,7 @@
"mpchange83": "ABGELEHNT",
"mpchange84": "FEHLER",
"mpchange85": "ERFOLGREICH",
"mpchange86": "Immer automatisches Abrufen des Wallet-Guthabens zulassen"
"mpchange86": "Immer automatisches Abrufen des Wallet-Guthabens zulassen",
"mpchange87": "Bitte geben Sie die Gruppen-ID ein"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Receptor",
"rchange7": "Acción",
"rchange8": "Tipo",
"rchange9": "Los niveles 1 a 4 solo pueden crear claves Self-Share (acuñación). ¡Solo el nivel 5 o superior puede crear una recompensa compartida!",
"rchange9": "Los niveles 0 a 4 solo pueden crear claves Self-Share (acuñación). ¡Solo el nivel 5 o superior puede crear una recompensa compartida!",
"rchange10": "Clave pública del receptor",
"rchange11": "Porcentaje de Reward share",
"rchange12": "Ejecutando el comando solicitado",
@ -1417,6 +1417,7 @@
"mpchange83": "RECHAZADO",
"mpchange84": "ERROR",
"mpchange85": "ÉXITO",
"mpchange86": "Permitir siempre obtener el saldo de la billetera automáticamente"
"mpchange86": "Permitir siempre obtener el saldo de la billetera automáticamente",
"mpchange87": "Por favor, introduzca el ID del grupo"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Saaja",
"rchange7": "Tegevus",
"rchange8": "Tüüp",
"rchange9": "Tase 1 - 4 saab luua iseseiseva jagamise. Tase 5 või kõrgem saab luua Preemiajagamise!",
"rchange9": "Tase 0 - 4 saab luua iseseiseva jagamise. Tase 5 või kõrgem saab luua Preemiajagamise!",
"rchange10": "Saaja avalik võti",
"rchange11": "Preemiajagamise protsent",
"rchange12": "Teeb midagi maitsvat",
@ -1417,6 +1417,7 @@
"mpchange83": "DECLINED",
"mpchange84": "FAILURE",
"mpchange85": "EDU",
"mpchange86": "Luba alati rahakoti saldo automaatne hankimine"
"mpchange86": "Luba alati rahakoti saldo automaatne hankimine",
"mpchange87": "Palun sisestage grupi ID"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Vastaanottaja",
"rchange7": "Toiminta",
"rchange8": "Tyyppi",
"rchange9": "Tasot 1 - 4 voivat luoda erillisen jaon. Taso 5 tai korkeampi voi luoda palkintoosuuden!",
"rchange9": "Tasot 0 - 4 voivat luoda erillisen jaon. Taso 5 tai korkeampi voi luoda palkintoosuuden!",
"rchange10": "Vastaanottajan julkinen avain",
"rchange11": "Palkintojen jakoprosentti",
"rchange12": "Tekee jotain herkullista",
@ -1417,6 +1417,7 @@
"mpchange83": "hylätty",
"mpchange84": "FAILURE",
"mpchange85": "SUCCESS",
"mpchange86": "Salli aina saada lompakon saldo automaattisesti"
"mpchange86": "Salli aina saada lompakon saldo automaattisesti",
"mpchange87": "Anna ryhmän tunnus"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Destinataire",
"rchange7": "Action",
"rchange8": "Type",
"rchange9": "Niveau 1 - 4 peuvent créer un autopartage et niveau 5 et supérieur peuvent créer un partage de récompense!",
"rchange9": "Niveau 0 - 4 peuvent créer un autopartage et niveau 5 et supérieur peuvent créer un partage de récompense!",
"rchange10": "Clé publique du bénéficiaire",
"rchange11": "Pourcentage du partage de récompense",
"rchange12": "Faire quelque chose de délicieux",
@ -1417,6 +1417,7 @@
"mpchange83": "REFUSÉ",
"mpchange84": "ÉCHEC",
"mpchange85": "SUCCÈS",
"mpchange86": "Toujours autoriser l'obtention automatique du solde du portefeuille"
"mpchange86": "Toujours autoriser l'obtention automatique du solde du portefeuille",
"mpchange87": "Veuillez saisir l'ID du groupe"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "प्राप्तकर्ता",
"rchange7": "कार्रवाई",
"rchange8": "टाइप",
"rchange9": "लेवल 1 - 4 एक सेल्फ शेयर बना सकता है और लेवल 5 या उससे ऊपर एक रिवॉर्ड शेयर बना सकता है!",
"rchange9": "लेवल 0 - 4 एक सेल्फ शेयर बना सकता है और लेवल 5 या उससे ऊपर एक रिवॉर्ड शेयर बना सकता है!",
"rchange10": "प्राप्तकर्ता सार्वजनिक कुंजी",
"rchange11": "रिवॉर्ड शेयर प्रतिशत",
"rchange12": "कुछ स्वादिष्ट करना",
@ -1417,6 +1417,7 @@
"mpchange83": "अस्वीकृत",
"mpchange84": "विफल",
"mpchange85": "सफल",
"mpchange86": "हमेशा वॉलेट बैलेंस को स्वचालित रूप से प्राप्त करने की अनुमति दें"
"mpchange86": "हमेशा वॉलेट बैलेंस को स्वचालित रूप से प्राप्त करने की अनुमति दें",
"mpchange87": "कृपया ग्रुप आईडी दर्ज करें"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Primatelj",
"rchange7": "Akcija",
"rchange8": "Vrsta",
"rchange9": "Level 1 - 4 može stvoriti samo vlastiti udio a level 5 ili više može stvoriti nagradni udio!",
"rchange9": "Level 0 - 4 može stvoriti samo vlastiti udio a level 5 ili više može stvoriti nagradni udio!",
"rchange10": "Primateljov javni ključ",
"rchange11": "Nagradni udio postotak",
"rchange12": "Radiš nešto ukusno :-)",
@ -1417,6 +1417,7 @@
"mpchange83": "ODBIJENO",
"mpchange84": "GREŠKA",
"mpchange85": "USPJEH",
"mpchange86": "Uvijek dopusti automatsko dobivanje stanja novčanika"
"mpchange86": "Uvijek dopusti automatsko dobivanje stanja novčanika",
"mpchange87": "Molimo unesite ID grupe"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Címzett",
"rchange7": "Akció",
"rchange8": "Típus",
"rchange9": "Az 1- 4. szint létrehozhat egy önmegosztást, és az 5. vagy annál magasabb szint jutalommegosztást hozhat létre!",
"rchange9": "Az 0- 4. szint létrehozhat egy önmegosztást, és az 5. vagy annál magasabb szint jutalommegosztást hozhat létre!",
"rchange10": "Címzett Nyilvános Kulcsa",
"rchange11": "Jutalomrészesedési Százalék",
"rchange12": "Valami Finomat Csinálni",
@ -1417,6 +1417,7 @@
"mpchange83": "Elutasítva",
"mpchange84": "FAILURE",
"mpchange85": "SIKER",
"mpchange86": "Mindig engedélyezze a pénztárcaegyenleg automatikus lekérését"
"mpchange86": "Mindig engedélyezze a pénztárcaegyenleg automatikus lekérését",
"mpchange87": "Kérjük, adja meg a csoport azonosítóját"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Destinatario",
"rchange7": "Azione",
"rchange8": "Tipo",
"rchange9": "Level 1 - 4 can create a Self Share and Level 5 or above can create a Reward Share!",
"rchange9": "Level 0 - 4 can create a Self Share and Level 5 or above can create a Reward Share!",
"rchange10": "Chiave pubblica del destinatario",
"rchange11": "Percentuale di quota premio",
"rchange12": "Fare qualcosa di delizioso",
@ -1417,6 +1417,7 @@
"mpchange83": "RIFIUTATO",
"mpchange84": "FALLITO",
"mpchange85": "RIUSCITO",
"mpchange86": "Consenti sempre di ottenere automaticamente il saldo del portafoglio"
"mpchange86": "Consenti sempre di ottenere automaticamente il saldo del portafoglio",
"mpchange87": "Inserisci l'ID del gruppo"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "受取人",
"rchange7": "アクション",
"rchange8": "タイプ",
"rchange9": "レベル 1 4 は自己シェアを、レベル 5 以上は報酬シェアを作成出来ます!",
"rchange9": "レベル 0 4 は自己シェアを、レベル 5 以上は報酬シェアを作成出来ます!",
"rchange10": "受取人の公開鍵",
"rchange11": "報酬シェア率",
"rchange12": "おいしいことをしています",
@ -1417,6 +1417,7 @@
"mpchange83": "拒否されました",
"mpchange84": "失敗",
"mpchange85": "成功",
"mpchange86": "ウォレット残高の自動取得を常に許可する"
"mpchange86": "ウォレット残高の自動取得を常に許可する",
"mpchange87": "グループ ID を入力してください"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "받는사람",
"rchange7": "액션",
"rchange8": "유형",
"rchange9": "레벨 1 - 4는 자체 공유를 생성할 수 있으며 레벨 5 이상은 보상 공유를 생성할 수 있습니다.",
"rchange9": "레벨 0 - 4는 자체 공유를 생성할 수 있으며 레벨 5 이상은 보상 공유를 생성할 수 있습니다.",
"rchange10": "수신자 공개 키",
"rchange11": "보상공유율",
"rchange12": "맛있는 거 하기",
@ -1417,6 +1417,7 @@
"mpchange83": "거부됨",
"mpchange84": "실패",
"mpchange85": "성공",
"mpchange86": "항상 지갑 잔액을 자동으로 가져오도록 허용"
"mpchange86": "항상 지갑 잔액을 자동으로 가져오도록 허용",
"mpchange87": "그룹 ID를 입력하세요"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Ontvanger",
"rchange7": "Actie",
"rchange8": "Type",
"rchange9": "Level 1 - 4 kunnen een zelf-beloning aanmaken en Level 5 en hoger kunnen een belonings-deel toekennen!",
"rchange9": "Level 0 - 4 kunnen een zelf-beloning aanmaken en Level 5 en hoger kunnen een belonings-deel toekennen!",
"rchange10": "Publieke sleutel van de ontvanger",
"rchange11": "Belonings-deel in procent",
"rchange12": "Doe iets heerlijk",
@ -1417,6 +1417,7 @@
"mpchange83": "GEWEIGERD",
"mpchange84": "MISLUKT",
"mpchange85": "SUCCES",
"mpchange86": "Altijd toestaan om automatisch saldo in portemonnee op te halen"
"mpchange86": "Altijd toestaan om automatisch saldo in portemonnee op te halen",
"mpchange87": "Voer de groeps-ID in"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Mottaker",
"rchange7": "Handling",
"rchange8": "Type",
"rchange9": "Nivå 1 - 4 kan opprette en selvdel og nivå 5 eller høyere kan opprette en belønningsdel!",
"rchange9": "Nivå 0 - 4 kan opprette en selvdel og nivå 5 eller høyere kan opprette en belønningsdel!",
"rchange10": "Mottaker offentlig nøkkel",
"rchange11": "Belønningsdel prosent",
"rchange12": "Gjøre noe nydelig",
@ -1417,6 +1417,7 @@
"mpchange83": "AVSLAGT",
"mpchange84": "FEIL",
"mpchange85": "SUKSESS",
"mpchange86": "Tillat alltid få lommeboksaldo automatisk"
"mpchange86": "Tillat alltid få lommeboksaldo automatisk",
"mpchange87": "Vennligst skriv inn gruppe-ID"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Odbiorca",
"rchange7": "Akcja",
"rchange8": "Typ",
"rchange9": "Poziomy 1 - 4 mogą tworzyć Self Share, a poziom 5 lub wyższy może tworzyć Reward Share!",
"rchange9": "Poziomy 0 - 4 mogą tworzyć Self Share, a poziom 5 lub wyższy może tworzyć Reward Share!",
"rchange10": "Publiczny klucz odbiorcy",
"rchange11": "Procent udziału w nagrodzie",
"rchange12": "Robimy coś pysznego",
@ -1417,6 +1417,7 @@
"mpchange83": "ODRZUCONE",
"mpchange84": "NIEPOWODZENIE",
"mpchange85": "POWODZENIE",
"mpchange86": "Zawsze zezwalaj na automatyczne pobieranie salda portfela"
"mpchange86": "Zawsze zezwalaj na automatyczne pobieranie salda portfela",
"mpchange87": "Wprowadź identyfikator grupy"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Recipiente",
"rchange7": "Ação",
"rchange8": "Tipo",
"rchange9": "Nível 1 - 4 podem criar Auto Ações e nível 5 ou superior podem criar Ações de Recompensa!",
"rchange9": "Nível 0 - 4 podem criar Auto Ações e nível 5 ou superior podem criar Ações de Recompensa!",
"rchange10": "Chave Pública do Destinatário",
"rchange11": "Porcentagem das ações de recompensa",
"rchange12": "Fazendo algo delicioso",
@ -1417,6 +1417,7 @@
"mpchange83": "RECLINADO",
"mpchange84": "FALHA",
"mpchange85": "SUCESSO",
"mpchange86": "Permitir sempre obter saldo da carteira automaticamente"
"mpchange86": "Permitir sempre obter saldo da carteira automaticamente",
"mpchange87": "Por favor introduza o ID do grupo"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Destinatar",
"rchange7": "Actiune",
"rchange8": "Tip",
"rchange9": "Nivelurile 1 - 4 pot crea un cota personala de recompensare, iar nivelul 5 sau mai sus pot crea o Cota de Recompensare!",
"rchange9": "Nivelurile 0 - 4 pot crea un cota personala de recompensare, iar nivelul 5 sau mai sus pot crea o Cota de Recompensare!",
"rchange10": "Cheia publica a destinatarului",
"rchange11": "Procentul cotei de recompensa",
"rchange12": "Se produce ceva delicios",
@ -1417,6 +1417,7 @@
"mpchange83": "RESFUS",
"mpchange84": "Eșec",
"mpchange85": "SUCCES",
"mpchange86": "Permiteți întotdeauna obținerea automată a soldului portofelului"
"mpchange86": "Permiteți întotdeauna obținerea automată a soldului portofelului",
"mpchange87": "Vă rugăm să introduceți ID-ul grupului"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Primalac",
"rchange7": "Akcija",
"rchange8": "Tip",
"rchange9": "Nivoi 1 - 4 mogu napraviti samostalni udeo a nivoi 5 i više mogu napraviti udeo u nagradi!",
"rchange9": "Nivoi 0 - 4 mogu napraviti samostalni udeo a nivoi 5 i više mogu napraviti udeo u nagradi!",
"rchange10": "Primalac Javnog Ključa",
"rchange11": "Procenat Udela u Nagradi",
"rchange12": "Rađenje nečeg slasnog",
@ -1417,6 +1417,7 @@
"mpchange83": "ODBIJENO",
"mpchange84": "GREŠKA",
"mpchange85": "USPEH",
"mpchange86": "Uvek dozvoli automatsko dobijanje stanja novčanika"
"mpchange86": "Uvek dozvoli automatsko dobijanje stanja novčanika",
"mpchange87": "Unesite ID grupe"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Получатель",
"rchange7": "Действие",
"rchange8": "Тип",
"rchange9": "Уровень 14 может создать акцию для самого себя, а уровень 5 или выше может создать акцию для других!",
"rchange9": "Уровень 04 может создать акцию для самого себя, а уровень 5 или выше может создать акцию для других!",
"rchange10": "Открытый ключ получателя",
"rchange11": "Процент доли вознаграждения",
"rchange12": "Делаю что-нибудь вкусненькое",
@ -1417,6 +1417,7 @@
"mpchange83": "ОТКЛОНЕНО",
"mpchange84": "НЕУДАЧА",
"mpchange85": "УСПЕШНО",
"mpchange86": "Всегда разрешать автоматически получать баланс кошелька"
"mpchange86": "Всегда разрешать автоматически получать баланс кошелька",
"mpchange87": "Пожалуйста, введите идентификатор группы"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "Recipient",
"rchange7": "Action",
"rchange8": "Type",
"rchange9": "Levels 1 - 4 can only create a Self-Share (minting) keys. Only Level 5 or above can create a Reward Share!",
"rchange9": "Levels 0 - 4 can only create a Self-Share (minting) keys. Only Level 5 or above can create a Reward Share!",
"rchange10": "Recipient's Public Key",
"rchange11": "Reward Share percentage",
"rchange12": "Executing Requested Command...",
@ -1417,6 +1417,7 @@
"mpchange83": "DECLINED",
"mpchange84": "FAILURE",
"mpchange85": "SUCCESS",
"mpchange86": "Always allow get wallet balance automatically"
"mpchange86": "Always allow get wallet balance automatically",
"mpchange87": "Please Enter The Group ID"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "接收者",
"rchange7": "操作",
"rchange8": "类型",
"rchange9": "等级1-4只能创建个人铸币密钥等级5或以上可以创建赞助码!",
"rchange9": "等级0-4只能创建个人铸币密钥等级5或以上可以创建赞助码!",
"rchange10": "接收者的公共密钥",
"rchange11": "奖励分享百分比",
"rchange12": "正在添加中...",
@ -1417,6 +1417,7 @@
"mpchange83": "拒绝",
"mpchange84": "失败",
"mpchange85": "成功",
"mpchange86": "始终允许自动获取钱包余额"
"mpchange86": "始终允许自动获取钱包余额",
"mpchange87": "请输入群组ID"
}
}

View File

@ -468,7 +468,7 @@
"rchange6": "接收者",
"rchange7": "操作",
"rchange8": "類型",
"rchange9": "等級1-4只能創建個人鑄幣密鑰等級5或以上可以創建贊助碼!",
"rchange9": "等級0-4只能創建個人鑄幣密鑰等級5或以上可以創建贊助碼!",
"rchange10": "接收者的公共密鑰",
"rchange11": "獎勵分享百分比",
"rchange12": "正在添加中...",
@ -1417,6 +1417,7 @@
"mpchange83": "拒絕",
"mpchange84": "失敗",
"mpchange85": "成功",
"mpchange86": "隨時允許自動取得錢包餘額"
"mpchange86": "隨時允許自動取得錢包餘額",
"mpchange87": "請輸入群組 ID"
}
}

View File

@ -20,7 +20,9 @@ import {
setSideEffectAction,
setTabNotifications,
allowQAPPAutoBalance,
removeQAPPAutoBalance
removeQAPPAutoBalance,
allowQAPPAutoTransactions,
removeQAPPAutoTransactions
} from '../../redux/app/app-actions'
import settings from '../../functional-components/settings-page'
import './welcome-page'
@ -56,7 +58,9 @@ window.reduxAction = {
allowShowSyncIndicator: allowShowSyncIndicator,
removeShowSyncIndicator: removeShowSyncIndicator,
allowQAPPAutoBalance: allowQAPPAutoBalance,
removeQAPPAutoBalance: removeQAPPAutoBalance
removeQAPPAutoBalance: removeQAPPAutoBalance,
allowQAPPAutoTransactions: allowQAPPAutoTransactions,
removeQAPPAutoTransactions: removeQAPPAutoTransactions
}
const animationDuration = 0.7 // Seconds

View File

@ -10,7 +10,9 @@ import {
removeQAPPAutoLists,
setIsOpenDevDialog,
allowQAPPAutoBalance,
removeQAPPAutoBalance
removeQAPPAutoBalance,
allowQAPPAutoTransactions,
removeQAPPAutoTransactions
} from '../../redux/app/app-actions'
import { securityViewStyles } from '../../styles/core-css'
import FileSaver from 'file-saver'
@ -87,6 +89,12 @@ class SecurityView extends connect(store)(LitElement) {
</label>
<mwc-checkbox style="margin-right: -15px;" id="balanceButton" @click=${(e) => this.checkForBalance(e)} ?checked=${store.getState().app.qAPPAutoBalance}></mwc-checkbox>
</div>
<div class="checkbox-row">
<label for="transactionsButton" id="transactionsButtonLabel" style="color: var(--black);">
Always allow wallet txs to be retrieved automatically
</label>
<mwc-checkbox style="margin-right: -15px;" id="transactionsButton" @click=${(e) => this.checkForTransactions(e)} ?checked=${store.getState().app.qAPPAutoTransactions}></mwc-checkbox>
</div>
<div class="checkbox-row">
<label for="authButton" id="authButtonLabel" style="color: var(--black);">
${get('browserpage.bchange39')}
@ -124,6 +132,14 @@ class SecurityView extends connect(store)(LitElement) {
}
}
checkForTransactions(e) {
if (e.target.checked) {
store.dispatch(removeQAPPAutoTransactions(false))
} else {
store.dispatch(allowQAPPAutoTransactions(true))
}
}
checkForLists(e) {
if (e.target.checked) {
store.dispatch(removeQAPPAutoLists(false))

View File

@ -86,5 +86,16 @@ export const defaultQappsTabs = [
"pluginNumber": "plugin-GGHiHzW6pe",
"menus": [],
"parent": false
},
{
"url": "myapp",
"domain": "core",
"page": "qdn/browser/index.html?name=Q-Mintership&service=APP",
"title": "Q-Mintership",
"icon": "vaadin:external-browser",
"mwcicon": "apps",
"pluginNumber": "plugin-GGJJPqW6pe",
"menus": [],
"parent": false
}
]

View File

@ -26,7 +26,9 @@ import {
ALLOW_SHOW_SYNC_INDICATOR,
REMOVE_SHOW_SYNC_INDICATOR,
ALLOW_QAPP_AUTO_BALANCE,
REMOVE_QAPP_AUTO_BALANCE
REMOVE_QAPP_AUTO_BALANCE,
ALLOW_QAPP_AUTO_TRANSACTIONS,
REMOVE_QAPP_AUTO_TRANSACTIONS
} from '../app-action-types'
export const doUpdateBlockInfo = (blockObj) => {
@ -136,6 +138,20 @@ export const removeQAPPAutoBalance = (payload) => {
}
}
export const allowQAPPAutoTransactions = (payload) => {
return {
type: ALLOW_QAPP_AUTO_TRANSACTIONS,
payload
}
}
export const removeQAPPAutoTransactions = (payload) => {
return {
type: REMOVE_QAPP_AUTO_TRANSACTIONS,
payload
}
}
export const allowQAPPAutoLists = (payload) => {
return {
type: ALLOW_QAPP_AUTO_LISTS,

View File

@ -41,3 +41,5 @@ export const ALLOW_SHOW_SYNC_INDICATOR = 'ALLOW_SHOW_SYNC_INDICATOR'
export const REMOVE_SHOW_SYNC_INDICATOR = 'REMOVE_SHOW_SYNC_INDICATOR'
export const ALLOW_QAPP_AUTO_BALANCE = 'ALLOW_QAPP_AUTO_BALANCE'
export const REMOVE_QAPP_AUTO_BALANCE = 'REMOVE_QAPP_AUTO_BALANCE'
export const ALLOW_QAPP_AUTO_TRANSACTIONS = 'ALLOW_QAPP_AUTO_TRANSACTIONS'
export const REMOVE_QAPP_AUTO_TRANSACTIONS = 'REMOVE_QAPP_AUTO_TRANSACTIONS'

View File

@ -42,7 +42,9 @@ import {
ALLOW_SHOW_SYNC_INDICATOR,
REMOVE_SHOW_SYNC_INDICATOR,
ALLOW_QAPP_AUTO_BALANCE,
REMOVE_QAPP_AUTO_BALANCE
REMOVE_QAPP_AUTO_BALANCE,
ALLOW_QAPP_AUTO_TRANSACTIONS,
REMOVE_QAPP_AUTO_TRANSACTIONS
} from './app-action-types'
import { initWorkersReducer } from './reducers/init-workers'
import { loginReducer } from './reducers/login-reducer'
@ -92,6 +94,7 @@ const INITIAL_STATE = {
qAPPFriendsList: loadStateFromLocalStorage('qAPPFriendsList') || false,
showSyncIndicator: loadStateFromLocalStorage('showSyncIndicator') || false,
qAPPAutoBalance: loadStateFromLocalStorage('qAPPAutoBalance') || false,
qAPPAutoTransactions: loadStateFromLocalStorage('qAPPAutoTransactions') || false,
chatLastSeen: [],
newTab: null,
tabInfo: {},
@ -270,6 +273,22 @@ export default (state = INITIAL_STATE, action) => {
}
}
case ALLOW_QAPP_AUTO_TRANSACTIONS: {
saveStateToLocalStorage("qAPPAutoTransactions", true)
return {
...state,
qAPPAutoTransactions: action.payload
}
}
case REMOVE_QAPP_AUTO_TRANSACTIONS: {
saveStateToLocalStorage("qAPPAutoTransactions", false)
return {
...state,
qAPPAutoTransactions: action.payload
}
}
case ALLOW_QAPP_AUTO_LISTS: {
saveStateToLocalStorage("qAPPAutoLists", true)
return {

View File

@ -14,6 +14,15 @@ import {
const Base64Message = {}
Base64Message.decode = function (string, keys, ref) {
let repliedToStr = ''
let hubSpecialId = ''
let hubMessageStr = ''
let newMessageObject = ''
let reactionStr = ''
let messageUseEmbed = {}
let editStr = false
let embedFileStr = '"images":[""]'
const binaryString = atob(string)
const binaryLength = binaryString.length
const bytes = new Uint8Array(binaryLength)
@ -34,88 +43,49 @@ Base64Message.decode = function (string, keys, ref) {
return decodedString
}
} else {
let repliedToStr = ''
let addedFileStr = ''
let messageStr = ''
let hubString = ''
let messageRep = ''
let messageUseEmbed = {}
const res = decryptSingle(string, keys, false)
if (res === 'noKey' || res === 'decryptionFailed') {
return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]}' + addedFileStr + ',"repliedTo":"","version":3,"isFromHub":true}'
return '{"specialId":"","message":"<p>This message could not be decrypted</p>","repliedTo":"","isEdited":false,"isFromHub":true,"version": 3}'
}
const decryptToUnit8Array = base64ToUint8Array(res)
const responseData = uint8ArrayToObject(decryptToUnit8Array)
if (responseData.type === "notification") {
const messageStrRaw = responseData.data.message
messageStr = messageStrRaw.trim()
}
if (ref !== "noref") {
if (responseData.type === "reaction") {
repliedToStr = ref
messageStr = responseData.content
}
}
if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) {
if (responseData.message.includes('qortal://use-embed/')) {
const useEmbed1 = extensionToPointer(responseData.message)
const useEmbed2 = /<newpointer>(.*?)<\/newpointer>/g.exec(useEmbed1)
const useEmbed3 = encodedToChar(useEmbed2[1])
messageUseEmbed = parseQortalLink(useEmbed3)
addedFileStr = embedToString(messageUseEmbed)
const useEmbed4 = responseData.message.split(useEmbed2[1]).join('')
if (useEmbed4 === "<p></p>") {
messageRep = useEmbed4.split('<p></p>').join('<p>Qortal-Hub embed link</p>')
} else {
messageRep = useEmbed4
}
} else {
messageRep = responseData.message
addedFileStr = ',"images":[""]'
}
const messageRep1 = messageRep.split('"').join('<upvote>')
const messageRep2 = messageRep1.split('</p><p></p><p></p><p></p><p>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep3 = messageRep2.split('</p><p></p><p></p><p>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep4 = messageRep3.split('</p><p></p><p>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep5 = messageRep4.replace('</p><p>', '')
const messageRep6 = messageRep5.replace('<p></p>', '')
const messageRep7 = messageRep6.replace('<p>', '')
const messageRep8 = messageRep7.replace('<br></p>', '')
const messageRep9 = messageRep8.replace('</p>', '')
const messageRep10 = messageRep9.trim()
const messageRep11 = messageRep10.split('<br><br><br><br>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep12 = messageRep11.split('<br><br><br>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep13 = messageRep12.split('<br><br>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep14 = messageRep13.split('<br>').join('"},{"type":"hardBreak"},{"type":"text","text":"')
messageStr = messageRep14
if (responseData.type === "edit") {
editStr = true
}
if (responseData.repliedTo) {
repliedToStr = responseData.repliedTo
}
if (responseData.type === "edit") {
hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true,"isFromHub":true}'
} else if (responseData.type === "reaction") {
hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true,"isFromHub":true}'
} else {
hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isFromHub":true}'
if (responseData.specialId) {
hubSpecialId = responseData.specialId
}
const preparedString = hubString.split('<upvote>').join('\\"')
const finalString = preparedString.replace(/<\/?[^>]+(>|$)/g, '')
if (responseData.type === "notification") {
hubMessageStr = responseData.data.message
} else if (ref !== "noref" && responseData.type === "reaction") {
reactionStr = '"isReaction":true,'
repliedToStr = ref
hubMessageStr = responseData.content
} else if (responseData.message.includes('qortal://use-embed/')) {
const useEmbed1 = extensionToPointer(responseData.message)
const useEmbed2 = /<newpointer>(.*?)<\/newpointer>/g.exec(useEmbed1)
const useEmbed3 = encodedToChar(useEmbed2[1])
messageUseEmbed = parseQortalLink(useEmbed3)
embedFileStr = embedToString(messageUseEmbed)
hubMessageStr = responseData.message.split(useEmbed2[1]).join('')
} else {
hubMessageStr = responseData.message
}
return finalString
const hubMessageFinal = hubMessageStr.split('"').join('&quot;')
newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageFinal + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,' + reactionStr + '"version": 3}'
return newMessageObject
}
}

View File

@ -50,5 +50,13 @@ export const decryptChatMessageBase64 = (encryptedMessage, privateKey, recipient
return _decryptedMessage
}
let decrypted1 = new TextDecoder('utf-8').decode(_decryptedMessage)
if (decrypted1.includes('messageText')) {
let decrypted2 = JSON.parse(decrypted1)
let decrypted3 = Object.assign(decrypted2, {isPrivate: true})
return JSON.stringify(decrypted3)
}
return new TextDecoder('utf-8').decode(_decryptedMessage)
}

View File

@ -38,16 +38,16 @@ crashReporter.start({
})
if (myMemory > 16000000000) {
app.commandLine.appendSwitch('js-flags', '--max-executable-size=192', '--max-old-space-size=8192', '--max-semi-space-size=2')
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=8192')
log.info("Memory Size Is 16GB Using JS Memory Heap Size 8GB")
} else if (myMemory > 12000000000) {
app.commandLine.appendSwitch('js-flags', '--max-executable-size=192', '--max-old-space-size=6144', '--max-semi-space-size=2')
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=6144')
log.info("Memory Size Is 12GB Using JS Memory Heap Size 6GB")
} else if (myMemory > 7000000000) {
app.commandLine.appendSwitch('js-flags', '--max-executable-size=192', '--max-old-space-size=4096', '--max-semi-space-size=2')
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=4096')
log.info("Memory Size Is 8GB Using JS Memory Heap Size 4GB")
} else {
app.commandLine.appendSwitch('js-flags', '--max-executable-size=192', '--max-old-space-size=2048', '--max-semi-space-size=2')
app.commandLine.appendSwitch('js-flags', '--max-old-space-size=2048')
log.info("Memory Size Is 4GB Using JS Memory Heap Size 2GB")
}
@ -69,8 +69,6 @@ if (process.arch === 'arm') {
} else {
app.commandLine.appendSwitch('enable-experimental-web-platform-features')
app.commandLine.appendSwitch('disable-renderer-backgrounding')
app.commandLine.appendSwitch('disable-http-cache')
app.commandLine.appendSwitch('disable-software-rasterizer')
app.commandLine.appendSwitch('in-process-gpu')
log.info('We are on 64bit. Hardware Acceleration is enabled !')
}

BIN
img/minter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

673
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "qortal-ui",
"version": "4.6.0",
"version": "4.6.1",
"description": "Qortal Project - decentralize the world - Data storage, communications, web hosting, decentralized trading, complete infrastructure for the future blockchain-based Internet",
"keywords": [
"QORT",
@ -30,7 +30,7 @@
"publish": "electron-builder -p always"
},
"dependencies": {
"@hapi/hapi": "21.3.12",
"@hapi/hapi": "21.4.0",
"@hapi/inert": "7.1.0",
"@lit-labs/motion": "1.0.6",
"@popperjs/core": "2.11.8",
@ -50,7 +50,7 @@
"crypto-js": "4.2.0",
"driver.js": "1.3.5",
"electron-dl": "3.5.2",
"electron-log": "5.3.0",
"electron-log": "5.3.2",
"electron-store": "8.2.0",
"electron-updater": "6.3.9",
"emoji-picker-js": "https://github.com/Qortal/emoji-picker-js",
@ -59,22 +59,23 @@
"localforage": "1.10.0",
"lodash": "4.17.21",
"os-locale": "5.0.0",
"prosemirror-commands": "1.6.2",
"prosemirror-commands": "1.7.0",
"prosemirror-dropcursor": "1.8.1",
"prosemirror-gapcursor": "1.3.2",
"prosemirror-history": "1.4.1",
"prosemirror-keymap": "1.2.2",
"prosemirror-model": "1.24.1",
"prosemirror-schema-list": "1.5.0",
"prosemirror-model": "1.25.0",
"prosemirror-schema-list": "1.5.1",
"prosemirror-state": "1.4.3",
"prosemirror-transform": "1.10.2",
"prosemirror-view": "1.37.2",
"prosemirror-transform": "1.10.3",
"prosemirror-view": "1.38.1",
"sass": "1.77.6",
"short-unique-id": "5.2.0",
"xhr2": "0.2.1"
},
"devDependencies": {
"@babel/core": "7.26.8",
"@babel/core": "7.26.10",
"@electron/notarize": "2.5.0",
"@electron/packager": "18.3.6",
"@material/mwc-button": "0.27.0",
"@material/mwc-checkbox": "0.27.0",
@ -114,8 +115,8 @@
"@qortal/rollup-plugin-web-worker-loader": "1.6.5",
"@rollup/plugin-alias": "5.1.1",
"@rollup/plugin-babel": "6.0.4",
"@rollup/plugin-commonjs": "28.0.2",
"@rollup/plugin-node-resolve": "16.0.0",
"@rollup/plugin-commonjs": "28.0.3",
"@rollup/plugin-node-resolve": "16.0.1",
"@rollup/plugin-replace": "6.0.2",
"@rollup/plugin-terser": "0.4.4",
"@vaadin/avatar": "24.2.9",
@ -127,8 +128,8 @@
"@vaadin/tabsheet": "24.2.9",
"@vaadin/tooltip": "24.2.9",
"@zip.js/zip.js": "2.7.57",
"axios": "1.7.9",
"electron": "34.1.1",
"axios": "1.8.3",
"electron": "32.3.1",
"electron-builder": "25.1.8",
"epml": "0.3.3",
"file-saver": "2.0.5",
@ -140,13 +141,13 @@
"pwa-helpers": "0.9.1",
"redux": "5.0.1",
"redux-thunk": "3.1.0",
"rollup": "4.34.6",
"rollup": "4.36.0",
"rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-progress": "1.1.2",
"rollup-plugin-scss": "3.0.0",
"shelljs": "0.8.5"
"shelljs": "0.9.2"
},
"engines": {
"node": ">=20.18.1"
"node": ">=20.16.0"
}
}

View File

@ -5,7 +5,7 @@ import localForage from 'localforage'
import '@material/mwc-icon'
// Multi language support
import { translate } from '../../../../core/translate'
import { get, translate } from '../../../../core/translate'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
@ -66,6 +66,9 @@ class ChatHead extends LitElement {
} else if (groupString === 'Group_1') {
const avatarUrl = `/img/qdcgroup.png`
this.avatarImg = this.createImage(avatarUrl)
} else if (groupString === 'Group_694') {
const avatarUrl = `/img/minter.png`
this.avatarImg = this.createImage(avatarUrl)
} else if (this.chatInfo.name) {
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.chatInfo.name}/qortal_avatar?async=true`
this.avatarImg = this.createImage(avatarUrl)
@ -129,12 +132,24 @@ class ChatHead extends LitElement {
>
${this.chatInfo.groupName ? this.chatInfo.groupName : this.chatInfo.name !== undefined ? this.chatInfo.name : this.chatInfo.address.substr(0, 15)}
</span>
<mwc-icon style="font-size:18px; color: var(--chat-group);">${this.chatInfo.groupId !== undefined ? 'lock_open' : 'lock'}</mwc-icon>
<mwc-icon
style="font-size:18px; color:${
this.chatInfo.groupId === undefined ? '#f0ad4e' :
this.chatInfo.isOpen === false ? '#C6011F' :
this.chatInfo.isOpen === true ? '#198754' : '#198754'}"
>
${
this.chatInfo.groupId === undefined ? 'private_connectivity' :
this.chatInfo.isOpen === false ? 'lock_outline' :
this.chatInfo.isOpen === true ? 'lock_open' :
'lock_open'
}
</mwc-icon>
</div>
</div>
<div class="about" style="margin-top:7px">
<div class="name">
<span style="float:left; padding-left: 8px; color: var(--chat-group);font-size:12px">${this.chatInfo.groupId !== undefined ? 'id: ' + this.chatInfo.groupId : ''}</span>
<span style="float:left; padding-left: 8px; color: var(--chat-group);font-size:12px">${this.chatInfo.groupId !== undefined ? 'id: ' + this.chatInfo.groupId : 'Private Chat'}</span>
<div style="color: var(--black); display: flex;font-size: 12px; align-items:center">
<div style="width: 8px; height: 8px;border-radius: 50%;background: ${isUnread ? 'var(--error)' : 'none'} ; margin-right:5px;"></div>
<message-time style="display: ${(this.chatInfo.timestamp && this.chatInfo.timestamp > 100000) ? 'block' : 'none'}" timestamp=${this.chatInfo.timestamp}></message-time>

View File

@ -3,7 +3,7 @@ import { ifDefined } from 'lit/directives/if-defined.js'
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
import { animate } from '@lit-labs/motion'
import { Epml } from '../../../epml'
import { Editor, Extension, generateHTML } from '@tiptap/core'
import { Editor, Extension, generateHTML, generateJSON } from '@tiptap/core'
import { escape } from 'html-escaper'
import { inputKeyCodes, replaceMessagesEdited, generateIdFromAddresses } from '../../utils/functions'
import { publishData, modalHelper, RequestQueue } from '../../utils/classes'
@ -345,7 +345,12 @@ class ChatPage extends LitElement {
}
${+this.repliedToMessageObj.version > 1 ?
html`
<span style="color: var(--black);">${unsafeHTML(generateHTML(this.repliedToMessageObj.message, [StarterKit, Underline, Highlight, Mention]))}</span>
<span style="color: var(--black);">
${this.repliedToMessageObj.decodedMessage.includes('specialId') ?
this.convertHubMessageToJson(this.repliedToMessageObj.message) :
unsafeHTML(generateHTML(this.repliedToMessageObj.message, [StarterKit, Underline, Highlight, Mention]))
}
</span>
`
: ''
}
@ -362,7 +367,12 @@ class ChatPage extends LitElement {
<vaadin-icon class="reply-icon" icon="vaadin:pencil" slot="icon"></vaadin-icon>
<div class="repliedTo-message">
<p class="senderName">${translate("chatpage.cchange25")}</p>
<span style="color: var(--black);">${unsafeHTML(generateHTML(this.editedMessageObj.message, [StarterKit, Underline, Highlight, Mention]))}</span>
<span style="color: var(--black);">
${this.editedMessageObj.decodedMessage.includes('specialId') && !this.editedMessageObj.decodedMessage.includes('messageText') ?
this.convertHubMessageToJson(this.editedMessageObj.message) :
unsafeHTML(generateHTML(this.editedMessageObj.message, [StarterKit, Underline, Highlight, Mention]))
}
</span>
</div>
<vaadin-icon class="close-icon" icon="vaadin:close-big" slot="icon" @click=${() => this.closeEditMessageContainer()}></vaadin-icon>
</div>
@ -845,7 +855,12 @@ class ChatPage extends LitElement {
if (isEnabledChatEnter) {
this.isEnabledChatEnter = isEnabledChatEnter === 'false' ? false : true
}
}
convertHubMessageToJson(message) {
let newJson = generateJSON(`${message}`, [StarterKit, Underline, Highlight, Mention])
return unsafeHTML(generateHTML(newJson, [StarterKit, Underline, Highlight, Mention]))
}
getNodeUrl() {
@ -1666,7 +1681,7 @@ class ChatPage extends LitElement {
const getMembersAdmins = await parentEpml.request("apiCall", {
type: "api",
url: `/groups/members/${groupId}?onlyAdmins=true&limit=20`
url: `/groups/members/${groupId}?onlyAdmins=true&limit=0`
})
const getGroupInfo = await parentEpml.request("apiCall", {
@ -2551,15 +2566,13 @@ class ChatPage extends LitElement {
const initDirect = async (cid, noInitial) => {
let timeoutId
let initial = 0
let directSocketTimeout
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let nodeProtocol = myNode.protocol
let directSocketLink
if (window.parent.location.protocol === "https:") {
if (nodeProtocol === "https") {
directSocketLink = `wss://${nodeUrl}/websockets/chat/messages?involving=${window.parent.reduxStore.getState().app.selectedAddress.address}&involving=${cid}&encoding=BASE64&limit=1`
} else {
// Fallback to http
@ -2587,12 +2600,17 @@ class ChatPage extends LitElement {
let getInitialMessages = []
let count = 0
let isUnread = false
let chatInfoTimestamp
const chatId = this.chatId
const findContent = this.chatHeads.find((item) => item.url === chatId)
const chatInfoTimestamp = findContent.timestamp || 0
const lastReadMessageTimestamp = this.lastReadMessageTimestamp
if (findContent === undefined) {
chatInfoTimestamp = 0
} else {
chatInfoTimestamp = findContent.timestamp || 0
}
if (lastReadMessageTimestamp && chatInfoTimestamp) {
if (lastReadMessageTimestamp < chatInfoTimestamp) {
@ -2675,17 +2693,15 @@ class ChatPage extends LitElement {
const initGroup = (gId, noInitial) => {
let timeoutId
let groupId = Number(gId)
let initial = 0
let count = 0
let groupSocketTimeout
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let nodeProtocol = myNode.protocol
let groupSocketLink
if (window.parent.location.protocol === "https:") {
if (nodeProtocol === "https") {
groupSocketLink = `wss://${nodeUrl}/websockets/chat/messages?txGroupId=${groupId}&encoding=BASE64&limit=1`
} else {
// Fallback to http
@ -2710,13 +2726,18 @@ class ChatPage extends LitElement {
this.lastReadMessageTimestamp = await chatLastSeen.getItem(this.chatId) || 0
if (noInitial) return
let getInitialMessages = []
const lastReadMessageTimestamp = this.lastReadMessageTimestamp
let isUnread = false
let chatInfoTimestamp
const chatId = this.chatId
const findContent = this.chatHeads.find((item) => item.url === chatId)
const chatInfoTimestamp = findContent.timestamp || 0
const lastReadMessageTimestamp = this.lastReadMessageTimestamp
if (findContent === undefined) {
chatInfoTimestamp = 0
} else {
chatInfoTimestamp = findContent.timestamp || 0
}
if (lastReadMessageTimestamp && chatInfoTimestamp) {
if (lastReadMessageTimestamp < chatInfoTimestamp) {

View File

@ -3,7 +3,7 @@ import { repeat } from 'lit/directives/repeat.js'
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
import { Epml } from '../../../epml'
import { cropAddress, roundToNearestDecimal } from '../../utils/functions'
import { generateHTML } from '@tiptap/core'
import { generateHTML, generateJSON } from '@tiptap/core'
import { chatLimit, totalMsgCount } from './ChatPage'
import { chatStyles } from './plugins-css'
import isElectron from 'is-electron'
@ -280,6 +280,7 @@ class ChatScroller extends LitElement {
render() {
let formattedMessages = this.messagesToRender
return html`
${this.isLoadingBefore
? html`
@ -1081,17 +1082,22 @@ class MessageTemplate extends LitElement {
let version = 0
let isForwarded = false
let isEdited = false
let isFromHub = false
let isEncrypted = false
try {
const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage)
if (+parsedMessageObj.version > 1 && parsedMessageObj.messageText) {
if (parsedMessageObj.version > 1 && parsedMessageObj.messageText) {
messageVersion2 = generateHTML(parsedMessageObj.messageText, [StarterKit, Underline, Highlight, Mention])
messageVersion2WithLink = processText(messageVersion2)
}
message = parsedMessageObj.messageText
if (parsedMessageObj.version > 1 && parsedMessageObj.message && !parsedMessageObj.messageText) {
messageVersion2 = parsedMessageObj.message
messageVersion2WithLink = processText(messageVersion2)
}
message = parsedMessageObj.messageText ? parsedMessageObj.messageText : parsedMessageObj.message
repliedToData = this.messageObj.repliedToData
isImageDeleted = parsedMessageObj.isImageDeleted
isGifDeleted = parsedMessageObj.isGifDeleted
@ -1101,7 +1107,7 @@ class MessageTemplate extends LitElement {
version = parsedMessageObj.version
isForwarded = parsedMessageObj.type === 'forward'
isEdited = parsedMessageObj.isEdited && true
isFromHub = parsedMessageObj.isFromHub && true
isEncrypted = parsedMessageObj.isFromHub || parsedMessageObj.isPrivate || parsedMessageObj.message ? true : false
if (parsedMessageObj.images && Array.isArray(parsedMessageObj.images) && parsedMessageObj.images.length > 0) {
image = parsedMessageObj.images[0]
@ -1133,8 +1139,8 @@ class MessageTemplate extends LitElement {
let hideit = hidemsg.includes(this.messageObj.sender)
let forwarded = ''
let edited = ''
let fromHubOk = ''
let fromHubNo = ''
let encrypted = ''
let decrypted = ''
levelFounder = html`<level-founder checkleveladdress="${this.messageObj.sender}"></level-founder>`
@ -1250,9 +1256,9 @@ class MessageTemplate extends LitElement {
</span>
`
fromHubOk = html`&nbsp;&nbsp;&nbsp;<mwc-icon style="font-size:16px; color: var(--chat-group);">key</mwc-icon>&nbsp;&nbsp;&nbsp;`
encrypted = html`&nbsp;&nbsp;&nbsp;<mwc-icon style="font-size:16px; color: var(--chat-group);">key</mwc-icon>&nbsp;&nbsp;&nbsp;`
fromHubNo = html`&nbsp;&nbsp;&nbsp;<mwc-icon style="font-size:16px; color: var(--chat-group);">key_off</mwc-icon>&nbsp;&nbsp;&nbsp;`
decrypted = html`&nbsp;&nbsp;&nbsp;<mwc-icon style="font-size:16px; color: var(--chat-group);">key_off</mwc-icon>&nbsp;&nbsp;&nbsp;`
if (repliedToData) {
try {
@ -1266,6 +1272,10 @@ class MessageTemplate extends LitElement {
try {
repliedToMessageText = generateHTML(repliedToData.decodedMessage.messageText, [StarterKit, Underline, Highlight, Mention])
} catch (error) { /* empty */ }
} else if (repliedToData && repliedToData.decodedMessage && repliedToData.decodedMessage.message) {
try {
repliedToMessageText = this.convertHubMessageToJson(repliedToData.decodedMessage.message)
} catch (error) { /* empty */ }
}
let replacedMessage = ''
@ -1672,7 +1682,7 @@ class MessageTemplate extends LitElement {
` : this.isAgo ? html`
<div style="display: flex; align-items: center;">
<div style="margin-top: 4px;">
${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`}
${isEncrypted ? html`${encrypted}` : html`${decrypted}`}
</div>
<div id="timeformat">
<span>
@ -1683,7 +1693,7 @@ class MessageTemplate extends LitElement {
` : this.isIso ? html`
<div style="display: flex; align-items: center;">
<div style="margin-top: 4px;">
${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`}
${isEncrypted ? html`${encrypted}` : html`${decrypted}`}
</div>
<div id="timeformat">
<span>
@ -1694,7 +1704,7 @@ class MessageTemplate extends LitElement {
` : this.isBoth ? html`
<div style="display: flex; align-items: center;">
<div style="margin-top: 4px;">
${isFromHub ? html`${fromHubOk}` : html`${fromHubNo}`}
${isEncrypted ? html`${encrypted}` : html`${decrypted}`}
</div>
<div id="timeformat">
<span>
@ -2067,6 +2077,11 @@ class MessageTemplate extends LitElement {
}, 60000)
}
convertHubMessageToJson(message) {
let newJson = generateJSON(`${message}`, [StarterKit, Underline, Highlight, Mention])
return generateHTML(newJson, [StarterKit, Underline, Highlight, Mention])
}
async closeDownloadProgressDialog() {
const closeDelay = ms => new Promise(res => setTimeout(res, ms))
this.shadowRoot.getElementById('downloadProgressDialog').close()
@ -2350,7 +2365,13 @@ class ChatMenu extends LitElement {
<div
class=${`menu-icon ${!this.firstMessageInChat ? 'tooltip' : ''}`}
data-text="${translate('blockpage.bcchange12')}"
@click=${() => {if (this.version === '0') {this.versionErrorSnack(); return;} this.setEditedMessageObj(this.originalMessage);}}
@click=${() => {
if (this.version === '0') {
this.versionErrorSnack();
return;
}
this.setEditedMessageObj(this.originalMessage);
}}
>
<vaadin-icon icon="vaadin:pencil" slot="icon"></vaadin-icon>
</div>

View File

@ -1649,7 +1649,7 @@ export const chatStyles = css`
position: absolute;
top: 5px;
left: 10px;
height: 75%;
height: 85%;
width: 2.6px;
background-color: var(--mdc-theme-primary);
}
@ -1669,7 +1669,7 @@ export const chatStyles = css`
overflow: hidden;
text-overflow: ellipsis;
max-width: 500px;
max-height: 40px;
max-height: 80px;
margin: 0;
padding: 0;
}
@ -2014,8 +2014,13 @@ export const chatStyles = css`
}
#messageContent code {
background-color: rgba(#616161, 0.1);
color: #616161;
background: #0D0D0D;
color: #FFF;
font-family: 'JetBrainsMono', monospace;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
white-space: pre-wrap;
margin-top: 10px;
}
#messageContent pre {
@ -2034,12 +2039,10 @@ export const chatStyles = css`
font-size: 0.8rem;
}
#messageContent img {
width: 1.7em;
height: 1.5em;
margin: 0px;
}
#messageContent blockquote {
@ -2078,8 +2081,13 @@ export const chatStyles = css`
}
.replied-message code {
background-color: rgba(#616161, 0.1);
color: #616161;
background: #0D0D0D;
color: #FFF;
font-family: 'JetBrainsMono', monospace;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
white-space: pre-wrap;
margin: 0px;
}
.replied-message pre {
@ -7138,18 +7146,28 @@ export const qchatStyles = css`
* {
--mdc-theme-primary: rgb(3, 169, 244);
--mdc-theme-secondary: var(--mdc-theme-primary);
--paper-input-container-focus-color: var(--mdc-theme-primary);
--mdc-theme-surface: var(--white);
--mdc-dialog-content-ink-color: var(--black);
--mdc-dialog-min-width: 750px;
--lumo-primary-text-color: rgb(0, 167, 245);
--lumo-primary-color-50pct: rgba(0, 167, 245, 0.5);
--lumo-primary-color-10pct: rgba(0, 167, 245, 0.1);
--lumo-primary-color: hsl(199, 100%, 48%);
--lumo-secondary-text-color: var(--sectxt);
--lumo-contrast-60pct: var(--vdicon);
--item-selected-color: var(--nav-selected-color);
--lumo-base-color: var(--white);
--lumo-body-text-color: var(--black);
--_lumo-grid-border-color: var(--border);
--_lumo-grid-secondary-border-color: var(--border2);
--mdc-dialog-min-width: 750px;
--item-selected-color-text: var(--nav-selected-color-text);
--item-color-active: var(--nav-color-active);
--item-color-hover: var(--nav-color-hover);
--item-text-color: var(--nav-text-color);
--item-icon-color: var(--nav-icon-color);
--item-border-color: var(--nav-border-color);
--item-border-selected-color: var(--nav-border-selected-color);
--paper-input-container-focus-color: var(--mdc-theme-primary);
}
paper-spinner-lite {
@ -7647,109 +7665,108 @@ export const qchatStyles = css`
overflow: hidden;
}
.check-roller {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.check-roller div {
animation: check-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
transform-origin: 40px 40px;
}
.check-roller div:after {
content: " ";
display: block;
.view-grid {
width: 120px;
height: 120px;
position: absolute;
width: 7px;
height: 7px;
left: 50%;
top: 50%;
}
.view-grid div {
position: absolute;
width: 34px;
height: 34px;
border-radius: 50%;
background: var(--black);
margin: -4px 0 0 -4px;
background: #03a9f4;
animation: view-grid 1.2s linear infinite;
}
.check-roller div:nth-child(1) {
animation-delay: -0.036s;
.view-grid div:nth-child(1) {
top: 4px;
left: 4px;
animation-delay: 0s;
}
.check-roller div:nth-child(1):after {
top: 63px;
left: 63px;
}
.check-roller div:nth-child(2) {
animation-delay: -0.072s;
}
.check-roller div:nth-child(2):after {
top: 68px;
left: 56px;
}
.check-roller div:nth-child(3) {
animation-delay: -0.108s;
}
.check-roller div:nth-child(3):after {
top: 71px;
.view-grid div:nth-child(2) {
top: 4px;
left: 48px;
animation-delay: -0.4s;
}
.check-roller div:nth-child(4) {
animation-delay: -0.144s;
.view-grid div:nth-child(3) {
top: 4px;
left: 90px;
animation-delay: -0.8s;
}
.check-roller div:nth-child(4):after {
top: 72px;
left: 40px;
.view-grid div:nth-child(4) {
top: 50px;
left: 4px;
animation-delay: -0.4s;
}
.check-roller div:nth-child(5) {
animation-delay: -0.18s;
.view-grid div:nth-child(5) {
top: 50px;
left: 48px;
animation-delay: -0.8s;
}
.check-roller div:nth-child(5):after {
top: 71px;
left: 32px;
.view-grid div:nth-child(6) {
top: 50px;
left: 90px;
animation-delay: -1.2s;
}
.check-roller div:nth-child(6) {
animation-delay: -0.216s;
.view-grid div:nth-child(7) {
top: 95px;
left: 4px;
animation-delay: -0.8s;
}
.check-roller div:nth-child(6):after {
top: 68px;
left: 24px;
.view-grid div:nth-child(8) {
top: 95px;
left: 48px;
animation-delay: -1.2s;
}
.check-roller div:nth-child(7) {
animation-delay: -0.252s;
.view-grid div:nth-child(9) {
top: 95px;
left: 90px;
animation-delay: -1.6s;
}
.check-roller div:nth-child(7):after {
top: 63px;
left: 17px;
}
.check-roller div:nth-child(8) {
animation-delay: -0.288s;
}
.check-roller div:nth-child(8):after {
top: 56px;
left: 12px;
}
@keyframes check-roller {
0% {
transform: rotate(0deg);
}
@keyframes view-grid {
0%,
100% {
transform: rotate(360deg);
opacity: 1;
}
50% {
opacity: 0.5;
}
}
paper-dialog.viewSettings {
min-width: 525px;
max-width: 525px;
min-height: auto;
max-height: 150px;
background-color: var(--white);
color: var(--black);
line-height: 1.6;
overflow: hidden;
border: 1px solid var(--black);
border-radius: 10px;
padding: 15px;
box-shadow: 0px 10px 15px rgba(0, 0, 0, 0.1);
}
.view {
display: inline;
width: 50%;
align-items: center;
}
`
@ -8516,7 +8533,7 @@ export const groupManagementStyles = css`
position: absolute;
top: 5px;
left: 10px;
height: 75%;
height: 85%;
width: 2.6px;
background-color: var(--mdc-theme-primary);
}
@ -8540,7 +8557,7 @@ export const groupManagementStyles = css`
overflow: hidden;
text-overflow: ellipsis;
max-width: 500px;
max-height: 40px;
max-height: 80px;
margin: 0;
padding: 0;
}

View File

@ -122,8 +122,9 @@ export const extensionToPointer = (repString) => {
const replace36 = replace35.split('.7z').join('.7z</newpointer>')
const replace37 = replace36.split('.gz').join('.gz</newpointer>')
const replace38 = replace37.split('.bz2').join('.bz2</newpointer>')
const replace39 = replace38.split('service=QCHAT_IMAGE</p>').join('service=QCHAT_IMAGE</newpointer></p>')
return replace38
return replace39
}
export const encodedToChar = (encodedString) => {
@ -159,15 +160,15 @@ export const embedToString = (embed) => {
embedService = embed.service
embedName = embed.name
embedIdentifier = embed.identifier
embedString = ',"images":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '"}],"isImageDeleted":false'
embedString = '"images":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '"}],"isImageDeleted":false'
} else if (embed.type === "ATTACHMENT") {
embedService = embed.service
embedName = embed.name
embedIdentifier = embed.identifier
embedAttachmentName = embed.fileName
embedString = ',"attachments":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '","attachmentName":"' + embedAttachmentName + '","attachmentSize":0}],"isAttachmentDeleted":false'
embedString = '"attachments":[{"service":"' + embedService + '","name":"' + embedName + '","identifier":"' + embedIdentifier + '","attachmentName":"' + embedAttachmentName + '","attachmentSize":0}],"isAttachmentDeleted":false'
} else {
embedString = ',"images":[""]'
embedString = '"images":[""]'
}
return embedString

View File

@ -1,6 +1,15 @@
// IS_USING_PUBLIC_NODE
export const IS_USING_PUBLIC_NODE = 'IS_USING_PUBLIC_NODE'
// GET_ARRR_SYNC_STATUS
export const GET_ARRR_SYNC_STATUS = 'GET_ARRR_SYNC_STATUS'
// GET_NODE_INFO
export const GET_NODE_INFO = 'GET_NODE_INFO'
// GET_NODE_STATUS
export const GET_NODE_STATUS = 'GET_NODE_STATUS'
// ADMIN_ACTION
export const ADMIN_ACTION = 'ADMIN_ACTION'
@ -123,6 +132,9 @@ export const OPEN_PROFILE = 'OPEN_PROFILE'
// GET_USER_WALLET
export const GET_USER_WALLET = 'GET_USER_WALLET'
// GET_USER_WALLET_TRANSACTIONS
export const GET_USER_WALLET_TRANSACTIONS = 'GET_USER_WALLET_TRANSACTIONS'
// GET_WALLET_BALANCE
export const GET_WALLET_BALANCE = 'GET_WALLET_BALANCE'

View File

@ -2767,6 +2767,15 @@ self.addEventListener('message', async (e) => {
})
const decode = (string, keys, ref) => {
let repliedToStr = ''
let hubSpecialId = ''
let hubMessageStr = ''
let newMessageObject = ''
let reactionStr = ''
let messageUseEmbed = {}
let editStr = false
let embedFileStr = '"images":[""]'
const binaryString = atob(string)
const binaryLength = binaryString.length
const bytes = new Uint8Array(binaryLength)
@ -2787,88 +2796,49 @@ const decode = (string, keys, ref) => {
return decodedString
}
} else {
let repliedToStr = ''
let addedFileStr = ''
let messageStr = ''
let hubString = ''
let messageRep = ''
let messageUseEmbed = {}
const res = decryptSingle(string, keys, false)
if (res === 'noKey' || res === 'decryptionFailed') {
return '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"This message could not be decrypted"}]}]}' + addedFileStr + ',"repliedTo":"","version":3,"isFromHub":true}'
return '{"specialId":"","message":"<p>This message could not be decrypted</p>","repliedTo":"","isEdited":false,"isFromHub":true,"version": 3}'
}
const decryptToUnit8Array = base64ToUint8Array(res)
const responseData = uint8ArrayToObject(decryptToUnit8Array)
if (responseData.type === "notification") {
const messageStrRaw = responseData.data.message
messageStr = messageStrRaw.trim()
}
if (ref !== "noref") {
if (responseData.type === "reaction") {
repliedToStr = ref
messageStr = responseData.content
}
}
if (responseData.hasOwnProperty('message') && typeof responseData['message'] === 'string' && responseData['message'].length) {
if (responseData.message.includes('qortal://use-embed/')) {
const useEmbed1 = extensionToPointer(responseData.message)
const useEmbed2 = /<newpointer>(.*?)<\/newpointer>/g.exec(useEmbed1)
const useEmbed3 = encodedToChar(useEmbed2[1])
messageUseEmbed = parseQortalLink(useEmbed3)
addedFileStr = embedToString(messageUseEmbed)
const useEmbed4 = responseData.message.split(useEmbed2[1]).join('')
if (useEmbed4 === "<p></p>") {
messageRep = useEmbed4.split('<p></p>').join('<p>Qortal-Hub embed link</p>')
} else {
messageRep = useEmbed4
}
} else {
messageRep = responseData.message
addedFileStr = ',"images":[""]'
}
const messageRep1 = messageRep.split('"').join('<upvote>')
const messageRep2 = messageRep1.split('</p><p></p><p></p><p></p><p>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep3 = messageRep2.split('</p><p></p><p></p><p>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep4 = messageRep3.split('</p><p></p><p>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep5 = messageRep4.replace('</p><p>', '')
const messageRep6 = messageRep5.replace('<p></p>', '')
const messageRep7 = messageRep6.replace('<p>', '')
const messageRep8 = messageRep7.replace('<br></p>', '')
const messageRep9 = messageRep8.replace('</p>', '')
const messageRep10 = messageRep9.trim()
const messageRep11 = messageRep10.split('<br><br><br><br>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep12 = messageRep11.split('<br><br><br>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep13 = messageRep12.split('<br><br>').join('"},{"type":"hardBreak"},{"type":"hardBreak"},{"type":"text","text":"')
const messageRep14 = messageRep13.split('<br>').join('"},{"type":"hardBreak"},{"type":"text","text":"')
messageStr = messageRep14
if (responseData.type === "edit") {
editStr = true
}
if (responseData.repliedTo) {
repliedToStr = responseData.repliedTo
}
if (responseData.type === "edit") {
hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isEdited":true,"isFromHub":true}'
} else if (responseData.type === "reaction") {
hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isReaction":true,"isFromHub":true}'
} else {
hubString = '{"messageText":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + messageStr + '"}]}]}' + addedFileStr + ',"repliedTo":"' + repliedToStr + '","version":3,"isFromHub":true}'
if (responseData.specialId) {
hubSpecialId = responseData.specialId
}
const preparedString = hubString.split('<upvote>').join('\\"')
const finalString = preparedString.replace(/<\/?[^>]+(>|$)/g, '')
if (responseData.type === "notification") {
hubMessageStr = responseData.data.message
} else if (ref !== "noref" && responseData.type === "reaction") {
reactionStr = '"isReaction":true,'
repliedToStr = ref
hubMessageStr = responseData.content
} else if (responseData.message.includes('qortal://use-embed/')) {
const useEmbed1 = extensionToPointer(responseData.message)
const useEmbed2 = /<newpointer>(.*?)<\/newpointer>/g.exec(useEmbed1)
const useEmbed3 = encodedToChar(useEmbed2[1])
messageUseEmbed = parseQortalLink(useEmbed3)
embedFileStr = embedToString(messageUseEmbed)
hubMessageStr = responseData.message.split(useEmbed2[1]).join('')
} else {
hubMessageStr = responseData.message
}
return finalString
const hubMessageFinal = hubMessageStr.split('"').join('&quot;')
newMessageObject = '{"specialId":"' + hubSpecialId + '","message":"' + hubMessageFinal + '",' + embedFileStr + ',"repliedTo":"' + repliedToStr + '","isEdited":' + editStr + ',"isFromHub":true,' + reactionStr + '"version": 3}'
return newMessageObject
}
}
@ -2923,6 +2893,14 @@ export const decryptChatMessageBase64 = (encryptedMessage, privateKey, recipient
return _decryptedMessage
}
let decrypted1 = new TextDecoder('utf-8').decode(_decryptedMessage)
if (decrypted1.includes('messageText')) {
let decrypted2 = JSON.parse(decrypted1)
let decrypted3 = Object.assign(decrypted2, {isPrivate: true})
return JSON.stringify(decrypted3)
}
return new TextDecoder('utf-8').decode(_decryptedMessage)
}
@ -2975,4 +2953,4 @@ const decodeMessage = (encodedMessageObj, isReceipient, _publicKey, privateKey,
}
return decodedMessageObj
}
}

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ import '@vaadin/grid'
// Multi language support
import { get, registerTranslateConfig, translate, use } from '../../../../core/translate'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
@ -427,7 +428,9 @@ class NodeManagement extends LitElement {
async addPeer() {
this.addPeerLoading = true
const addPeerAddress = this.shadowRoot.getElementById('addPeerAddress').value
await parentEpml.request('apiCall', {
url: `/peers?apiKey=${this.getApiKey()}`,
method: 'POST',
@ -456,7 +459,6 @@ class NodeManagement extends LitElement {
addMintingAccount() {
this.addMintingAccountLoading = true
this.addMintingAccountMessage = 'Loading...'
this.addMintingAccountKey = this.shadowRoot.querySelector('#addMintingAccountKey').value
parentEpml.request('apiCall', {
@ -479,6 +481,7 @@ class NodeManagement extends LitElement {
updateMintingAccounts() {
this.mintingAccounts = []
parentEpml.request('apiCall', {
url: `/admin/mintingaccounts?apiKey=${this.getApiKey()}`,
method: 'GET'
@ -518,10 +521,6 @@ class NodeManagement extends LitElement {
if (!arr) { return true }
return arr.length === 0
}
round(number) {
return (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
}
}
window.customElements.define('node-management', NodeManagement)

View File

@ -10,6 +10,7 @@ import '@vaadin/button'
// Multi language support
import { get, registerTranslateConfig, translate, use } from '../../../../core/translate'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
@ -144,7 +145,6 @@ class OverviewPage extends LitElement {
async firstUpdated() {
this.changeTheme()
this.changeLanguage()
this.nodeConfig = window.parent.reduxStore.getState().app.nodeConfig
this.accountInfo = window.parent.reduxStore.getState().app.accountInfo
@ -199,11 +199,13 @@ class OverviewPage extends LitElement {
changeTheme() {
const checkTheme = localStorage.getItem('qortalTheme')
if (checkTheme === 'dark') {
this.theme = 'dark'
} else {
this.theme = 'light'
}
document.querySelector('html').setAttribute('theme', this.theme)
}
@ -225,6 +227,7 @@ class OverviewPage extends LitElement {
async refreshItems() {
this.nodeConfig = window.parent.reduxStore.getState().app.nodeConfig
this.accountInfo = window.parent.reduxStore.getState().app.accountInfo
await this.getNodeInfo()
await this.getCoreInfo()
await this.getBalanceInfo()
@ -234,12 +237,14 @@ class OverviewPage extends LitElement {
async getMintingKeysList() {
this.check1 = false
this.check2 = false
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeStatus = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
const statusUrl = `${nodeStatus}/admin/mintingaccounts`
const statusUrl = `${nodeStatus}/admin/mintingaccounts?apiKey=${this.getApiKey()}`
try {
const res = await fetch(statusUrl)
this.listAccounts = await res.json()
const addressInfo = window.parent.reduxStore.getState().app.accountInfo.addressInfo
@ -249,7 +254,6 @@ class OverviewPage extends LitElement {
const findRemovedSponsorsKey = this.listAccounts.filter((my) => my.address)
this.check1 = findMyMintingAccount !== undefined
this.check2 = findMyMintingRecipient !== undefined
if (findRemovedSponsorsKey.length > 0) {
@ -285,8 +289,7 @@ class OverviewPage extends LitElement {
this.cssStatus = ''
return html`<span class="btn btn-sm btn-info float-right">${translate("walletprofile.wp1")}</span>`
} else if (this.nodeInfo.isMintingPossible === true && this.nodeInfo.isSynchronizing === false && this.check1 === false && this.check2 === true && addressInfo.level == 0 && addressInfo.blocksMinted < 7200) {
this.cssStatus = ''
return html`<span class="btn btn-sm btn-info float-right">${translate("becomeMinterPage.bchange12")}</span>`
return html`<span class="float-right"><start-minting-now></start-minting-now></span>`
} else if (this.check1 === false && this.check2 === false && myMintingKey === true) {
return html`<span class="float-right"><start-minting-now></start-minting-now></span>`
} else if (myMintingKey === false) {
@ -319,6 +322,7 @@ class OverviewPage extends LitElement {
const infoNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const infoNodeUrl = infoNode.protocol + '://' + infoNode.domain + ':' + infoNode.port
const nodeUrl = `${infoNodeUrl}/admin/status`
await fetch(nodeUrl).then(response => {
return response.json()
}).then(data => {
@ -332,6 +336,7 @@ class OverviewPage extends LitElement {
const infoCore = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const infoCoreUrl = infoCore.protocol + '://' + infoCore.domain + ':' + infoCore.port
const coreUrl = `${infoCoreUrl}/admin/info`
await fetch(coreUrl).then(response => {
return response.json()
}).then(data => {
@ -344,6 +349,7 @@ class OverviewPage extends LitElement {
const infoBalance = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const infoBalanceUrl = infoBalance.protocol + '://' + infoBalance.domain + ':' + infoBalance.port
const balanceUrl = `${infoBalanceUrl}/addresses/balance/${this.accountInfo.addressInfo.address}`
await fetch(balanceUrl).then(response => {
return response.json()
}).then(data => {
@ -422,7 +428,7 @@ class StartMintingNow extends LitElement {
async getMintingAcccounts() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
const url = `${nodeUrl}/admin/mintingaccounts`
const url = `${nodeUrl}/admin/mintingaccounts?apiKey=${this.getApiKey()}`
try {
const res = await fetch(url)
this.mintingAccountData = await res.json()
@ -484,7 +490,9 @@ class StartMintingNow extends LitElement {
let interval = null
let stop = false
this.status = 2
const getAnswer = async () => {
const rewardShares = async (minterAddr) => {
const url = `${nodeUrl}/addresses/rewardshares?minters=${minterAddr}&recipients=${minterAddr}`
@ -508,6 +516,7 @@ class StartMintingNow extends LitElement {
stop = false
}
}
interval = setInterval(getAnswer, 5000)
}

View File

@ -39,6 +39,7 @@ import '@polymer/paper-icon-button/paper-icon-button.js'
import '@polymer/paper-spinner/paper-spinner-lite.js'
import '@vaadin/grid'
import '@vaadin/tooltip'
import '@vaadin/text-field'
// Multi language support
import { get, registerTranslateConfig, translate, use } from '../../../../core/translate'
@ -62,6 +63,7 @@ class Chat extends LitElement {
messages: { type: Array },
btnDisable: { type: Boolean },
isLoading: { type: Boolean },
isViewOpen: { type: Boolean },
balance: { type: Number },
theme: { type: String, reflect: true },
blockedUsers: { type: Array },
@ -69,6 +71,7 @@ class Chat extends LitElement {
privateMessagePlaceholder: { type: String },
imageFile: { type: Object },
activeChatHeadUrl: { type: String },
switchChatHeadUrl: { type: String },
openPrivateMessage: { type: Boolean },
userFound: { type: Array },
userFoundModalOpen: { type: Boolean },
@ -102,6 +105,7 @@ class Chat extends LitElement {
this.messages = []
this.btnDisable = false
this.isLoading = false
this.isViewOpen = false
this.showNewMessageBar = this.showNewMessageBar.bind(this)
this.hideNewMessageBar = this.hideNewMessageBar.bind(this)
this.setOpenPrivateMessage = this.setOpenPrivateMessage.bind(this)
@ -113,6 +117,7 @@ class Chat extends LitElement {
this.privateMessagePlaceholder = ''
this.imageFile = null
this.activeChatHeadUrl = ''
this.switchChatHeadUrl = ''
this.openPrivateMessage = false
this.userFound = []
this.userFoundModalOpen = false
@ -140,7 +145,7 @@ class Chat extends LitElement {
</vaadin-tooltip>
</div>
<div style="display:flex; align-items:center;gap:10px">
<div id="viewChat" class="create-chat" @click=${() => { this.shadowRoot.querySelector('#viewChatDialog').show() }}>
<div id="viewChat" class="create-chat" @click=${() => { this.openView(this.activeChatHeadUrl) }}>
<mwc-icon style="color: var(--black);">pageview</mwc-icon>
<vaadin-tooltip
for="viewChat"
@ -185,7 +190,11 @@ class Chat extends LitElement {
<span>${translate("chatpage.cchange5")} <mwc-icon style="font-size: 16px; vertical-align: bottom;">keyboard_arrow_down</mwc-icon></span>
</div>
<div class="chat-history">
${this.activeChatHeadUrl ? html`${this.renderChatPage()}` : html`${this.renderChatWelcomePage()}`}
${this.activeChatHeadUrl ?
html`${this.renderChatPage()}`
: this.isViewOpen ? html`${this.renderChatViewPage()}`
: html`${this.renderChatWelcomePage()}`
}
</div>
</div>
<!-- Start Chatting Dialog -->
@ -315,43 +324,24 @@ class Chat extends LitElement {
</mwc-button>
</mwc-dialog>
<!-- View Chat Over ID -->
<mwc-dialog id="viewChatDialog">
<div style="text-align: center;">
<h1>Please Enter The Group ID</h1>
<hr>
<br>
<paper-dialog id="viewChatDialog" class="viewSettings" modal>
<div style="display: inline;">
<div class="view">
<vaadin-text-field
style="width: 350px"
id="groupIdInput"
required
allowed-char-pattern="[0-9]"
placeholder="${translate("modals.mpchange87")}"
value=""
@keydown="${this.viewKeyListener}"
clear-button-visible
>
</vaadin-text-field>
<paper-icon-button icon="icons:visibility" @click="${() => this.switchChatID()}" title="${translate("general.view")}"></paper-icon-button>
<paper-icon-button icon="icons:close" @click="${() => this.closeView()}" title="${translate("general.close")}"></paper-icon-button>
</div>
</div>
<div style="display: flex; align-items: center;">
<mwc-textfield
style="width: 100%;"
required
id="groupIdInput"
label="Emter Group ID"
type="number"
auto-validate="false"
value=""
>
</mwc-textfield>
</div>
<mwc-button slot="primaryAction" dialogAction="cancel" class="red">
${translate("general.close")}
</mwc-button>
<mwc-button slot="secondaryAction" class="green" @click=${this.switchChatID}>
${translate("general.view")}
</mwc-button>
</mwc-dialog>
<paper-dialog id="checkIdDialog" class="check" modal>
<div class="check-roller">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<h2>Checking</h2>
</paper-dialog>
</div>
`
@ -499,8 +489,6 @@ class Chat extends LitElement {
viewGroupID = this.shadowRoot.getElementById('groupIdInput').value
this.shadowRoot.getElementById('checkIdDialog').open()
await parentEpml.request('apiCall', {
url: `/groups/${viewGroupID}`
}).then(res => {
@ -508,25 +496,55 @@ class Chat extends LitElement {
})
if (checkTheID.error) {
this.shadowRoot.getElementById('checkIdDialog').close()
this.shadowRoot.getElementById('viewChatDialog').close()
this.shadowRoot.getElementById('groupIdInput').value = ''
this.isViewOpen = false
this.activeChatHeadUrl = this.switchChatHeadUrl
this.switchChatHeadUrl = ''
this.resetChatEditor()
parentEpml.request('showSnackBar', `${notFound}`)
} else if (checkTheID.groupId) {
let switchToID = checkTheID.groupName
this.shadowRoot.getElementById('checkIdDialog').close()
this.shadowRoot.getElementById('viewChatDialog').close()
this.shadowRoot.getElementById('groupIdInput').value = ''
this.switchChatHeadUrl = ''
parentEpml.request('showSnackBar', `${switchToID}`)
this.processChatID(checkTheID.groupId)
} else {
this.shadowRoot.getElementById('checkIdDialog').close()
this.shadowRoot.getElementById('viewChatDialog').close()
this.shadowRoot.getElementById('groupIdInput').value = ''
this.isViewOpen = false
this.activeChatHeadUrl = this.switchChatHeadUrl
this.switchChatHeadUrl = ''
this.resetChatEditor()
parentEpml.request('showSnackBar', `${wentWrong}`)
}
}
openView(currentUrl) {
this.switchChatHeadUrl = currentUrl
this.activeChatHeadUrl = ''
this.isViewOpen = true
this.shadowRoot.getElementById('viewChatDialog').open()
this.shadowRoot.getElementById('groupIdInput').value = ''
this.resetChatEditor()
}
closeView() {
this.shadowRoot.getElementById('viewChatDialog').close()
this.shadowRoot.getElementById('groupIdInput').value = ''
this.isViewOpen = false
this.activeChatHeadUrl = this.switchChatHeadUrl
this.switchChatHeadUrl = ''
this.resetChatEditor()
}
viewKeyListener(e) {
if (e.key === 'Enter') {
this.switchChatID()
}
}
async processChatID(newID) {
let viewNewUrl = 'group/' + newID
this.setActiveChatHeadUrl(viewNewUrl)
@ -535,6 +553,7 @@ class Chat extends LitElement {
async setActiveChatHeadUrl(url) {
await this.getSymKeyFile(url)
this.isViewOpen = false
}
async getSymKeyFile(url) {
@ -1153,6 +1172,22 @@ class Chat extends LitElement {
`
}
renderChatViewPage() {
return html`
<div class="view-grid">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
`
}
renderChatHead(chatHeadArr) {
return chatHeadArr.map(eachChatHead => {
return html`<chat-head activeChatHeadUrl=${this.activeChatHeadUrl} .setActiveChatHeadUrl=${(val) => this.setActiveChatHeadUrl(val)} chatInfo=${JSON.stringify(eachChatHead)}></chat-head>`
@ -1207,6 +1242,20 @@ class Chat extends LitElement {
}
}
async getGroupType(newGroupId) {
try {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
const response = await fetch(`${nodeUrl}/groups/${newGroupId}`)
const data = await response.json()
return data.isOpen
} catch (error) {
console.error('Error fetching group type', error)
throw error
}
}
async setChatHeads(chatObj) {
const chatObjGroups = Array.isArray(chatObj.groups) ? chatObj.groups : []
const chatObjDirect = Array.isArray(chatObj.direct) ? chatObj.direct : []
@ -1216,12 +1265,14 @@ class Chat extends LitElement {
url: `group/${group.groupId}`,
groupName: 'Qortal General Chat',
timestamp: group.timestamp === undefined ? 2 : group.timestamp,
sender: group.sender
sender: group.sender,
isOpen: true
} : {
...group,
timestamp: group.timestamp === undefined ? 1 : group.timestamp,
url: `group/${group.groupId}`,
ownerName: group.ownerName === undefined ? await this.getOwnerName(group.groupId) : 'undefined'
ownerName: group.ownerName === undefined ? await this.getOwnerName(group.groupId) : 'undefined',
isOpen: group.isOpen === undefined ? await this.getGroupType(group.groupId) : true
}))
let directList = chatObjDirect.map(dc => {

View File

@ -13,11 +13,14 @@ import {
processTransactionV2,
publishData,
requestQueueGetAtAddresses,
tradeBotCreateRequest
tradeBotCreateRequest,
getArrrSyncStatus,
getNodeInfo,
getNodeStatus
} from '../../../utils/classes'
import {appendBuffer} from '../../../utils/utilities'
import {QORT_DECIMALS} from '../../../../../crypto/api/constants'
import {listOfAllQortalRequests} from '../../components/qdn-action-constants'
import {mimeToExtensionMap, listOfAllQortalRequests} from '../../components/qdn-action-constants'
import {
createSymmetricKeyAndNonce,
decryptGroupEncryptionWithSharingKey,
@ -262,7 +265,7 @@ class WebBrowser extends LitElement {
${this.renderFollowUnfollowButton()}
</div>
<div class="iframe-container">
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen">
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen; clipboard-read; clipboard-write;">
<span style="color: var(--black);">${translate('browserpage.bchange6')}</span>
</iframe>
</div>
@ -319,6 +322,21 @@ class WebBrowser extends LitElement {
}
break
case actions.GET_ARRR_SYNC_STATUS: {
response = await getArrrSyncStatus()
}
break
case actions.GET_NODE_INFO: {
response = await getNodeInfo()
}
break
case actions.GET_NODE_STATUS: {
response = await getNodeStatus()
}
break
case actions.ADMIN_ACTION: {
let type = data.type
let value = data.value
@ -2252,6 +2270,108 @@ class WebBrowser extends LitElement {
}
break
case actions.SAVE_FILE: {
try {
const requiredFields = ['filename', 'blob']
const missingFields = []
let dataSentBack = {}
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field)
}
})
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ')
const tryAgain = get("walletpage.wchange44")
await showErrorAndWait(
"MISSING_FIELDS",
{
id1: missingFieldsString,
id2: tryAgain
}
)
dataSentBack['error'] = `Missing fields: ${missingFieldsString}`
response = JSON.stringify(dataSentBack)
break
}
const filename = data.filename
const blob = data.blob
const res = await showModalAndWait(
actions.SAVE_FILE,
{
filename
}
)
if (res.action === 'reject') {
let myMsg1 = get("transactions.declined")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 })
response = '{"error": "User declined request"}'
break
}
const mimeType = blob.type || data.mimeType
let backupExention = filename.split('.').pop()
if (backupExention) {
backupExention = '.' + backupExention
}
const fileExtension = mimeToExtensionMap[mimeType] || backupExention
let fileHandleOptions = {}
if (!mimeType) {
const obj = {}
obj['error'] = 'A mimeType could not be derived'
response = JSON.stringify(obj)
break
}
if (!fileExtension) {
const obj = {}
obj['error'] = 'A file extension could not be derived'
response = JSON.stringify(obj)
break
}
if (fileExtension && mimeType) {
fileHandleOptions = {
accept: {
[mimeType]: [fileExtension]
}
}
}
try {
const fileHandle = await self.showSaveFilePicker({
suggestedName: filename,
types: [
{
description: mimeType,
...fileHandleOptions
}
]
})
const writeFile = async (fileHandle, contents) => {
const writable = await fileHandle.createWritable()
await writable.write(contents)
await writable.close()
}
writeFile(fileHandle, blob).then(() => console.log("FILE SAVED"))
} catch (error) {
if (error.name === 'AbortError') {
const obj = {}
obj['error'] = 'User declined the download'
response = JSON.stringify(obj)
break
}
FileSaver.saveAs(blob, filename)
}
response = JSON.stringify(true)
} catch (error) {
let myMsg1 = get("managegroup.mg58")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
const obj = {}
obj['error'] = error.message || 'Failed to initiate download'
response = JSON.stringify(obj)
}
}
break
case actions.DEPLOY_AT: {
const requiredFields = ['name', 'description', 'tags', 'creationBytes', 'amount', 'assetId', 'type']
const missingFields = []
@ -2583,6 +2703,7 @@ class WebBrowser extends LitElement {
break
case 'ARRR':
userWallet['address'] = arrrAddress
userWallet['publicKey'] = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58
break
default:
break
@ -2599,12 +2720,121 @@ class WebBrowser extends LitElement {
}
break
case actions.GET_USER_WALLET_TRANSACTIONS: {
const requiredFields = ['coin']
const missingFields = []
let dataSentBack = {}
let skipWalletTransactions = false
let resSkipWalletTransactions
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field)
}
})
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ')
const tryAgain = get("walletpage.wchange44")
await showErrorAndWait(
"MISSING_FIELDS",
{
id1: missingFieldsString,
id2: tryAgain
}
)
dataSentBack['error'] = `Missing fields: ${missingFieldsString}`
response = JSON.stringify(dataSentBack)
break
}
if (window.parent.reduxStore.getState().app.qAPPAutoTransactions) {
skipWalletTransactions = true
}
if (!skipWalletTransactions) {
resSkipWalletTransactions = await showModalAndWait(
actions.GET_USER_WALLET_TRANSACTIONS
)
}
if ((resSkipWalletTransactions && resSkipWalletTransactions.action === 'accept') || skipWalletTransactions) {
let coin = data.coin
if (coin === "QORT") {
let qortAddress = window.parent.reduxStore.getState().app.selectedAddress.address
try {
response = await parentEpml.request('apiCall', {
url: `/transactions/address/${qortAddress}?limit=0&reverse=true`
})
break
} catch (error) {
let myMsg1 = get("browserpage.bchange21")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", {id1: myMsg1, id2: myMsg2})
const data = {}
data['error'] = error.message ? error.message : get("browserpage.bchange21")
response = JSON.stringify(data)
break
}
} else {
let _url = ``
let _body = null
switch (coin) {
case 'BTC':
_url = `/crosschain/btc/wallettransactions?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.btcWallet.derivedMasterPublicKey
break
case 'LTC':
_url = `/crosschain/ltc/wallettransactions?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.ltcWallet.derivedMasterPublicKey
break
case 'DOGE':
_url = `/crosschain/doge/wallettransactions?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.dogeWallet.derivedMasterPublicKey
break
case 'DGB':
_url = `/crosschain/dgb/wallettransactions?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.dgbWallet.derivedMasterPublicKey
break
case 'RVN':
_url = `/crosschain/rvn/wallettransactions?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.rvnWallet.derivedMasterPublicKey
break
case 'ARRR':
_url = `/crosschain/arrr/wallettransactions?apiKey=${this.getApiKey()}`
_body = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58
break
default:
break
}
try {
response = await parentEpml.request('apiCall', {
url: _url,
method: 'POST',
body: _body
})
break
} catch (error) {
let myMsg1 = get("browserpage.bchange21")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
const data = {}
data['error'] = error.message ? error.message : get("browserpage.bchange21")
response = JSON.stringify(data)
break
}
}
} else if (resSkipWalletTransactions.action === 'reject') {
let myMsg1 = get("transactions.declined")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 })
response = '{"error": "User declined request"}'
break
}
}
break
case actions.GET_WALLET_BALANCE: {
const requiredFields = ['coin']
const missingFields = []
let dataSentBack = {}
let skip = false
let res3
let skipWalletBalance = false
let resSkipWalletBalance
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field)
@ -2629,32 +2859,30 @@ class WebBrowser extends LitElement {
// then set the response string from the core to the `response` variable (defined above)
// If they decline, send back JSON that includes an `error` key, such as `{"error": "User declined request"}`
if (window.parent.reduxStore.getState().app.qAPPAutoBalance) {
skip = true
skipWalletBalance = true
}
if (!skip) {
res3 = await showModalAndWait(
if (!skipWalletBalance) {
resSkipWalletBalance = await showModalAndWait(
actions.GET_WALLET_BALANCE
)
}
if ((res3 && res3.action === 'accept') || skip) {
if ((resSkipWalletBalance && resSkipWalletBalance.action === 'accept') || skipWalletBalance) {
let coin = data.coin
if (coin === "QORT") {
let qortAddress = window.parent.reduxStore.getState().app.selectedAddress.address
try {
this.loader.show()
response = await parentEpml.request('apiCall', {
url: `/addresses/balance/${qortAddress}?apiKey=${this.getApiKey()}`
})
this.loader.hide()
break
} catch (error) {
this.loader.hide()
let myMsg1 = get("browserpage.bchange21")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", {id1: myMsg1, id2: myMsg2})
const data = {}
data['error'] = error.message ? error.message : get("browserpage.bchange21")
response = JSON.stringify(data)
break
}
} else {
let _url = ``
@ -2688,14 +2916,12 @@ class WebBrowser extends LitElement {
break
}
try {
this.loader.show()
const res = await parentEpml.request('apiCall', {
url: _url,
method: 'POST',
body: _body
})
if (isNaN(Number(res))) {
this.loader.hide()
let myMsg1 = get("browserpage.bchange21")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
@ -2704,12 +2930,10 @@ class WebBrowser extends LitElement {
response = JSON.stringify(data)
break
} else {
this.loader.hide()
response = (Number(res) / 1e8).toFixed(8)
break
}
} catch (error) {
this.loader.hide()
let myMsg1 = get("browserpage.bchange21")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
@ -2719,7 +2943,7 @@ class WebBrowser extends LitElement {
break
}
}
} else if (res3.action === 'reject') {
} else if (resSkipWalletBalance.action === 'reject') {
let myMsg1 = get("transactions.declined")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 })
@ -2732,7 +2956,9 @@ class WebBrowser extends LitElement {
case actions.GET_USER_WALLET_INFO: {
const requiredFields = ['coin']
const missingFields = []
let skipUserWalletInfo = false
let dataSentBack = {}
let resSkipUserWalletInfo
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field)
@ -2752,16 +2978,20 @@ class WebBrowser extends LitElement {
response = JSON.stringify(dataSentBack)
break
}
const userWallet = await showModalAndWait(
actions.GET_USER_WALLET
)
if (userWallet.action === 'accept') {
if (window.parent.reduxStore.getState().app.qAPPAutoAuth) {
skipUserWalletInfo = true
}
if (!skipUserWalletInfo) {
resSkipUserWalletInfo = await showModalAndWait(
actions.GET_USER_WALLET
)
}
if ((resSkipUserWalletInfo && resSkipUserWalletInfo.action === 'accept') || skipUserWalletInfo) {
let coin = data.coin
let walletKeys = this.getUserWallet(coin)
let _url = `/crosschain/` + data.coin.toLowerCase() + `/addressinfos?apiKey=${this.getApiKey()}`
let _body = { xpub58: walletKeys['publicKey'] }
try {
this.loader.show()
const bodyToString = JSON.stringify(_body)
const res = await parentEpml.request('apiCall', {
url: _url,
@ -2774,7 +3004,6 @@ class WebBrowser extends LitElement {
})
response = JSON.stringify(res)
} catch (error) {
this.loader.hide()
let myMsg1 = get("browserpage.bchange21")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
@ -2782,10 +3011,8 @@ class WebBrowser extends LitElement {
data['error'] = error.message ? error.message : get("browserpage.bchange21")
response = JSON.stringify(data)
return
} finally {
this.loader.hide()
}
} else if (userWallet.action === 'reject') {
} else if (resSkipUserWalletInfo.action === 'reject') {
let myMsg1 = get("transactions.declined")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("DECLINED_REQUEST", { id1: myMsg1, id2: myMsg2 })
@ -2819,7 +3046,6 @@ class WebBrowser extends LitElement {
}
let _url = `/crosschain/` + data.coin.toLowerCase() + `/serverinfos`
try {
this.loader.show()
const res = await parentEpml.request('apiCall', {
url: _url,
method: 'GET',
@ -2829,7 +3055,6 @@ class WebBrowser extends LitElement {
})
response = JSON.stringify(res.servers)
} catch (error) {
this.loader.hide()
let myMsg1 = get("modals.mpchange55")
let myMsg2 = get("walletpage.wchange44")
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
@ -2837,8 +3062,6 @@ class WebBrowser extends LitElement {
data['error'] = error.message ? error.message : get("modals.mpchange55")
response = JSON.stringify(data)
return
} finally {
this.loader.hide()
}
}
break
@ -3263,10 +3486,11 @@ class WebBrowser extends LitElement {
const signRequest = await showModalAndWait(
actions.SIGN_TRANSACTION,
{
text1: `${shouldProcess ? get("modals.mpchange65") : get("modals.mpchange6")}`,
text1: `${shouldProcess ? get("modals.mpchange65") : get("modals.mpchange66")}`,
text2: get("modals.mpchange67"),
text3: `${get("modals.mpchange68")} ${decodedData.type}`,
json: `${get("modals.mpchange69")} ${decodedData}`
txdata: `${get("modals.mpchange69")}`,
txjson: `${JSON.stringify(decodedData)}`
}
)
if (signRequest.action === 'accept') {
@ -3297,10 +3521,7 @@ class WebBrowser extends LitElement {
const signedBytes = appendBuffer(arbitraryBytesBuffer, signature)
const signedBytesToBase58 = Base58.encode(signedBytes)
if(!shouldProcess) {
let myMsg1 = get("modals.mpchange70")
let myMsg2 = get("modals.mpchange71") + signedBytesToBase58
await showSuccessAndWait("REQUEST_SUCCESS", { id1: myMsg1, id2: myMsg2 })
response = '{"error": "Process transaction was not requested!"}'
response = signedBytesToBase58
break
}
try {
@ -5126,7 +5347,6 @@ async function showModalAndWait(type, data) {
${type === actions.GET_PROFILE_DATA ? `
<div class="modal-subcontainer">
<p class="modal-paragraph">${get("browserpage.bchange49")}: <span style="font-weight: bold"> ${data.property}</span></p>
</div>
` : ''}
@ -5163,7 +5383,8 @@ async function showModalAndWait(type, data) {
<p class="modal-paragraph">${data.text1}</p>
<p class="modal-paragraph">${data.text2}</p>
<p class="modal-paragraph">${data.text3}</p>
<p class="modal-paragraph">Transaction: <span>${data.json}</span></p>
<p class="modal-paragraph"><span>${data.txdata}</span></p>
<p class="modal-paragraph"><span>${convertJson(data.txjson)}</span></p>
` : ''}
${type === actions.CREATE_TRADE_BUY_ORDER ? `
@ -5193,6 +5414,18 @@ async function showModalAndWait(type, data) {
<p class="modal-paragraph">${data.text3}</p>
<p class="modal-paragraph">${get("walletpage.wchange36")}: <span>${data.fee}</span></p>
` : ''}
${type === actions.GET_USER_WALLET_TRANSACTIONS ? `
<div class="modal-subcontainer">
<p class="modal-paragraph">Do you give this application permission to retrieve your wallet transactions?</p>
<div class="checkbox-row">
<label for="transactionsButton" id="transactionsButtonLabel" style="color: var(--black);">
Always allow wallet txs to be retrieved automatically
</label>
<mwc-checkbox style="margin-right: -15px;" id="transactionsButton" ?checked=${window.parent.reduxStore.getState().app.qAPPAutoTransactions}></mwc-checkbox>
</div>
</div>
` : ''}
</div>
<div class="modal-buttons">
<button id="cancel-button">${get("browserpage.bchange27")}</button>
@ -5264,7 +5497,7 @@ async function showModalAndWait(type, data) {
})
}
const checkbox1 = modal.querySelector('#abalanceButton')
const checkbox1 = modal.querySelector('#balanceButton')
if (checkbox1) {
checkbox1.addEventListener('click', (e) => {
if (e.target.checked) {
@ -5293,6 +5526,24 @@ async function showModalAndWait(type, data) {
})
}
const labelButton3 = modal.querySelector('#transactionsButtonLabel')
if (labelButton3) {
labelButton3.addEventListener('click', () => {
this.shadowRoot.getElementById('transactionsButton').click()
})
}
const checkbox3 = modal.querySelector('#transactionsButton')
if (checkbox3) {
checkbox3.addEventListener('click', (e) => {
if (e.target.checked) {
window.parent.reduxStore.dispatch(window.parent.reduxAction.removeQAPPAutoTransacions(false))
return
}
window.parent.reduxStore.dispatch(window.parent.reduxAction.allowQAPPAutoTransacions(true))
})
}
const labelButtonFriendsList = modal.querySelector('#friendsListLabel')
if (labelButtonFriendsList) {
labelButtonFriendsList.addEventListener('click', () => {
@ -5313,6 +5564,35 @@ async function showModalAndWait(type, data) {
})
}
function convertJson(jsonStr) {
let regeStr = ''
let f = {
brace: 0
}
regeStr = jsonStr.replace(/({|}[,]*|[^{}:]+:[^{}:,]*[,{]*)/g, function (m, p1) {
const rtnFn = function() {
return '<div style="text-indent: ' + (f['brace'] * 20) + 'px;color: var(--black);">' + p1 + '</div>'
}
let rtnStr = 0
if (p1.lastIndexOf('{') === (p1.length - 1)) {
rtnStr = rtnFn()
f['brace'] += 1
} else if (p1.indexOf('}') === 0) {
f['brace'] -= 1
rtnStr = rtnFn()
} else {
rtnStr = rtnFn()
}
return rtnStr
})
return regeStr
}
async function showErrorAndWait(type, data) {
// Create the modal and add it to the DOM
const modalDelay = ms => new Promise(res => setTimeout(res, ms))

View File

@ -13,6 +13,7 @@ import '@vaadin/grid'
// Multi language support
import { get, registerTranslateConfig, translate, use } from '../../../../core/translate'
registerTranslateConfig({
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
})
@ -346,7 +347,7 @@ class RewardShare extends LitElement {
getTxnRequestResponse(myTransaction)
}
} else if (accountDetails.address === recipientAddress) {
if (accountDetails.level >= 1 && accountDetails.level <= 4) {
if (accountDetails.level <= 4) {
this.error = false
this.message = ''
let myTransaction = await makeTransactionRequest(lastRef)
@ -361,7 +362,6 @@ class RewardShare extends LitElement {
getTxnRequestResponse(myTransaction)
}
} else if (accountDetails.level >= 5) {
this.error = false
this.message = ''
let myTransaction = await makeTransactionRequest(lastRef)
@ -504,7 +504,7 @@ class RewardShare extends LitElement {
getTxnRequestResponse(myTransaction)
}
} else if (accountDetails.address === recipientAddress) {
if (accountDetails.level >= 1 && accountDetails.level <= 4) {
if (accountDetails.level <= 4) {
this.error = false
this.message = ''
let myTransaction = await makeTransactionRequest(lastRef)
@ -519,7 +519,6 @@ class RewardShare extends LitElement {
getTxnRequestResponse(myTransaction)
}
} else if (accountDetails.level >= 5) {
this.error = false
this.message = ''
let myTransaction = await makeTransactionRequest(lastRef)
@ -680,4 +679,4 @@ class RewardShare extends LitElement {
}
}
window.customElements.define('reward-share', RewardShare)
window.customElements.define('reward-share', RewardShare)

View File

@ -136,9 +136,10 @@ function attemptReconnectNodeStatusSocket() {
const initBlockSocket = () => {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let nodeProtocol = myNode.protocol
let activeBlockSocketLink
if (window.parent.location.protocol === "https:") {
if (nodeProtocol === "https") {
activeBlockSocketLink = `wss://${nodeUrl}/websockets/blocks`
} else {
activeBlockSocketLink = `ws://${nodeUrl}/websockets/blocks`
@ -205,9 +206,10 @@ const pingactiveBlockSocket = () => {
const initNodeStatusSocket = () => {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let nodeProtocol = myNode.protocol
let activeNodeStatusSocketLink
if (window.parent.location.protocol === "https:") {
if (nodeProtocol === "https") {
activeNodeStatusSocketLink = `wss://${nodeUrl}/websockets/admin/status`
} else {
activeNodeStatusSocketLink = `ws://${nodeUrl}/websockets/admin/status`

View File

@ -112,9 +112,10 @@ parentEpml.subscribe('logged_in', async isLoggedIn => {
const initChatHeadSocket = () => {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ":" + myNode.port
let nodeProtocol = myNode.protocol
let activeChatSocketLink
if (window.parent.location.protocol === "https:") {
if (nodeProtocol === "https") {
activeChatSocketLink = `wss://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`
} else {
activeChatSocketLink = `ws://${nodeUrl}/websockets/chat/active/${window.parent.reduxStore.getState().app.selectedAddress.address}?encoding=BASE64`

View File

@ -2882,7 +2882,7 @@ class TradeBotPortal extends LitElement {
const initTradeOffersWebSocket = (restarted = false) => {
let tradeOffersSocketCounter = 0
let socketTimeout
let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true`
let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true`
const socket = new WebSocket(socketLink)
socket.onopen = () => {
setTimeout(pingSocket, 50)
@ -2914,7 +2914,7 @@ class TradeBotPortal extends LitElement {
const initTradeBotWebSocket = (restarted = false) => {
let socketTimeout
let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN`
let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN`
const socket = new WebSocket(socketLink)
socket.onopen = () => {
setTimeout(pingSocket, 50)
@ -2943,7 +2943,7 @@ class TradeBotPortal extends LitElement {
const initTradePresenceWebSocket = (restarted = false) => {
let socketTimeout
let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence`
let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradepresence`
const socket = new WebSocket(socketLink)
socket.onopen = () => {
setTimeout(pingSocket, 50)
@ -3289,10 +3289,19 @@ class TradeBotPortal extends LitElement {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ':' + myNode.port
let nodeProtocol = myNode.protocol
let checkProtocol
if (nodeProtocol === "https") {
checkProtocol = 'wss'
} else {
checkProtocol = 'ws'
}
const modifiers = [
{ searchValue: 'PROTOCOL', replaceValue: checkProtocol },
{ searchValue: 'NODEURL', replaceValue: nodeUrl },
{ searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin },
{ searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }
]
workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers)

View File

@ -2181,7 +2181,7 @@ class TradePortal extends LitElement {
const initTradeOffersWebSocket = (restarted = false) => {
let tradeOffersSocketCounter = 0
let socketTimeout
let socketLink = `ws://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true`
let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN&includeHistoric=true`
const socket = new WebSocket(socketLink)
socket.onopen = () => {
setTimeout(pingSocket, 50)
@ -2213,7 +2213,7 @@ class TradePortal extends LitElement {
const initTradeBotWebSocket = (restarted = false) => {
let socketTimeout
let socketLink = `ws://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN`
let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradebot?foreignBlockchain=FOREIGN_BLOCKCHAIN`
const socket = new WebSocket(socketLink)
socket.onopen = () => {
setTimeout(pingSocket, 50)
@ -2242,7 +2242,7 @@ class TradePortal extends LitElement {
const initTradePresenceWebSocket = (restarted = false) => {
let socketTimeout
let socketLink = `ws://NODEURL/websockets/crosschain/tradepresence`
let socketLink = `PROTOCOL://NODEURL/websockets/crosschain/tradepresence`
const socket = new WebSocket(socketLink)
socket.onopen = () => {
setTimeout(pingSocket, 50)
@ -2726,10 +2726,19 @@ class TradePortal extends LitElement {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ':' + myNode.port
let nodeProtocol = myNode.protocol
let checkProtocol
if (nodeProtocol === "https") {
checkProtocol = 'wss'
} else {
checkProtocol = 'ws'
}
const modifiers = [
{ searchValue: 'PROTOCOL', replaceValue: checkProtocol },
{ searchValue: 'NODEURL', replaceValue: nodeUrl },
{ searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin },
{ searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin }
]
workers.get(this.selectedCoin).tradesConnectedWorker = this.inlineWorker(this.initSocket, modifiers)
@ -2791,7 +2800,7 @@ class TradePortal extends LitElement {
})
const getCompletedTrades = async () => {
const url = `http://NODEURL/crosschain/trades?limit=25&reverse=true&foreignBlockchain=FOREIGN_BLOCKCHAIN`
const url = `PROTOCOL://NODEURL/crosschain/trades?limit=25&reverse=true&foreignBlockchain=FOREIGN_BLOCKCHAIN`
const res = await fetch(url)
const historicTrades = await res.json()
const compareFn = (a, b) => {
@ -2810,7 +2819,7 @@ class TradePortal extends LitElement {
}
const getOffers = async () => {
const url = `http://NODEURL/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN`
const url = `PROTOCOL://NODEURL/crosschain/tradeoffers?foreignBlockchain=FOREIGN_BLOCKCHAIN`
const res = await fetch(url)
const openTradeOrders = await res.json()
const myOpenTradeOrders = await openTradeOrders.filter((order) => order.mode === 'OFFERING' && order.qortalCreator === 'SELECTED_ADDRESS')
@ -2872,11 +2881,20 @@ class TradePortal extends LitElement {
let myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
let nodeUrl = myNode.domain + ':' + myNode.port
let nodeProtocol = myNode.protocol
let checkProtocol
if (nodeProtocol === "https") {
checkProtocol = 'https'
} else {
checkProtocol = 'http'
}
const modifiers = [
{ searchValue: 'PROTOCOL', replaceValue: checkProtocol },
{ searchValue: 'NODEURL', replaceValue: nodeUrl },
{ searchValue: 'SELECTED_ADDRESS', replaceValue: this.selectedAddress.address, },
{ searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin, },
{ searchValue: 'SELECTED_ADDRESS', replaceValue: this.selectedAddress.address },
{ searchValue: 'FOREIGN_BLOCKCHAIN', replaceValue: this.selectedCoin, }
]
workers.get(this.selectedCoin).handleStuckTradesConnectedWorker = this.inlineWorker(this.handleStuckTrades, modifiers)

View File

@ -1552,3 +1552,99 @@ export const cancelTradeOfferTradeBot = async (body, keyPair) => {
throw new Error("Failed to Cancel Sell Order. Try again!")
}
}
export const getArrrSyncStatus = async () => {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = `${myNode.protocol}://${myNode.domain}:${myNode.port}`
const myApiKey = myNode.apiKey
const url = `${nodeUrl}/crosschain/arrr/syncstatus?apiKey=${myApiKey}`
const arrrSeed = window.parent.reduxStore.getState().app.selectedAddress.arrrWallet.seed58
try {
const response = await fetch(url, {
method: "POST",
headers: {
Accept: "*/*"
},
body: arrrSeed
})
let res
try {
res = await response.clone().json()
} catch (e) {
res = await response.text()
}
return res
} catch (error) {
console.error(error.message || "Error in retrieving arrr sync status")
}
}
export const getNodeInfo = async () => {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = `${myNode.protocol}://${myNode.domain}:${myNode.port}`
const url = `${nodeUrl}/admin/info`
try {
const response = await fetch(url, {
method: "GET",
headers: {
Accept: "*/*"
}
})
if (!response.ok) console.error("Failed to retrieve node info")
let res
try {
res = await response.clone().json()
} catch (e) {
res = await response.text()
}
if (res.error && res.message) {
console.error(res.message)
}
return res
} catch (error) {
console.error(error.message || "Error in retrieving node info")
}
}
export const getNodeStatus = async () => {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
const nodeUrl = `${myNode.protocol}://${myNode.domain}:${myNode.port}`
const url = `${nodeUrl}/admin/status`
try {
const response = await fetch(url, {
method: "GET",
headers: {
Accept: "*/*"
}
})
if (!response.ok) console.error("Failed to retrieve node status")
let res
try {
res = await response.clone().json()
} catch (e) {
res = await response.text()
}
if (res.error && res.message) {
console.error(res.message)
}
return res
} catch (error) {
console.error(error.message || "Error in retrieving node status")
}
}