@abtnode/ux 1.16.29-beta-44e63d18 → 1.16.29-beta-0c32fe15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/blocklet/overview.js +25 -7
- package/lib/blocklet/publish/create-release/connect-store-button.js +1 -1
- package/lib/blocklet/publish/create-release/header.js +1 -1
- package/lib/blocklet/publish/utils/wait-connect.js +1 -1
- package/lib/hooks/use-promise-window-open.js +15 -3
- package/lib/locales/ar.js +5 -2
- package/lib/locales/de.js +5 -2
- package/lib/locales/en.js +3 -0
- package/lib/locales/es.js +5 -2
- package/lib/locales/fr.js +5 -2
- package/lib/locales/hi.js +5 -2
- package/lib/locales/i18n.db +0 -0
- package/lib/locales/id.js +5 -2
- package/lib/locales/ja.js +5 -2
- package/lib/locales/ko.js +5 -2
- package/lib/locales/pt.js +5 -2
- package/lib/locales/ru.js +5 -2
- package/lib/locales/th.js +5 -2
- package/lib/locales/vi.js +5 -2
- package/lib/locales/zh-tw.js +5 -2
- package/lib/locales/zh.js +4 -1
- package/lib/store/connect-actions.js +11 -6
- package/lib/store/developer-avatar.js +27 -0
- package/lib/store/item.js +50 -23
- package/lib/team/members/invite-member.js +10 -6
- package/package.json +11 -11
package/lib/blocklet/overview.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import Button from '@arcblock/ux/lib/Button';
|
|
2
1
|
import styled from '@emotion/styled';
|
|
3
2
|
import React, { useState } from 'react';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
3
|
+
import { Box, Tooltip, Typography } from '@mui/material';
|
|
4
|
+
import { Icon } from '@iconify/react';
|
|
5
|
+
import QuestionMarkRoundedIcon from '@iconify-icons/material-symbols/question-mark-rounded';
|
|
6
|
+
import KeyboardArrowDownRoundedIcon from '@iconify-icons/material-symbols/keyboard-arrow-down-rounded';
|
|
7
|
+
import KeyboardArrowUpRoundedIcon from '@iconify-icons/material-symbols/keyboard-arrow-up-rounded';
|
|
8
|
+
import Button from '@arcblock/ux/lib/Button';
|
|
6
9
|
import InfoRow from '@arcblock/ux/lib/InfoRow';
|
|
7
10
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
8
11
|
import Tag from '@arcblock/ux/lib/Tag';
|
|
9
12
|
import { getDisplayName, getWhoCanAccess } from '@blocklet/meta/lib/util';
|
|
10
|
-
import Typography from '@mui/material/Typography';
|
|
11
13
|
import { useBlockletContext } from '../contexts/blocklet';
|
|
12
14
|
import { useNodeContext } from '../contexts/node';
|
|
13
15
|
import DidAddress from '../did-address';
|
|
@@ -45,8 +47,20 @@ export default function BlockletOverview() {
|
|
|
45
47
|
did: appDid,
|
|
46
48
|
showQrcode: true
|
|
47
49
|
})
|
|
48
|
-
} : null, appPid ? {
|
|
49
|
-
name:
|
|
50
|
+
} : null, appPid && appDid !== appPid ? {
|
|
51
|
+
name: /*#__PURE__*/_jsxs(Box, {
|
|
52
|
+
sx: {
|
|
53
|
+
display: 'flex',
|
|
54
|
+
alignItems: 'center',
|
|
55
|
+
gap: 1
|
|
56
|
+
},
|
|
57
|
+
children: [t('blocklet.appPid'), /*#__PURE__*/_jsx(Tooltip, {
|
|
58
|
+
title: t('blocklet.whyNeedAppPid'),
|
|
59
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
60
|
+
icon: QuestionMarkRoundedIcon
|
|
61
|
+
})
|
|
62
|
+
})]
|
|
63
|
+
}),
|
|
50
64
|
value: /*#__PURE__*/_jsx(DidAddress, {
|
|
51
65
|
did: appPid,
|
|
52
66
|
showQrcode: true
|
|
@@ -61,7 +75,11 @@ export default function BlockletOverview() {
|
|
|
61
75
|
style: {
|
|
62
76
|
marginLeft: '18px'
|
|
63
77
|
},
|
|
64
|
-
endIcon: showAllDIDs ? /*#__PURE__*/_jsx(
|
|
78
|
+
endIcon: showAllDIDs ? /*#__PURE__*/_jsx(Icon, {
|
|
79
|
+
icon: KeyboardArrowUpRoundedIcon
|
|
80
|
+
}) : /*#__PURE__*/_jsx(Icon, {
|
|
81
|
+
icon: KeyboardArrowDownRoundedIcon
|
|
82
|
+
}),
|
|
65
83
|
onClick: () => setShowAllDIDs(!showAllDIDs),
|
|
66
84
|
children: showAllDIDs ? t('common.collapseAll') : t('blocklet.router.showAllDIDs')
|
|
67
85
|
})]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
async function waitPromiseFunction(promiseFunction, interval =
|
|
1
|
+
async function waitPromiseFunction(promiseFunction, interval = 1000, maxAttempts = 300, intervalFirst = 4000) {
|
|
2
2
|
let attempts = 0;
|
|
3
3
|
|
|
4
4
|
// eslint-disable-next-line no-promise-executor-return
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { WELLKNOWN_SERVICE_PATH_PREFIX } from '@abtnode/constant';
|
|
1
2
|
import { useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
// `${WELLKNOWN_SERVICE_PATH_PREFIX}/open-window`
|
|
5
|
+
|
|
2
6
|
function usePromiseWindowOpen({
|
|
3
7
|
onOpen,
|
|
4
8
|
onClose
|
|
@@ -10,17 +14,25 @@ function usePromiseWindowOpen({
|
|
|
10
14
|
clearInterval(timer.current);
|
|
11
15
|
windowRef.current.close();
|
|
12
16
|
}
|
|
13
|
-
|
|
17
|
+
const key = Math.random().toString(36).slice(2);
|
|
18
|
+
windowRef.current = window.open(`${WELLKNOWN_SERVICE_PATH_PREFIX}/open-window?key=${key}`, '_blank');
|
|
14
19
|
onOpen?.(windowRef.current);
|
|
15
20
|
timer.current = setInterval(() => {
|
|
16
21
|
if (!windowRef.current || windowRef.current.closed) {
|
|
17
22
|
windowRef.current = null;
|
|
18
23
|
clearInterval(timer.current);
|
|
19
|
-
|
|
24
|
+
// close 之前, 需要多等待一次 project-id 的轮询
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
onClose?.();
|
|
27
|
+
}, 1100);
|
|
20
28
|
}
|
|
21
|
-
},
|
|
29
|
+
}, 200);
|
|
22
30
|
await Promise.resolve(fn(windowRef.current, url => {
|
|
23
31
|
if (!windowRef.current) {
|
|
32
|
+
localStorage.setItem(`open-window-url-${key}`, JSON.stringify({
|
|
33
|
+
url,
|
|
34
|
+
time: Date.now()
|
|
35
|
+
}));
|
|
24
36
|
return;
|
|
25
37
|
}
|
|
26
38
|
windowRef.current.location.href = url;
|
package/lib/locales/ar.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'اختر موردًا من Blocklets',
|
|
737
737
|
resourceUpload: 'تحميل المورد من القرص الخاص بك (الفهرس.html مطلوب في الأرشيف)',
|
|
738
738
|
deleteStoreTip: 'هل أنت متأكد أنك تريد إزالة {name} من قائمة متجر الاتصال؟',
|
|
739
|
-
disconnectStoreTip: 'سيتم حذف بلوكليت من المخزن بعد الفصل. هل أنت متأكد من أنك تريد الفصل؟'
|
|
739
|
+
disconnectStoreTip: 'سيتم حذف بلوكليت من المخزن بعد الفصل. هل أنت متأكد من أنك تريد الفصل؟',
|
|
740
|
+
connectOrUpload: 'الاتصال أو التحميل',
|
|
741
|
+
developerInfo: 'معلومات المطور'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'يجب أن يكون طول العنوان على الأقل 3 أحرف',
|
|
742
|
-
descriptionValidationError: 'يجب أن تكون طول الوصف بين 3 و 160 حرفًا'
|
|
744
|
+
descriptionValidationError: 'يجب أن تكون طول الوصف بين 3 و 160 حرفًا',
|
|
745
|
+
whyNeedAppPid: 'إذا تم نقل تطبيقك، فإن DID الدائم هو DID الذي تم إنشاؤه عند تثبيت Blocklet هذا في الأصل.'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'عقدة',
|
package/lib/locales/de.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Wählen Sie eine Ressource aus Blocklets',
|
|
737
737
|
resourceUpload: 'Ressource von Ihrer Festplatte hochladen (index.html ist im Archiv erforderlich)',
|
|
738
738
|
deleteStoreTip: 'Möchten Sie {name} wirklich aus der Verbindungsliste des Stores entfernen?',
|
|
739
|
-
disconnectStoreTip: 'Das Blocklet wird nach dem Trennen aus dem Store entfernt. Möchten Sie wirklich trennen?'
|
|
739
|
+
disconnectStoreTip: 'Das Blocklet wird nach dem Trennen aus dem Store entfernt. Möchten Sie wirklich trennen?',
|
|
740
|
+
connectOrUpload: 'Verbinden oder Hochladen',
|
|
741
|
+
developerInfo: 'Entwicklerinformation'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'Die Länge des Titels muss mindestens 3 Zeichen betragen',
|
|
742
|
-
descriptionValidationError: 'Die Beschreibungslänge muss zwischen 3 und 160 Zeichen liegen'
|
|
744
|
+
descriptionValidationError: 'Die Beschreibungslänge muss zwischen 3 und 160 Zeichen liegen',
|
|
745
|
+
whyNeedAppPid: 'Wenn Ihre Anwendung migriert wurde, ist die permanente DID die DID, die bei der ursprünglichen Installation dieses Blocklets generiert wurde.'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Knoten',
|
package/lib/locales/en.js
CHANGED
|
@@ -372,6 +372,7 @@ export default {
|
|
|
372
372
|
noService: 'No Services',
|
|
373
373
|
appId: 'App DID',
|
|
374
374
|
appPid: 'Permanent DID',
|
|
375
|
+
whyNeedAppPid: 'If your application has been migrated, the permanent DID is the DID generated when this Blocklet was originally installed',
|
|
375
376
|
alsoKnownAs: 'Also Known As',
|
|
376
377
|
skSource: 'Owner Wallet',
|
|
377
378
|
reloadSuccess: 'Blocklet was reloaded successfully',
|
|
@@ -658,6 +659,8 @@ export default {
|
|
|
658
659
|
isInProgress: 'Blocklet is in progress, please wait for it to finish'
|
|
659
660
|
},
|
|
660
661
|
publish: {
|
|
662
|
+
connectOrUpload: 'Connect or Upload',
|
|
663
|
+
developerInfo: 'Developer Information',
|
|
661
664
|
branding: 'Branding',
|
|
662
665
|
brandingHelp: 'More information about the blocklet will be displayed in the Store',
|
|
663
666
|
download: 'Download {name}',
|
package/lib/locales/es.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Seleccionar recurso de blocklets',
|
|
737
737
|
resourceUpload: 'Cargar recurso desde tu disco (index.html es requerido en el archivo)',
|
|
738
738
|
deleteStoreTip: '¿Estás seguro de que quieres eliminar a {name} de la lista de la tienda Connect?',
|
|
739
|
-
disconnectStoreTip: 'Después de la desconexión, se eliminará el blocklet de la tienda. ¿Seguro que desea desconectar?'
|
|
739
|
+
disconnectStoreTip: 'Después de la desconexión, se eliminará el blocklet de la tienda. ¿Seguro que desea desconectar?',
|
|
740
|
+
connectOrUpload: 'Conectar o Subir',
|
|
741
|
+
developerInfo: 'Información del desarrollador'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'La longitud del título debe ser de al menos 3 caracteres',
|
|
742
|
-
descriptionValidationError: 'La longitud de la descripción debe estar entre 3 y 160 caracteres'
|
|
744
|
+
descriptionValidationError: 'La longitud de la descripción debe estar entre 3 y 160 caracteres',
|
|
745
|
+
whyNeedAppPid: 'Si se ha migrado su aplicación, el DID permanente es el DID generado cuando este Blocklet se instaló originalmente.'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Nodo',
|
package/lib/locales/fr.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Sélectionnez une ressource des blocklets',
|
|
737
737
|
resourceUpload: "Téléchargez la ressource depuis votre disque (index.html est requis dans l'archive)",
|
|
738
738
|
deleteStoreTip: 'Êtes-vous sûr de vouloir supprimer {name} de la liste du magasin Connect?',
|
|
739
|
-
disconnectStoreTip: 'Le bloclet sera supprimé du store après sa déconnexion. Êtes-vous sûr de vouloir le déconnecter ?'
|
|
739
|
+
disconnectStoreTip: 'Le bloclet sera supprimé du store après sa déconnexion. Êtes-vous sûr de vouloir le déconnecter ?',
|
|
740
|
+
connectOrUpload: 'Connecter ou Télécharger',
|
|
741
|
+
developerInfo: 'Informations sur le développeur'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: "La longueur du titre doit être d'au moins 3 caractères",
|
|
742
|
-
descriptionValidationError: 'La longueur de la description doit être comprise entre 3 et 160 caractères'
|
|
744
|
+
descriptionValidationError: 'La longueur de la description doit être comprise entre 3 et 160 caractères',
|
|
745
|
+
whyNeedAppPid: "Si votre application a été migrée, le DID permanent est le DID généré lors de l'installation initiale de ce Blocklet."
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Noeud',
|
package/lib/locales/hi.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'ब्लॉकलेट से संसाधन का चयन करें',
|
|
737
737
|
resourceUpload: 'अपनी डिस्क से संसाधन अपलोड करें (संग्रह में index.html आवश्यक है)',
|
|
738
738
|
deleteStoreTip: 'क्या आप वाकई {name} को कनेक्ट स्टोर से हटाना चाहते हैं?',
|
|
739
|
-
disconnectStoreTip: 'ब्लॉकलेट को डिस्कनेक्ट करने के बाद उसे स्टोर से हटा दिया जाएगा। क्या आप वाकई में उसे डिस्कनेक्ट करना चाहते हैं?'
|
|
739
|
+
disconnectStoreTip: 'ब्लॉकलेट को डिस्कनेक्ट करने के बाद उसे स्टोर से हटा दिया जाएगा। क्या आप वाकई में उसे डिस्कनेक्ट करना चाहते हैं?',
|
|
740
|
+
connectOrUpload: 'कनेक्ट करें या अपलोड करें',
|
|
741
|
+
developerInfo: 'डेवलपर सूचना'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'शीर्षक की लंबाई कम से कम 3 अक्षर होनी चाहिए',
|
|
742
|
-
descriptionValidationError: 'विवरण की लंबाई 3 और 160 वर्णों के बीच होनी चाहिए'
|
|
744
|
+
descriptionValidationError: 'विवरण की लंबाई 3 और 160 वर्णों के बीच होनी चाहिए',
|
|
745
|
+
whyNeedAppPid: 'अगर आपका एप्लीकेशन माइग्रेट कर दिया गया है, तो परमानेंट DID वही DID है जो उस समय जनरेट की गई थी जब पहली बार यह ब्लॉकलेट इंस्टॉल किया गया था।'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'नोड',
|
package/lib/locales/i18n.db
CHANGED
|
Binary file
|
package/lib/locales/id.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Pilih sumber dari blocklets',
|
|
737
737
|
resourceUpload: 'Unggah sumber daya dari disk Anda (index.html diperlukan dalam arsip)',
|
|
738
738
|
deleteStoreTip: 'Apakah Anda yakin ingin menghapus {name} dari daftar Toko Koneksi?',
|
|
739
|
-
disconnectStoreTip: 'Setelah terputus, blocklet akan dihapus dari toko. Apa Anda yakin untuk memutuskan?'
|
|
739
|
+
disconnectStoreTip: 'Setelah terputus, blocklet akan dihapus dari toko. Apa Anda yakin untuk memutuskan?',
|
|
740
|
+
connectOrUpload: 'Hubungkan atau Unggah',
|
|
741
|
+
developerInfo: 'Informasi Pengembang'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'Panjang judul harus setidaknya 3 karakter',
|
|
742
|
-
descriptionValidationError: 'Panjang deskripsi harus antara 3 dan 160 karakter.'
|
|
744
|
+
descriptionValidationError: 'Panjang deskripsi harus antara 3 dan 160 karakter.',
|
|
745
|
+
whyNeedAppPid: 'Jika aplikasi Anda telah dimigrasikan, DID permanen adalah DID yang dihasilkan saat Blocklet ini pertama kali dipasang'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Node',
|
package/lib/locales/ja.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'ブロックレットからリソースを選択する',
|
|
737
737
|
resourceUpload: 'ディスクからリソースをアップロードします(アーカイブにindex.htmlが必要です)',
|
|
738
738
|
deleteStoreTip: '{name}を接続ストアリストから削除してもよろしいですか?',
|
|
739
|
-
disconnectStoreTip: 'ブロックレットの接続を解除すると、ブロックレットはストアから削除されます。接続を解除してもよろしいですか?'
|
|
739
|
+
disconnectStoreTip: 'ブロックレットの接続を解除すると、ブロックレットはストアから削除されます。接続を解除してもよろしいですか?',
|
|
740
|
+
connectOrUpload: '接続またはアップロード',
|
|
741
|
+
developerInfo: '開発者情報'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'タイトルの長さは最低3文字以上である必要があります',
|
|
742
|
-
descriptionValidationError: '説明の長さは3から160文字の間でなければなりません'
|
|
744
|
+
descriptionValidationError: '説明の長さは3から160文字の間でなければなりません',
|
|
745
|
+
whyNeedAppPid: 'アプリケーションが移行されている場合、永続的な DID はこの Blocklet が最初にインストールされたときに生成された DID です。'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'ノード',
|
package/lib/locales/ko.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: '블록릿에서 리소스 선택',
|
|
737
737
|
resourceUpload: '디스크에서 리소스를 업로드하세요 (아카이브에 index.html이 필요합니다)',
|
|
738
738
|
deleteStoreTip: '{name}을(를) 연결 스토어 목록에서 제거하시겠습니까?',
|
|
739
|
-
disconnectStoreTip: '연결이 끊어지면 Blocklet이 스토어에서 제거됩니다. 연결을 끊으시겠습니까?'
|
|
739
|
+
disconnectStoreTip: '연결이 끊어지면 Blocklet이 스토어에서 제거됩니다. 연결을 끊으시겠습니까?',
|
|
740
|
+
connectOrUpload: '연결하거나 업로드',
|
|
741
|
+
developerInfo: '개발자 정보'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: '제목 길이는 최소 3자 이상이어야 합니다',
|
|
742
|
-
descriptionValidationError: '설명 길이는 3에서 160자 사이여야 합니다'
|
|
744
|
+
descriptionValidationError: '설명 길이는 3에서 160자 사이여야 합니다',
|
|
745
|
+
whyNeedAppPid: '애플리케이션이 마이그레이션된 경우 영구 DID는 이 Blocklet이 처음 설치되었을 때 생성된 DID입니다.'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: '노드',
|
package/lib/locales/pt.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Selecionar recurso dos blocos',
|
|
737
737
|
resourceUpload: 'Carregar recurso do seu disco (index.html é necessário no arquivo)',
|
|
738
738
|
deleteStoreTip: 'Tem certeza de que deseja remover {name} da lista da Loja de Conexão?',
|
|
739
|
-
disconnectStoreTip: 'Após desconectado, o Blocklet será removido da loja. Você tem certeza que deseja desconectar?'
|
|
739
|
+
disconnectStoreTip: 'Após desconectado, o Blocklet será removido da loja. Você tem certeza que deseja desconectar?',
|
|
740
|
+
connectOrUpload: 'Conectar ou Enviar',
|
|
741
|
+
developerInfo: 'Informações do Desenvolvedor'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'O comprimento do título deve ter pelo menos 3 caracteres',
|
|
742
|
-
descriptionValidationError: 'O comprimento da descrição deve estar entre 3 e 160 caracteres.'
|
|
744
|
+
descriptionValidationError: 'O comprimento da descrição deve estar entre 3 e 160 caracteres.',
|
|
745
|
+
whyNeedAppPid: 'Se o seu aplicativo foi migrado, o DID permanente é o DID gerado quando este Blocklet foi instalado originalmente'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Nó',
|
package/lib/locales/ru.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Выберите ресурс из блоклетов',
|
|
737
737
|
resourceUpload: 'Загрузите ресурс с вашего диска (в архиве требуется index.html)',
|
|
738
738
|
deleteStoreTip: 'Вы уверены, что хотите удалить {name} из списка магазина Connect?',
|
|
739
|
-
disconnectStoreTip: 'Блоклет будет удален из магазина после отключения. Уверены, что хотите отключить?'
|
|
739
|
+
disconnectStoreTip: 'Блоклет будет удален из магазина после отключения. Уверены, что хотите отключить?',
|
|
740
|
+
connectOrUpload: 'Подключиться или Загрузить',
|
|
741
|
+
developerInfo: 'Информация для разработчиков'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'Длина заголовка должна быть не менее 3 символов',
|
|
742
|
-
descriptionValidationError: 'Длина описания должна быть от 3 до 160 символов'
|
|
744
|
+
descriptionValidationError: 'Длина описания должна быть от 3 до 160 символов',
|
|
745
|
+
whyNeedAppPid: 'Если ваше приложение перенесено, постоянный DID — это DID, созданный при первоначальной установке этого Blocklet.'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Узел',
|
package/lib/locales/th.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'เลือกทรัพยากรจากบล็อกเล็ต',
|
|
737
737
|
resourceUpload: 'อัปโหลดทรัพยากรจากดิสก์ของคุณ (index.html จำเป็นในไฟล์เข้าเก็บ)',
|
|
738
738
|
deleteStoreTip: 'คุณแน่ใจหรือว่าต้องการลบ {name} ออกจากรายการร้านค้าเชื่อมต่อหรือไม่?',
|
|
739
|
-
disconnectStoreTip: 'เมื่อยกเลิกการเชื่อมต่อแล้ว Blocklet จะถูกลบออกจากร้าน คุณแน่ใจไหมว่าต้องการยกเลิกการเชื่อมต่อหรือไม่'
|
|
739
|
+
disconnectStoreTip: 'เมื่อยกเลิกการเชื่อมต่อแล้ว Blocklet จะถูกลบออกจากร้าน คุณแน่ใจไหมว่าต้องการยกเลิกการเชื่อมต่อหรือไม่',
|
|
740
|
+
connectOrUpload: 'เชื่อมต่อหรืออัปโหลด',
|
|
741
|
+
developerInfo: 'ข้อมูลนักพัฒนา'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'ความยาวของชื่อต้องมีอย่างน้อย 3 ตัวอักษร',
|
|
742
|
-
descriptionValidationError: 'ความยาวคำอธิบายต้องอยู่ระหว่าง 3 ถึง 160 ตัวอักษร.'
|
|
744
|
+
descriptionValidationError: 'ความยาวคำอธิบายต้องอยู่ระหว่าง 3 ถึง 160 ตัวอักษร.',
|
|
745
|
+
whyNeedAppPid: 'หากแอปพลิเคชันของคุณได้รับการโยกย้ายมา DID ถาวรคือ DID ที่สร้างขึ้นเมื่อติดตั้ง Blocklet นี้เริ่มแรก'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'โหนด',
|
package/lib/locales/vi.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: 'Chọn tài nguyên từ blocklets',
|
|
737
737
|
resourceUpload: 'Tải tài nguyên từ ổ đĩa của bạn (index.html cần thiết trong tệp nén)',
|
|
738
738
|
deleteStoreTip: 'Bạn có chắc chắn muốn xóa {name} khỏi danh sách Cửa hàng Kết nối không?',
|
|
739
|
-
disconnectStoreTip: 'Sau khi ngắt kết nối, Blocklet sẽ bị xóa khỏi cửa hàng. Bạn có chắc chắn muốn ngắt kết nối không?'
|
|
739
|
+
disconnectStoreTip: 'Sau khi ngắt kết nối, Blocklet sẽ bị xóa khỏi cửa hàng. Bạn có chắc chắn muốn ngắt kết nối không?',
|
|
740
|
+
connectOrUpload: 'Kết nối hoặc Tải lên',
|
|
741
|
+
developerInfo: 'Thông tin nhà phát triển'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: 'Độ dài tiêu đề phải ít nhất 3 ký tự',
|
|
742
|
-
descriptionValidationError: 'Chiều dài mô tả phải từ 3 đến 160 ký tự.'
|
|
744
|
+
descriptionValidationError: 'Chiều dài mô tả phải từ 3 đến 160 ký tự.',
|
|
745
|
+
whyNeedAppPid: 'Nếu ứng dụng của bạn đã được di chuyển, DID vĩnh viễn là DID được tạo khi Blocklet này được cài đặt ban đầu'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: 'Nút',
|
package/lib/locales/zh-tw.js
CHANGED
|
@@ -736,10 +736,13 @@ export default {
|
|
|
736
736
|
resourceSelect: '從 blocklets 選擇資源',
|
|
737
737
|
resourceUpload: '從您的磁盤上傳資源(存檔中需要index.html)',
|
|
738
738
|
deleteStoreTip: '您確定要將{name}從連接商店列表中移除嗎?',
|
|
739
|
-
disconnectStoreTip: '斷開連線後,blocklet 將從商店中移除。您確定要斷開連線嗎?'
|
|
739
|
+
disconnectStoreTip: '斷開連線後,blocklet 將從商店中移除。您確定要斷開連線嗎?',
|
|
740
|
+
connectOrUpload: '連接或上傳',
|
|
741
|
+
developerInfo: '開發者資訊'
|
|
740
742
|
},
|
|
741
743
|
titleValidationError: '標題長度必須至少為3到40個字符',
|
|
742
|
-
descriptionValidationError: '描述長度必須介於3到160個字符之間'
|
|
744
|
+
descriptionValidationError: '描述長度必須介於3到160個字符之間',
|
|
745
|
+
whyNeedAppPid: '如果已遷移您的應用程式,永久 DID 是最初安裝此 Blocklet 時產生的 DID。'
|
|
743
746
|
},
|
|
744
747
|
dashboard: {
|
|
745
748
|
nodeDid: '節點',
|
package/lib/locales/zh.js
CHANGED
|
@@ -370,6 +370,7 @@ export default {
|
|
|
370
370
|
noService: '暂无服务',
|
|
371
371
|
appId: '应用 DID',
|
|
372
372
|
appPid: '永久性 DID',
|
|
373
|
+
whyNeedAppPid: '如果你的应用曾经迁移过,永久性 DID 是最初安装这个 Blocklet 时产生的 DID',
|
|
373
374
|
alsoKnownAs: '曾用 DID',
|
|
374
375
|
skSource: '安装钱包',
|
|
375
376
|
reloadSuccess: '应用重启成功',
|
|
@@ -736,7 +737,9 @@ export default {
|
|
|
736
737
|
resourceSelect: '从 blocklets 选择资源',
|
|
737
738
|
resourceUpload: '从您的磁盘上传资源(存档中需要index.html)',
|
|
738
739
|
deleteStoreTip: '您确定要将{name}从连接商店列表中移除吗?',
|
|
739
|
-
disconnectStoreTip: '断开连接后,blocklet 将从商店中移除。您确定要断开连接吗?'
|
|
740
|
+
disconnectStoreTip: '断开连接后,blocklet 将从商店中移除。您确定要断开连接吗?',
|
|
741
|
+
connectOrUpload: '连接或上传',
|
|
742
|
+
developerInfo: '开发者信息'
|
|
740
743
|
},
|
|
741
744
|
titleValidationError: '标题长度必须至少为3到40个字符',
|
|
742
745
|
descriptionValidationError: '描述长度必须在3到160个字符之间'
|
|
@@ -13,7 +13,7 @@ import canDeleteStore from '../blocklet/publish/utils/can-delete-store';
|
|
|
13
13
|
import { useSessionContext } from '../contexts/session';
|
|
14
14
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
15
15
|
function ConnectActions({
|
|
16
|
-
|
|
16
|
+
connectedStore,
|
|
17
17
|
onDisconnect,
|
|
18
18
|
onDelete,
|
|
19
19
|
store,
|
|
@@ -31,8 +31,14 @@ function ConnectActions({
|
|
|
31
31
|
const [showDisconnectConfirm, setShowDisconnectConfirm] = useState(false);
|
|
32
32
|
const handleOpenUrl = e => {
|
|
33
33
|
e.stopPropagation();
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
if (connectedStore?.developerDid) {
|
|
35
|
+
const didConnect = Buffer.from(JSON.stringify({
|
|
36
|
+
forceConnected: connectedStore?.developerDid
|
|
37
|
+
}), 'utf8').toString('base64');
|
|
38
|
+
window.open(`${joinURL(store.url, 'developer/blocklets')}?__did-connect__=${didConnect}`);
|
|
39
|
+
} else {
|
|
40
|
+
window.open(`${joinURL(store.url, 'developer/blocklets')}`);
|
|
41
|
+
}
|
|
36
42
|
};
|
|
37
43
|
const handleOpen = event => {
|
|
38
44
|
setAnchorEl(event.currentTarget);
|
|
@@ -55,7 +61,7 @@ function ConnectActions({
|
|
|
55
61
|
setShowDisconnectConfirm(true);
|
|
56
62
|
},
|
|
57
63
|
icon: LinkOffIcon,
|
|
58
|
-
hidden: !
|
|
64
|
+
hidden: !connectedStore
|
|
59
65
|
}];
|
|
60
66
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
61
67
|
children: [/*#__PURE__*/_jsx(Button, {
|
|
@@ -132,7 +138,7 @@ function ConnectActions({
|
|
|
132
138
|
});
|
|
133
139
|
}
|
|
134
140
|
ConnectActions.propTypes = {
|
|
135
|
-
|
|
141
|
+
connectedStore: PropTypes.object.isRequired,
|
|
136
142
|
onDisconnect: PropTypes.func,
|
|
137
143
|
onDelete: PropTypes.func,
|
|
138
144
|
store: PropTypes.object.isRequired,
|
|
@@ -141,7 +147,6 @@ ConnectActions.propTypes = {
|
|
|
141
147
|
};
|
|
142
148
|
ConnectActions.defaultProps = {
|
|
143
149
|
projectId: '',
|
|
144
|
-
connected: false,
|
|
145
150
|
onDelete: () => {},
|
|
146
151
|
onDisconnect: () => {}
|
|
147
152
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Avatar } from '@mui/material';
|
|
2
|
+
import { joinURL } from 'ufo';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
function DeveloperAvatar({
|
|
6
|
+
connectedStore,
|
|
7
|
+
sx,
|
|
8
|
+
...rest
|
|
9
|
+
}) {
|
|
10
|
+
return /*#__PURE__*/_jsx(Avatar, {
|
|
11
|
+
sx: {
|
|
12
|
+
width: 24,
|
|
13
|
+
height: 24,
|
|
14
|
+
...sx
|
|
15
|
+
},
|
|
16
|
+
src: joinURL(connectedStore.storeUrl, `/.well-known/service/user/avatar/${connectedStore.developerDid}?imageFilter=resize&w=120&h=120`),
|
|
17
|
+
...rest
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
DeveloperAvatar.propTypes = {
|
|
21
|
+
connectedStore: PropTypes.object.isRequired,
|
|
22
|
+
sx: PropTypes.object
|
|
23
|
+
};
|
|
24
|
+
DeveloperAvatar.defaultProps = {
|
|
25
|
+
sx: {}
|
|
26
|
+
};
|
|
27
|
+
export default DeveloperAvatar;
|
package/lib/store/item.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { makeStyles, styled } from '@mui/styles';
|
|
2
2
|
import { Typography, Button, ButtonGroup, CircularProgress, Box, Tooltip, tooltipClasses } from '@mui/material';
|
|
3
3
|
import LaunchIcon from '@mui/icons-material/Launch';
|
|
4
|
-
import PublishIcon from '@mui/icons-material/BackupOutlined';
|
|
5
4
|
import LinkOutlinedIcon from '@mui/icons-material/LinkOutlined';
|
|
6
|
-
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
|
|
7
5
|
import DoneIcon from '@mui/icons-material/Done';
|
|
8
6
|
import PropTypes from 'prop-types';
|
|
9
7
|
import { useEffect, useState } from 'react';
|
|
10
8
|
import { joinURL } from 'ufo';
|
|
11
9
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
12
10
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
11
|
+
import PublishIcon from '@mui/icons-material/BackupOutlined';
|
|
13
12
|
import DeleteStore from './delete';
|
|
14
13
|
import { useNodeContext } from '../contexts/node';
|
|
15
14
|
import { formatError } from '../util';
|
|
16
15
|
import ConnectActions from './connect-actions';
|
|
17
16
|
import DidAddress from '../did-address';
|
|
18
17
|
import usePromiseWindowOpen from '../hooks/use-promise-window-open';
|
|
19
|
-
import
|
|
18
|
+
import DeveloperAvatar from './developer-avatar';
|
|
19
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
20
|
export const BEHAVIOR = {
|
|
21
21
|
CONNECT: 'connect',
|
|
22
22
|
SELECT: 'select'
|
|
@@ -83,7 +83,6 @@ const WhiteTooltip = styled(({
|
|
|
83
83
|
[`& .${tooltipClasses.tooltip}`]: {
|
|
84
84
|
backgroundColor: '#fff',
|
|
85
85
|
color: 'rgba(0, 0, 0, 0.87)',
|
|
86
|
-
maxWidth: 250,
|
|
87
86
|
borderRadius: 8,
|
|
88
87
|
padding: theme.spacing(2),
|
|
89
88
|
fontSize: theme.typography.pxToRem(12),
|
|
@@ -238,33 +237,61 @@ export default function StoreItem({
|
|
|
238
237
|
}), /*#__PURE__*/_jsxs("div", {
|
|
239
238
|
className: classes.actions,
|
|
240
239
|
children: [connectedStore && /*#__PURE__*/_jsx(WhiteTooltip, {
|
|
241
|
-
placement: "
|
|
242
|
-
title: /*#__PURE__*/_jsxs(
|
|
240
|
+
placement: "top",
|
|
241
|
+
title: /*#__PURE__*/_jsxs(Box, {
|
|
243
242
|
children: [/*#__PURE__*/_jsx(Typography, {
|
|
244
243
|
component: "span",
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
244
|
+
variant: "caption",
|
|
245
|
+
sx: {
|
|
246
|
+
opacity: 0.7
|
|
247
|
+
},
|
|
248
|
+
children: t('blocklet.publish.developerInfo')
|
|
249
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
250
|
+
sx: {
|
|
251
|
+
display: 'flex',
|
|
252
|
+
flexDirection: 'row',
|
|
253
|
+
alignItems: 'center',
|
|
254
|
+
gap: 1,
|
|
255
|
+
mt: 1
|
|
256
|
+
},
|
|
257
|
+
children: [/*#__PURE__*/_jsx(DeveloperAvatar, {
|
|
258
|
+
connectedStore: connectedStore,
|
|
259
|
+
sx: {
|
|
260
|
+
width: 42,
|
|
261
|
+
height: 42
|
|
262
|
+
}
|
|
263
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
264
|
+
sx: {
|
|
265
|
+
flex: 1
|
|
266
|
+
},
|
|
267
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
268
|
+
component: "span",
|
|
269
|
+
variant: "subtitle1",
|
|
270
|
+
children: connectedStore.developerName
|
|
271
|
+
}), /*#__PURE__*/_jsx(DidAddress, {
|
|
272
|
+
size: 14,
|
|
273
|
+
copyable: true,
|
|
274
|
+
compact: true,
|
|
275
|
+
responsive: false,
|
|
276
|
+
did: connectedStore.developerDid
|
|
277
|
+
})]
|
|
278
|
+
})]
|
|
253
279
|
})]
|
|
254
280
|
}),
|
|
255
|
-
children: /*#__PURE__*/_jsx(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
281
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
282
|
+
children: /*#__PURE__*/_jsx(DeveloperAvatar, {
|
|
283
|
+
connectedStore: connectedStore,
|
|
284
|
+
sx: {
|
|
285
|
+
marginRight: 1,
|
|
286
|
+
cursor: 'help'
|
|
287
|
+
}
|
|
288
|
+
})
|
|
262
289
|
})
|
|
263
290
|
}), isPublish && /*#__PURE__*/_jsxs(ButtonGroup, {
|
|
264
291
|
disabled: loading,
|
|
265
292
|
variant: "outlined",
|
|
266
293
|
sx: {
|
|
267
|
-
height:
|
|
294
|
+
height: 38
|
|
268
295
|
},
|
|
269
296
|
size: "small",
|
|
270
297
|
children: [!connected && /*#__PURE__*/_jsxs(Button, {
|
|
@@ -324,7 +351,7 @@ export default function StoreItem({
|
|
|
324
351
|
}), t('common.upload')]
|
|
325
352
|
}), /*#__PURE__*/_jsx(ConnectActions, {
|
|
326
353
|
projectId: projectId,
|
|
327
|
-
|
|
354
|
+
connectedStore: connectedStore,
|
|
328
355
|
store: store,
|
|
329
356
|
onDelete: onDelete,
|
|
330
357
|
teamDid: teamDid,
|
|
@@ -33,7 +33,7 @@ export default function InviteMember({
|
|
|
33
33
|
inviteInfo: null,
|
|
34
34
|
role: '',
|
|
35
35
|
remark: '',
|
|
36
|
-
sourceAppPid: apps.length > 0 ? apps[0].
|
|
36
|
+
sourceAppPid: apps.length > 0 ? apps[0].appPid : null
|
|
37
37
|
});
|
|
38
38
|
const onCreate = async () => {
|
|
39
39
|
if (!currentState.role) {
|
|
@@ -44,6 +44,10 @@ export default function InviteMember({
|
|
|
44
44
|
currentState.error = null;
|
|
45
45
|
currentState.loading = true;
|
|
46
46
|
try {
|
|
47
|
+
let sourceAppPid = currentState.sourceAppPid ?? null;
|
|
48
|
+
if (sourceAppPid === teamDid) {
|
|
49
|
+
sourceAppPid = null;
|
|
50
|
+
}
|
|
47
51
|
const {
|
|
48
52
|
inviteInfo
|
|
49
53
|
} = await api.createMemberInvitation({
|
|
@@ -51,7 +55,7 @@ export default function InviteMember({
|
|
|
51
55
|
teamDid,
|
|
52
56
|
role: currentState.role,
|
|
53
57
|
remark: trimRemark,
|
|
54
|
-
sourceAppPid
|
|
58
|
+
sourceAppPid
|
|
55
59
|
}
|
|
56
60
|
});
|
|
57
61
|
currentState.inviteInfo = inviteInfo;
|
|
@@ -85,7 +89,7 @@ export default function InviteMember({
|
|
|
85
89
|
label: t('common.passport'),
|
|
86
90
|
disabled: currentState.loading,
|
|
87
91
|
children: apps.map(r => /*#__PURE__*/_jsx(MenuItem, {
|
|
88
|
-
value: r.
|
|
92
|
+
value: r.appPid,
|
|
89
93
|
children: /*#__PURE__*/_jsxs(Box, {
|
|
90
94
|
sx: {
|
|
91
95
|
display: 'flex',
|
|
@@ -100,16 +104,16 @@ export default function InviteMember({
|
|
|
100
104
|
gap: 1
|
|
101
105
|
},
|
|
102
106
|
children: [/*#__PURE__*/_jsx(Avatar, {
|
|
103
|
-
did: r.
|
|
107
|
+
did: r.appPid,
|
|
104
108
|
size: 28
|
|
105
109
|
}), r.appName]
|
|
106
110
|
}), /*#__PURE__*/_jsx(DID, {
|
|
107
|
-
did: r.
|
|
111
|
+
did: r.appPid,
|
|
108
112
|
compact: true,
|
|
109
113
|
responsive: false
|
|
110
114
|
})]
|
|
111
115
|
})
|
|
112
|
-
}, r.
|
|
116
|
+
}, r.appPid))
|
|
113
117
|
})]
|
|
114
118
|
}) : null, /*#__PURE__*/_jsxs(FormControl, {
|
|
115
119
|
fullWidth: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/ux",
|
|
3
|
-
"version": "1.16.29-beta-
|
|
3
|
+
"version": "1.16.29-beta-0c32fe15",
|
|
4
4
|
"description": "UX components shared across abtnode packages",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@abtnode/auth": "1.16.29-beta-
|
|
29
|
-
"@abtnode/constant": "1.16.29-beta-
|
|
30
|
-
"@abtnode/util": "1.16.29-beta-
|
|
28
|
+
"@abtnode/auth": "1.16.29-beta-0c32fe15",
|
|
29
|
+
"@abtnode/constant": "1.16.29-beta-0c32fe15",
|
|
30
|
+
"@abtnode/util": "1.16.29-beta-0c32fe15",
|
|
31
31
|
"@ahooksjs/use-url-state": "^3.5.1",
|
|
32
32
|
"@arcblock/did": "^1.18.124",
|
|
33
33
|
"@arcblock/did-connect": "^2.10.3",
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"@arcblock/react-hooks": "^2.10.3",
|
|
38
38
|
"@arcblock/terminal": "^2.10.3",
|
|
39
39
|
"@arcblock/ux": "^2.10.3",
|
|
40
|
-
"@blocklet/constant": "1.16.29-beta-
|
|
41
|
-
"@blocklet/js-sdk": "1.16.29-beta-
|
|
42
|
-
"@blocklet/launcher-layout": "2.3.
|
|
43
|
-
"@blocklet/list": "^0.13.
|
|
44
|
-
"@blocklet/meta": "1.16.29-beta-
|
|
40
|
+
"@blocklet/constant": "1.16.29-beta-0c32fe15",
|
|
41
|
+
"@blocklet/js-sdk": "1.16.29-beta-0c32fe15",
|
|
42
|
+
"@blocklet/launcher-layout": "2.3.27",
|
|
43
|
+
"@blocklet/list": "^0.13.6",
|
|
44
|
+
"@blocklet/meta": "1.16.29-beta-0c32fe15",
|
|
45
45
|
"@blocklet/ui-react": "^2.10.3",
|
|
46
|
-
"@blocklet/uploader": "0.1.
|
|
46
|
+
"@blocklet/uploader": "0.1.19",
|
|
47
47
|
"@emotion/react": "^11.10.4",
|
|
48
48
|
"@emotion/styled": "^11.10.4",
|
|
49
49
|
"@iconify-icons/logos": "^1.2.36",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"jest": "^29.7.0",
|
|
109
109
|
"jest-environment-jsdom": "^29.7.0"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "38987125da4365838cc40c38a34daaf1bc364763"
|
|
112
112
|
}
|