Rewrite sidebar to Typescript

This commit is contained in:
viktorstrate
2021-04-19 13:18:15 +02:00
parent 1430e9da02
commit 74cf35ef82
9 changed files with 101 additions and 58 deletions

View File

@@ -17,6 +17,7 @@
"add": "Tilføj",
"cancel": "Annuller",
"delete": "Slet",
"more": "Mere",
"remove": "Fjern",
"save": "Gem"
},
@@ -76,7 +77,7 @@
"title": "Billeder"
},
"places_page": {
"title": null
"title": "Kort"
},
"routes": {
"page_not_found": "Side ikke fundet"
@@ -169,7 +170,7 @@
},
"sidebar": {
"album": {
"title": "Album indstillinger"
"title": "Indstillinger for album"
},
"download": {
"filesize": {
@@ -223,7 +224,7 @@
"flash": "Blitz",
"focal_length": "Brændvidde",
"iso": "ISO",
"lens": "Lense",
"lens": "Objektiv",
"maker": "Mærke"
}
}

View File

@@ -17,6 +17,7 @@
"add": "Add",
"cancel": "Cancel",
"delete": "Delete",
"more": "More",
"remove": "Remove",
"save": "Save"
},

View File

@@ -17,6 +17,7 @@
"add": "Ajouter",
"cancel": "Annuler",
"delete": "Effacer",
"more": null,
"remove": "Supprimer",
"save": "Sauvegarder"
},

View File

@@ -17,6 +17,7 @@
"add": "Lägg till",
"cancel": "Avbryt",
"delete": "Radera",
"more": null,
"remove": "Ta bort",
"save": "Spara"
},

View File

