1import { css } from '@emotion/react'; 2import { useMemo } from 'react'; 3 4import { androidPermissions, AndroidPermission, PermissionReference } from './data'; 5 6import { Callout } from '~/ui/components/Callout'; 7import { Cell, HeaderCell, Row, Table, TableHead } from '~/ui/components/Table'; 8import { CODE, P, createPermalinkedComponent } from '~/ui/components/Text'; 9 10// TODO(cedric): all commented code is related to the "granter" column. 11// This column defines if the permission is granted by the system or user (requires notification). 12// We have to clearly communicate what it means before showing it to the user. 13 14type AndroidPermissionsProps = { 15 permissions: PermissionReference<AndroidPermission>[]; 16}; 17 18// const grantedByInfo = 'Some permissions are granted by the system without user approval'; 19 20export function AndroidPermissions({ permissions }: AndroidPermissionsProps) { 21 const list = useMemo(() => getPermissions(permissions), [permissions]); 22 23 return ( 24 <Table> 25 <TableHead> 26 <Row> 27 <HeaderCell>Android Permission</HeaderCell> 28 {/* <HeaderCell> 29 <span css={grantedByInfoStyle} title={grantedByInfo}> 30 Granted by <QuestionIcon size={12} title={grantedByInfo} /> 31 </span> 32 </HeaderCell> */} 33 <HeaderCell>Description</HeaderCell> 34 </Row> 35 </TableHead> 36 <tbody> 37 {list.map(permission => ( 38 <AndroidPermissionRow key={permission.name} {...permission} /> 39 ))} 40 </tbody> 41 </Table> 42 ); 43} 44 45const PermissionPermalink = createPermalinkedComponent(P, { 46 baseNestingLevel: 4, 47}); 48 49function AndroidPermissionRow({ 50 name, 51 description, 52 explanation, 53 warning, 54 apiDeprecated, 55}: AndroidPermission) { 56 return ( 57 <Row subtle={!!apiDeprecated}> 58 <Cell> 59 <PermissionPermalink id={`permission-${name.toLowerCase()}`}> 60 <CODE>{name}</CODE> 61 </PermissionPermalink> 62 </Cell> 63 {/* <Cell> 64 <i>{getPermissionGranter(permission)}</i> 65 </Cell> */} 66 <Cell> 67 {!!description && ( 68 <P css={(warning || explanation) && descriptionSpaceStyle}>{description}</P> 69 )} 70 {!!warning && ( 71 <Callout css={quoteStyle} type="warning"> 72 {warning} 73 </Callout> 74 )} 75 {explanation && !warning && ( 76 <Callout css={quoteStyle}> 77 <span dangerouslySetInnerHTML={{ __html: explanation }} /> 78 </Callout> 79 )} 80 </Cell> 81 </Row> 82 ); 83} 84 85function getPermissions(permissions: AndroidPermissionsProps['permissions']) { 86 return permissions 87 .map(permission => 88 typeof permission === 'string' 89 ? androidPermissions[permission] 90 : { ...androidPermissions[permission.name], ...permission } 91 ) 92 .filter(Boolean); 93} 94 95// const grantedByInfoStyle = css` 96// white-space: nowrap; 97// `; 98 99const descriptionSpaceStyle = css` 100 margin-bottom: 1rem; 101`; 102 103const quoteStyle = css` 104 margin-bottom: 0; 105`; 106 107// function getPermissionGranter(permission: AndroidPermission): 'user' | 'system' | 'none' { 108// if (!permission.protection) return 'none'; 109// if (permission.protection.includes('dangerous')) return 'user'; 110// return 'system'; 111// } 112