Skip to content

Commit

Permalink
feat: open nft media in browser (#5359)
Browse files Browse the repository at this point in the history
* enhancement: move open url in browser into own function

* enhancement: add confirmation popup

* chore: add localization to external url popup

* fix: fix condition for blacklist

* fix: fix url validation

* chore: remove blacklist from electron + locale fixase

* feat: open nft media in browser

* enhancment: rewrite ipfs/http protocol into https

* fix: disable instead of hiding menu options on nft details menu

Co-authored-by: Nicole O'Brien <nicole.obrien@iota.org>
  • Loading branch information
MarkNerdi996 and nicole-obrien committed Dec 7, 2022
1 parent be3cff4 commit 4163211
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 10 deletions.
@@ -1,13 +1,13 @@
<script lang="ts">
import { collectiblesRoute, CollectiblesRoute } from '@core/router'
import { DetailsView, GalleryView } from './views'
import { NftDetailsView, GalleryView } from './views'
</script>

<div class="w-full h-full flex flex-col flex-nowrap p-8 relative flex-1 bg-gray-50 dark:bg-gray-900">
{#if $collectiblesRoute === CollectiblesRoute.Gallery}
<GalleryView />
{/if}
{#if $collectiblesRoute === CollectiblesRoute.Details}
<DetailsView />
<NftDetailsView />
{/if}
</div>
@@ -1,2 +1,2 @@
export { default as DetailsView } from './DetailsView.svelte'
export { default as NftDetailsView } from './NftDetailsView.svelte'
export { default as GalleryView } from './GalleryView.svelte'
38 changes: 34 additions & 4 deletions packages/shared/components/modals/CollectibleDetailsMenu.svelte
Expand Up @@ -4,12 +4,15 @@
import { closePopup, openPopup } from '@auxiliary/popup/actions'
import { checkActiveProfileAuth } from '@core/profile/actions'
import { burnNft } from '@core/wallet'
import { INft } from '@core/nfts'
import { INft, rewriteIpfsUri } from '@core/nfts'
import { CollectiblesRoute, collectiblesRouter } from '@core/router'
import { openUrlInBrowser } from '@core/app'
export let modal: Modal = undefined
export let nft: INft
$: url = composeUrl(nft?.parsedMetadata?.uri)
function openBurnNft(): void {
openPopup({
type: 'confirmation',
Expand All @@ -36,13 +39,40 @@
},
})
}
function composeUrl(targetUrl: string): string {
if (!targetUrl) {
return undefined
}
const url = new URL(targetUrl)
switch (url.protocol) {
case 'http:':
return targetUrl.replace('http:', 'https:')
case 'https:':
return targetUrl
case 'ipfs:':
return rewriteIpfsUri(targetUrl)
default:
return undefined
}
}
function handleOpenMediaClick(): void {
openUrlInBrowser(url)
}
</script>

<Modal bind:this={modal} position={{ top: '100px', right: '60px' }}>
<div class="flex flex-col">
<MenuItem icon="receive" title={localize('views.collectibles.details.menu.download')} first />
<MenuItem icon="profile" title={localize('views.collectibles.details.menu.setAvatar')} />
<MenuItem icon="export" title={localize('views.collectibles.details.menu.view')} />
<MenuItem icon="receive" title={localize('views.collectibles.details.menu.download')} disabled={true} />
<MenuItem icon="profile" title={localize('views.collectibles.details.menu.setAvatar')} disabled={true} />
<MenuItem
icon="export"
title={localize('views.collectibles.details.menu.view')}
onClick={handleOpenMediaClick}
disabled={!url}
/>
<MenuItem icon="delete" title={localize('views.collectibles.details.menu.burn')} onClick={openBurnNft} />
</div>
</Modal>
9 changes: 8 additions & 1 deletion packages/shared/lib/core/app/utils/openUrlInBrowser.ts
Expand Up @@ -2,14 +2,21 @@ import { closePopup, openPopup } from '@auxiliary/popup'
import { localize } from '@core/i18n'
import { Platform } from '../classes/platform.class'
import { externalAllowedLinks } from '../constants'
import { showAppNotification } from '@auxiliary/notification'

export function openUrlInBrowser(targetUrl: string): void {
const url = new URL(targetUrl)
const domain = url.hostname.replace('www.', '').replace('mailto:', '')

const isAllowed = externalAllowedLinks.includes(domain) || externalAllowedLinks.includes(domain + url.pathname)

if (isAllowed) {
if (url.protocol !== 'https:') {
showAppNotification({
alert: true,
type: 'error',
message: localize('popups.externalUrl.invalidProtocol'),
})
} else if (isAllowed) {
Platform.openUrl(targetUrl)
} else {
openPopup({
Expand Down
1 change: 1 addition & 0 deletions packages/shared/lib/core/nfts/utils/index.ts
@@ -1,3 +1,4 @@
export * from './buildNftFromNftOutput'
export * from './getIsSpendableFromUnspentNftOutput'
export * from './parseNftMetadata'
export * from './rewriteIpfsUri'
5 changes: 5 additions & 0 deletions packages/shared/lib/core/nfts/utils/rewriteIpfsUri.ts
@@ -0,0 +1,5 @@
export function rewriteIpfsUri(ipfsUri: string): string {
const url = new URL(ipfsUri)

return 'https://ipfs.io/ipfs/' + url.pathname.replace('//', '')
}
5 changes: 3 additions & 2 deletions packages/shared/locales/en.json
Expand Up @@ -563,7 +563,7 @@
"menu": {
"download": "Download",
"setAvatar": "Set NFT as profile avatar",
"view": "View in IPFS",
"view": "View media in browser",
"burn": "Burn NFT"
}
},
Expand Down Expand Up @@ -704,7 +704,8 @@
"title": "Open URL in Browser",
"body": "Are you sure you want to open \"{url}\" in the browser?",
"hint": "This URL is unknown to Firefly. Please double check the URL before opening it.",
"action": "Open URL"
"action": "Open URL",
"invalidProtocol": "Cannot open URL with invalid protocol"
},
"hideAccount": {
"title": "Hide {name}?",
Expand Down

0 comments on commit 4163211

Please sign in to comment.