Merge pull request #4648 from urbit/mp/landscape/2021-3-23-grabbag

landscape: assigned grabbag
This commit is contained in:
matildepark 2021-03-23 20:14:25 -04:00 committed by GitHub
commit 4d13b065cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 56 additions and 117 deletions

View File

@ -199,6 +199,7 @@ export default class ChatEditor extends Component {
width='calc(100% - 88px)'
className={inCodeMode ? 'chat code' : 'chat'}
color="black"
overflow='scroll'
>
{MOBILE_BROWSER_REGEX.test(navigator.userAgent)
? <MobileBox

View File

@ -93,7 +93,10 @@ function Group(props: GroupProps) {
);
const { hideUnreads } = useSettingsState(selectCalmState);
const joined = useSettingsState(selectJoined);
const days = Math.floor(moment.duration(moment(joined).add(14, 'days').diff(moment())).as('days'));
const days = Math.max(0, Math.floor(moment.duration(moment(joined)
.add(14, 'days')
.diff(moment()))
.as('days'))) || 0;
return (
<Tile ref={anchorRef} position="relative" bg={isTutorialGroup ? 'lightBlue' : undefined} to={`/~landscape${path}`} gridColumnStart={first ? '1' : null}>
<Col height="100%" justifyContent="space-between">

View File

@ -112,6 +112,7 @@ export function ProfileStatus(props: any): ReactElement {
display='inline-block'
verticalAlign='middle'
color='gray'
title={contact?.status ?? ''}
>
{contact?.status ?? ''}
</RichText>

View File

@ -142,6 +142,10 @@
margin-bottom: 16px;
}
.md ul ul {
margin-bottom: 0px;
}
.md h2, .md h3, .md h4, .md h5, .md p, .md a, .md ul {
font-weight: 400;
}

View File

@ -54,10 +54,10 @@ export function CalmPrefs(props: {
hideUnreads,
hideGroups,
hideUtilities,
imageShown,
videoShown,
oembedShown,
audioShown,
imageShown: !imageShown,
videoShown: !videoShown,
oembedShown: !oembedShown,
audioShown: !audioShown
};
const onSubmit = useCallback(async (v: FormSchema, actions: FormikHelpers<FormSchema>) => {
@ -67,10 +67,10 @@ export function CalmPrefs(props: {
api.settings.putEntry('calm', 'hideUnreads', v.hideUnreads),
api.settings.putEntry('calm', 'hideGroups', v.hideGroups),
api.settings.putEntry('calm', 'hideUtilities', v.hideUtilities),
api.settings.putEntry('remoteContentPolicy', 'imageShown', v.imageShown),
api.settings.putEntry('remoteContentPolicy', 'videoShown', v.videoShown),
api.settings.putEntry('remoteContentPolicy', 'audioShown', v.audioShown),
api.settings.putEntry('remoteContentPolicy', 'oembedShown', v.oembedShown),
api.settings.putEntry('remoteContentPolicy', 'imageShown', !v.imageShown),
api.settings.putEntry('remoteContentPolicy', 'videoShown', !v.videoShown),
api.settings.putEntry('remoteContentPolicy', 'audioShown', !v.audioShown),
api.settings.putEntry('remoteContentPolicy', 'oembedShown', !v.oembedShown),
]);
actions.setStatus({ success: null });
}, [api]);
@ -115,24 +115,24 @@ export function CalmPrefs(props: {
id="hideNicknames"
caption="Do not show user-set nicknames"
/>
<Text fontWeight="medium">Remote Content</Text>
<Text fontWeight="medium">Remote content</Text>
<Toggle
label="Load images"
label="Disable images"
id="imageShown"
caption="Images will be replaced with an inline placeholder that must be clicked to be viewed"
/>
<Toggle
label="Load audio files"
label="Disable audio files"
id="audioShown"
caption="Audio content will be replaced with an inline placeholder that must be clicked to be viewed"
/>
<Toggle
label="Load video files"
label="Disable video files"
id="videoShown"
caption="Video content will be replaced with an inline placeholder that must be clicked to be viewed"
/>
<Toggle
label="Load embedded content"
label="Disable embedded content"
id="oembedShown"
caption="Embedded content may contain scripts that can track you"
/>

View File

@ -1,85 +0,0 @@
import React from 'react';
import {
Box,
Button,
ManagedCheckboxField as Checkbox
} from '@tlon/indigo-react';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
import GlobalApi from '~/logic/api/global';
import useSettingsState, {selectSettingsState} from '~/logic/state/settings';
const formSchema = Yup.object().shape({
imageShown: Yup.boolean(),
audioShown: Yup.boolean(),
videoShown: Yup.boolean(),
oembedShown: Yup.boolean()
});
interface FormSchema {
imageShown: boolean;
audioShown: boolean;
videoShown: boolean;
oembedShown: boolean;
}
interface RemoteContentFormProps {
api: GlobalApi;
}
const selState = selectSettingsState(['remoteContentPolicy', 'set']);
export default function RemoteContentForm(props: RemoteContentFormProps) {
const { api } = props;
const { remoteContentPolicy, set: setRemoteContentPolicy} = useSettingsState(selState);
const imageShown = remoteContentPolicy.imageShown;
const audioShown = remoteContentPolicy.audioShown;
const videoShown = remoteContentPolicy.videoShown;
const oembedShown = remoteContentPolicy.oembedShown;
return (
<Formik
validationSchema={formSchema}
initialValues={
{
imageShown,
audioShown,
videoShown,
oembedShown
} as FormSchema
}
onSubmit={(values, actions) => {
setRemoteContentPolicy((state) => {
Object.assign(state.remoteContentPolicy, values);
});
actions.setSubmitting(false);
}}
>
{props => (
<Form>
<Box
display="grid"
gridTemplateColumns="1fr"
gridTemplateRows="audio"
gridRowGap={5}
>
<Box color="black" fontSize={1} fontWeight={900}>
Remote Content
</Box>
<Checkbox label="Load images" id="imageShown" />
<Checkbox label="Load audio files" id="audioShown" />
<Checkbox label="Load video files" id="videoShown" />
<Checkbox
label="Load embedded content"
id="oembedShown"
caption="Embedded content may contain scripts"
/>
<Button style={{ cursor: 'pointer' }} border={1} borderColor="washedGray" type="submit">
Save
</Button>
</Box>
</Form>
)}
</Formik>
);
}

View File

@ -1,5 +1,5 @@
import React, { ReactElement, useCallback } from 'react';
import { Formik } from 'formik';
import { Formik, FormikHelpers } from 'formik';
import {
ManagedTextInputField as Input,
@ -10,6 +10,7 @@ import {
Col,
Anchor
} from '@tlon/indigo-react';
import { AsyncButton } from "~/views/components/AsyncButton";
import GlobalApi from '~/logic/api/global';
import { BucketList } from './BucketList';
@ -35,19 +36,19 @@ export default function S3Form(props: S3FormProps): ReactElement {
const { api } = props;
const s3 = useStorageState((state) => state.s3);
const onSubmit = useCallback(
(values: FormSchema) => {
const onSubmit = useCallback(async (values: FormSchema, actions: FormikHelpers<FormSchema>) => {
if (values.s3secretAccessKey !== s3.credentials?.secretAccessKey) {
api.s3.setSecretAccessKey(values.s3secretAccessKey);
await api.s3.setSecretAccessKey(values.s3secretAccessKey);
}
if (values.s3endpoint !== s3.credentials?.endpoint) {
api.s3.setEndpoint(values.s3endpoint);
await api.s3.setEndpoint(values.s3endpoint);
}
if (values.s3accessKeyId !== s3.credentials?.accessKeyId) {
api.s3.setAccessKeyId(values.s3accessKeyId);
await api.s3.setAccessKeyId(values.s3accessKeyId);
}
actions.setStatus({ success: null });
},
[api, s3]
);
@ -95,9 +96,9 @@ export default function S3Form(props: S3FormProps): ReactElement {
label='Secret Access Key'
id='s3secretAccessKey'
/>
<Button style={{ cursor: 'pointer' }} type='submit'>
<AsyncButton primary style={{ cursor: 'pointer' }} type='submit'>
Submit
</Button>
</AsyncButton>
</Col>
</Form>
</Formik>

View File

@ -7,7 +7,6 @@ import { StoreState } from "~/logic/store/type";
import DisplayForm from "./lib/DisplayForm";
import S3Form from "./lib/S3Form";
import SecuritySettings from "./lib/Security";
import RemoteContentForm from "./lib/RemoteContent";
import { NotificationPreferences } from "./lib/NotificationPref";
import { CalmPrefs } from "./lib/CalmPref";
import { Link } from "react-router-dom";

View File

@ -11,7 +11,7 @@ import {
import { Invite } from '@urbit/api/invite';
import { Text, Icon, Row } from '@tlon/indigo-react';
import { cite } from '~/logic/lib/util';
import { cite, useShowNickname } from '~/logic/lib/util';
import GlobalApi from '~/logic/api/global';
import { resourceFromPath } from '~/logic/lib/group';
import { GroupInvite } from './Group';
@ -19,6 +19,7 @@ import { InviteSkeleton } from './InviteSkeleton';
import { JoinSkeleton } from './JoinSkeleton';
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
import useGroupState from '~/logic/state/group';
import useContactState from '~/logic/state/contact';
import useMetadataState from '~/logic/state/metadata';
interface InviteItemProps {
@ -37,7 +38,10 @@ export function InviteItem(props: InviteItemProps) {
const status = pendingJoin[resource];
const groups = useGroupState(state => state.groups);
const associations = useMetadataState(state => state.associations);
const waiter = useWaitForProps({ associations, groups, pendingJoin}, 50000);
const contacts = useContactState(state => state.contacts);
const contact = contacts?.[`~${invite?.ship}`] ?? {};
const showNickname = useShowNickname(contact);
const waiter = useWaitForProps({ associations, groups, pendingJoin }, 50000);
const history = useHistory();
const inviteAccept = useCallback(async () => {
@ -114,8 +118,10 @@ export function InviteItem(props: InviteItemProps) {
>
<Row py="1" alignItems="center">
<Icon display="block" color="blue" icon="Bullet" mr="2" />
<Text mr="1" mono>
{cite(`~${invite!.ship}`)}
<Text mr="1"
mono={!showNickname}
fontWeight={showNickname ? '500' : '400'}>
{showNickname ? contact?.nickname : cite(`~${invite!.ship}`)}
</Text>
<Text mr="1">invited you to a DM</Text>
</Row>
@ -140,8 +146,10 @@ export function InviteItem(props: InviteItemProps) {
>
<Row py="1" alignItems="center">
<Icon display="block" color="blue" icon="Bullet" mr="2" />
<Text mr="1" mono>
{cite(`~${invite!.ship}`)}
<Text mr="1"
mono={!showNickname}
fontWeight={showNickname ? '500' : '400'}>
{showNickname ? contact?.nickname : cite(`~${invite!.ship}`)}
</Text>
<Text mr="1">
invited you to ~{invite.resource.ship}/{invite.resource.name}

View File

@ -176,8 +176,9 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
marginBottom='0'
disableRemoteContent
gray
title={contact?.status ?? ''}
>
{contact?.status ? contact.status : ''}
{contact?.status ?? ''}
</RichText>
)}
</Col>

View File

@ -30,7 +30,7 @@ interface OmniboxProps {
notifications: number;
}
const SEARCHED_CATEGORIES = ['ships', 'other', 'commands', 'groups', 'subscriptions', 'apps'];
const SEARCHED_CATEGORIES = ['commands', 'ships', 'other', 'groups', 'subscriptions', 'apps'];
const settingsSel = (s: SettingsState) => s.leap;
export function Omnibox(props: OmniboxProps) {

View File

@ -64,7 +64,7 @@ export class OmniboxResult extends Component {
graphic = <Icon display='inline-block' verticalAlign='middle' icon='Users' mr='2' size='18px' color={iconFill} />;
} else if (icon === 'tutorial') {
graphic = <Icon display='inline-block' verticalAlign='middle' icon='Tutorial' mr='2' size='18px' color={iconFill} />;
}
}
else {
graphic = <Icon display='inline-block' icon='NullIcon' verticalAlign="middle" mr='2' size="16px" color={iconFill} />;
}
@ -102,6 +102,12 @@ export class OmniboxResult extends Component {
<Text
mono={(icon == 'profile' && text.startsWith('~'))}
color={this.state.hovered || selected === link ? 'white' : 'black'}
display='inline-block'
verticalAlign='middle'
width='100%'
overflow='hidden'
textOverflow='ellipsis'
whiteSpace='pre'
mr='1'
>
{text.startsWith("~") ? cite(text) : text}