diff --git a/.gitignore b/.gitignore index 4dbca652..0ed9ea7c 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ src/config/setup.json # e2e screenshots e2e/screenshots/* +package-lock.json +webpack.config.js.backup +package.json diff --git a/docs/SIP-100-account-icon-jp.md b/docs/SIP-100-account-icon-jp.md new file mode 100644 index 00000000..6757ebbd --- /dev/null +++ b/docs/SIP-100-account-icon-jp.md @@ -0,0 +1,62 @@ +# SIP-426: メタデータによるアカウントアイコン表示 + +## 概要(Summary) +この提案は、Symbol Explorer において、アカウントメタデータに保存された画像URLをもとにアカウントアイコンを表示できる新機能を導入するものです。 +所有者のアドレスが記載されたSNSのURLを追加することで本人のアドレスであることが客観的に証明される。 + +## 動機(Motivation) +現在、Symbol Explorerではアカウントは単なるアドレス文字列として表示されています。アカウントに関連付けられたビジュアルアイコンを表示できるようにすることで、以下の効果が期待できます: + +- 直感的で親しみやすいユーザーインターフェースの実現 +- 分散型アイデンティティとパーソナライズ表現の推進 +- 既知アドレスを視覚的に素早く認識できるようになる +- 誰のアドレスかSNSを使ってのアドレスの検証 + + +## 仕様(Specification) + +### メタデータの使用(Metadata Usage) +- 利用するメタデータキー: `social_meta_data` +- 値:JSON + +```JSON + +{"url":"https://example.com","name":"myname","imageUrl":"https://example.com/image.jpg","namespace":"my namespace"} + +``` + +### 表示ルール(Display Rules) +- `social_meta_data` が存在し、かつ有効な画像URLであれば、その画像をアカウントアイコンとして表示します。 +- メタデータが存在しない、または無効な場合は、従来のSVGプレースホルダーアイコンを使用します。 +- 画像は丸型アイコンとして表示します(`border-radius: 50%` を適用)。 + +### モデレーション(Moderation) +- 不適切と思われるアイコンに対して、ユーザーが「非表示」ボタンをクリックして手動で隠すことができます。 +- 非表示設定されたアカウントは、ブラウザの localStorage に保存され、以降の読み込み時に表示されなくなります。 +- (オプション)ユーザーが不適切な画像を「通報」できるボタンも将来的に導入可能です。 + +### バリデーション(Validation) +- 画像表示前に以下のバリデーションを行います: + - `http://` または `https://` で始まるか + - 適切な長さと形式であるかを検証して、不正利用を防止する + +## 根拠(Rationale) +この機能は、Symbolアカウントメタデータの既存機能を活用するため、プロトコルレベルの変更を必要としません。 +ユーザーインターフェースを大きく向上させつつ、後方互換性を保ち、ローカルでの安全管理も可能にします。 + +## 後方互換性(Backwards Compatibility) +この提案は、既存機能を壊すことはありません。 +`social_meta_data` が設定されていないアカウントは、従来通りデフォルトのアイコンが表示されます。 + +## 実装上の注意点(Implementation Notes) +- メタデータは非同期で取得し、初回ページロードをブロックしないようにする +- アイコンサイズは最適化する(例:64x64px以内) +- パフォーマンス向上のため、アイコン画像は遅延読み込み(lazy loading)を検討する + +## 参考リンク(References) +- 関連する機能提案ディスカッション:[GitHub Issue #1200](https://github.com/symbol/symbol-explorer/issues/1200) + +--- + +*提案者(Author): [bootarou]* +*日付(Date): 2025-04-26* \ No newline at end of file diff --git a/docs/SIP-100-account-icon.md b/docs/SIP-100-account-icon.md new file mode 100644 index 00000000..16259f39 --- /dev/null +++ b/docs/SIP-100-account-icon.md @@ -0,0 +1,76 @@ +# SIP-426: Account Icon Display Using Metadata + +## Summary + +This proposal introduces a new feature that enables Symbol Explorer to render account icons based on image URLs stored in account metadata. +By adding the owner's social media URL that references their address, it becomes possible to objectively verify that the address belongs to the owner. + +## Motivation + +Currently, accounts in Symbol Explorer are displayed only as raw address strings. +By associating accounts with visual icons, the following benefits can be achieved: + +- A more intuitive and user-friendly interface +- Promotion of decentralized identity and personalization +- Easier visual recognition of familiar addresses +- Verification of address ownership using social media links + +## Specification + +### Metadata Usage + +- Metadata key: `social_meta_data` +- Value: JSON format + +```json +{ + "url": "https://example.com", + "name": "Myname", + "imageUrl": "https://example.com/image.jpg", + "namespace": "My namespace" +} +``` + +### Display Rules + +- If `social_meta_data` exists and contains a valid `imageUrl`, display the image as the account icon. +- If no valid metadata is found, fall back to the default SVG placeholder icon. +- The icon image should be displayed as a circle (`border-radius: 50%`). + +### Moderation + +- Users can manually hide icons they find inappropriate by clicking a "Hide" button. +- Hidden accounts are stored in the browser's localStorage to prevent future loading. +- (Optional) A "Report" button may be introduced to allow users to report inappropriate images for moderation. + +### Validation + +Before displaying an image, perform the following validations: + +- Check if the URL starts with `http://` or `https://` +- Ensure the URL is within a reasonable length and proper format to prevent abuse + +## Rationale + +This feature leverages the existing Symbol account metadata functionality and does not require any protocol-level changes. +It improves the user interface while maintaining backward compatibility and ensuring local client-side control for user safety. + +## Backwards Compatibility + +This proposal does not break any existing functionality. +Accounts without `social_meta_data` will continue to display the default SVG icon as before. + +## Implementation Notes + +- Fetch metadata asynchronously to avoid blocking the initial page load +- Optimize icon size (e.g., within 64x64px) +- Consider implementing lazy loading for account images to enhance performance + +## References + +- Related feature discussion: [GitHub Issue #1200](https://github.com/symbol/symbol-explorer/issues/1200) + +--- + +*Author: [bootarou]* +*Date: 2025-04-26* diff --git a/package-lock.json b/package-lock.json index db7b34c7..bbf8539e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "babel-eslint": "^10.1.0", "babel-jest": "^28.1.1", "browserify-zlib": "^0.2.0", + "buffer": "^6.0.3", "crypto-browserify": "^3.12.1", "cypress": "^10.1.0", "eslint": "^7.32.0", @@ -7219,6 +7220,31 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/bl/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -7523,9 +7549,9 @@ } }, "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, "funding": [ { @@ -7544,7 +7570,7 @@ "license": "MIT", "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ieee754": "^1.2.1" } }, "node_modules/buffer-crc32": { @@ -9221,6 +9247,31 @@ "dev": true, "license": "MIT" }, + "node_modules/cypress/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/cypress/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", diff --git a/package.json b/package.json index 3a8e8a50..8b114889 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "babel-eslint": "^10.1.0", "babel-jest": "^28.1.1", "browserify-zlib": "^0.2.0", + "buffer": "^6.0.3", "crypto-browserify": "^3.12.1", "cypress": "^10.1.0", "eslint": "^7.32.0", diff --git a/src/components/graphics/AccountIcon.vue b/src/components/graphics/AccountIcon.vue index b0551a08..04c8f398 100644 --- a/src/components/graphics/AccountIcon.vue +++ b/src/components/graphics/AccountIcon.vue @@ -1,58 +1,241 @@ diff --git a/src/store/ui.js b/src/store/ui.js index 5d51ce17..856ce8ed 100644 --- a/src/store/ui.js +++ b/src/store/ui.js @@ -94,9 +94,17 @@ export default { let value = payload.param; if (null != value) - router.push({ path: `/${pageName}/${value}` }); + router.push({ path: `/${pageName}/${value}` }).catch(err => { + if (err.name !== 'NavigationDuplicated') { + throw err; + } + }); else - router.push({ path: `/${pageName}` }); + router.push({ path: `/${pageName}` }).catch(err => { + if (err.name !== 'NavigationDuplicated') { + throw err; + } + }); } },