@@ -24,6 +24,8 @@ import {
sidebarPhoto_media_videoMetadata,
} from './__generated__/sidebarPhoto'
import { sidebarDownloadQuery_media_downloads } from './__generated__/sidebarDownloadQuery'
const SIDEBAR_MEDIA_QUERY = gql`
query sidebarPhoto($id: ID!) {
media(id: $id) {
@@ -161,13 +163,15 @@ export const MetadataInfo = ({ media }: MediaInfoProps) => {
x => mediaExif[x] !== null && x != '__typename'
)
const exif = exifKeys.reduce(
(prev, curr) => ({
const exif = exifKeys.reduce((prev, curr) => {
const value = mediaExif[curr]
if (isNil(value)) return prev
return {
...prev,
[curr]: mediaExif[curr],
}),
{} as { [key: string]: string | number | null }
)
[curr]: value,
}
}, {} as { [key: string]: string | number })
if (!isNil(exif.dateShot)) {
exif.dateShot = new Date(exif.dateShot).toLocaleString()
@@ -202,7 +206,7 @@ export const MetadataInfo = ({ media }: MediaInfoProps) => {
}
exifItems = exifKeys.map(key => (
<SidebarItem key={key} name={exifName[key]} value={exif[key]} />
<SidebarItem key={key} name={exifName[key]} value={exif[key] as string} />
))
}
@@ -214,13 +218,15 @@ export const MetadataInfo = ({ media }: MediaInfoProps) => {
let metadata = Object.keys(videoMetadata)
.filter(x => !['id', '__typename', 'width', 'height'].includes(x))
.reduce(
(prev, curr) => ({
.reduce((prev, curr) => {
const value = videoMetadata[curr as string]
if (isNil(value)) return prev
return {
...prev,
[curr]: videoMetadata[curr as string],
}),
{} as { [key: string]: string | number | null }
)
[curr]: value,
}
}, {} as { [key: string]: string | number })
metadata = {
dimensions: `${media.videoMetadata.width}x${media.videoMetadata.height}`,
@@ -228,7 +234,7 @@ export const MetadataInfo = ({ media }: MediaInfoProps) => {
}
videoMetadataItems = Object.keys(metadata).map(key => (
<SidebarItem key={key} name={key} value={metadata[key]} />
<SidebarItem key={key} name={key} value={metadata[key] as string} />
))
}
@@ -376,7 +382,7 @@ const SidebarContent = ({ media, hidePreview }: SidebarContentProps) => {
)}
<Name>{media.title}</Name>
<MetadataInfo media={media} />
<SidebarDownload photo={media} />
<SidebarDownload media={media} />
<SidebarPhotoShare id={media.id} />
</div>
)
@@ -403,6 +409,7 @@ export interface MediaSidebarMedia {
videoMetadata?: sidebarPhoto_media_videoMetadata | null
exif?: sidebarPhoto_media_exif | null
faces?: sidebarPhoto_media_faces[]
downloads?: sidebarDownloadQuery_media_downloads[]
}
type MediaSidebarType = {

View File

@@ -211,7 +211,7 @@ const ShareItemMoreDropdown = ({
// onClose={() => setDropdownOpen(false)}
// open={dropdownOpen}
button
text="More"
text={t('general.action.more', 'More')}
closeOnChange={false}
closeOnBlur={false}
>

View File

@@ -6,6 +6,13 @@ import { MessageState } from '../messages/Messages'
import { useLazyQuery, gql } from '@apollo/client'
import { authToken } from '../../helpers/authentication'
import { useTranslation } from 'react-i18next'
import { TranslationFn } from '../../localization'
import { MediaSidebarMedia } from './MediaSidebar'
import {
sidebarDownloadQuery,
sidebarDownloadQueryVariables,
sidebarDownloadQuery_media_downloads,
} from './__generated__/sidebarDownloadQuery'
export const SIDEBAR_DOWNLOAD_QUERY = gql`
query sidebarDownloadQuery($mediaId: ID!) {
@@ -24,10 +31,12 @@ export const SIDEBAR_DOWNLOAD_QUERY = gql`
}
`
const formatBytes = t => bytes => {
if (bytes == 0) return '0 Byte'
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
const count = Math.round(bytes / Math.pow(1024, i), 2)
const formatBytes = (t: TranslationFn) => (bytes: number) => {
if (bytes == 0)
return t('sidebar.download.filesize.byte', '{{count}} Byte', { count: 0 })
const i = Math.floor(Math.log(bytes) / Math.log(1024))
const count = Math.round(bytes / Math.pow(1024, i))
switch (i) {
case 0:
@@ -46,7 +55,7 @@ const formatBytes = t => bytes => {
}
}
const downloadMedia = t => async url => {
const downloadMedia = (t: TranslationFn) => async (url: string) => {
const imgUrl = new URL(url, location.origin)
if (authToken() == null) {
@@ -68,15 +77,32 @@ const downloadMedia = t => async url => {
blob = await response.blob()
}
const filename = url.match(/[^/]*$/)[0]
if (blob == null) {
console.log('Blob is null canceling')
return
}
const filenameMatch = url.match(/[^/]*$/)
if (filenameMatch == null) {
console.error('Could not extract filename', url)
return
}
const filename = filenameMatch[0]
downloadBlob(blob, filename)
}
const downloadMediaShowProgress = t => async response => {
const downloadMediaShowProgress = (t: TranslationFn) => async (
response: Response
) => {
const totalBytes = Number(response.headers.get('content-length'))
const reader = response.body.getReader()
let data = new Uint8Array(totalBytes)
const reader = response.body?.getReader()
const data = new Uint8Array(totalBytes)
if (reader == null) {
throw new Error('Download reader is null')
}
let canceled = false
const onDismiss = () => {
@@ -84,9 +110,9 @@ const downloadMediaShowProgress = t => async response => {
reader.cancel('Download canceled by user')
}
const notifKey = Math.random().toString(26)
const notifyKey = Math.random().toString(26)
MessageState.add({
key: notifKey,
key: notifyKey,
type: 'progress',
onDismiss,
props: {
@@ -108,7 +134,7 @@ const downloadMediaShowProgress = t => async response => {
receivedBytes += result.value ? result.value.length : 0
MessageState.add({
key: notifKey,
key: notifyKey,
type: 'progress',
onDismiss,
props: {
@@ -126,7 +152,7 @@ const downloadMediaShowProgress = t => async response => {
}
MessageState.add({
key: notifKey,
key: notifyKey,
type: 'progress',
props: {
header: 'Downloading photo completed',
@@ -137,20 +163,20 @@ const downloadMediaShowProgress = t => async response => {
})
setTimeout(() => {
MessageState.removeKey(notifKey)
MessageState.removeKey(notifyKey)
}, 2000)
const content = new Blob([data.buffer], {
type: response.headers.get('content-type'),
type: response.headers.get('content-type') || undefined,
})
return content
}
const downloadBlob = async (blob, filename) => {
let objectUrl = window.URL.createObjectURL(blob)
const downloadBlob = async (blob: Blob, filename: string) => {
const objectUrl = window.URL.createObjectURL(blob)
let anchor = document.createElement('a')
const anchor = document.createElement('a')
document.body.appendChild(anchor)
anchor.href = objectUrl
@@ -166,36 +192,43 @@ const DownloadTableRow = styled(Table.Row)`
cursor: pointer;
`
const SidebarDownload = ({ photo }) => {
type SidebarDownladProps = {
media: MediaSidebarMedia
}
const SidebarDownload = ({ media }: SidebarDownladProps) => {
const { t } = useTranslation()
if (!photo || !photo.id) return null
if (!media || !media.id) return null
const [
loadPhotoDownloads,
{ called, loading, data },
] = useLazyQuery(SIDEBAR_DOWNLOAD_QUERY, { variables: { mediaId: photo.id } })
const [loadPhotoDownloads, { called, loading, data }] = useLazyQuery<
sidebarDownloadQuery,
sidebarDownloadQueryVariables
>(SIDEBAR_DOWNLOAD_QUERY, { variables: { mediaId: media.id } })
let downloads = []
let downloads: sidebarDownloadQuery_media_downloads[] = []
if (called) {
if (!loading) {
downloads = data && data.media.downloads
downloads = (data && data.media.downloads) || []
}
} else {
if (!photo.downloads) {
if (!media.downloads) {
loadPhotoDownloads()
} else {
downloads = photo.downloads
downloads = media.downloads
}
}
const extractExtension = url => {
return url.split(/[#?]/)[0].split('.').pop().trim().toLowerCase()
const extractExtension = (url: string) => {
const urlMatch = url.split(/[#?]/)
if (urlMatch == null) return
return urlMatch[0].split('.').pop()?.trim().toLowerCase()
}
const download = downloadMedia(t)
const bytes = formatBytes(t)
let downloadRows = downloads.map(x => (
const downloadRows = downloads.map(x => (
<DownloadTableRow
key={x.mediaUrl.url}
onClick={() => download(x.mediaUrl.url)}

View File

@@ -1,5 +1,4 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
const ItemName = styled.div`
@@ -17,16 +16,16 @@ const ItemValue = styled.div`
font-size: 1rem;
`
const SidebarItem = ({ name, value }) => (
type SidebarItemProps = {
name: string
value: string
}
const SidebarItem = ({ name, value }: SidebarItemProps) => (
<div>
<ItemName>{name}</ItemName>
<ItemValue>{value}</ItemValue>
</div>
)
SidebarItem.propTypes = {
name: PropTypes.string.isRequired,
value: PropTypes.any.isRequired,
}
export default SidebarItem

View File

@@ -3,7 +3,7 @@
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
"incremental": true /* Enable incremental compilation */,
// "incremental": true /* Enable incremental compilation */,
"target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
"lib": [