Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: open nft media in browser #5359

Merged
merged 11 commits into from Dec 7, 2022
@@ -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