mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-15 01:52:42 +03:00
Merge pull request #4648 from urbit/mp/landscape/2021-3-23-grabbag
landscape: assigned grabbag
This commit is contained in:
commit
4d13b065cd
@ -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
|
||||
|
@ -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">
|
||||
|
@ -112,6 +112,7 @@ export function ProfileStatus(props: any): ReactElement {
|
||||
display='inline-block'
|
||||
verticalAlign='middle'
|
||||
color='gray'
|
||||
title={contact?.status ?? ''}
|
||||
>
|
||||
{contact?.status ?? ''}
|
||||
</RichText>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
/>
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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";
|
||||
|
@ -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}
|
||||
|
@ -176,8 +176,9 @@ const ProfileOverlay = (props: ProfileOverlayProps) => {
|
||||
marginBottom='0'
|
||||
disableRemoteContent
|
||||
gray
|
||||
title={contact?.status ?? ''}
|
||||
>
|
||||
{contact?.status ? contact.status : ''}
|
||||
{contact?.status ?? ''}
|
||||
</RichText>
|
||||
)}
|
||||
</Col>
|
||||
|
@ -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) {
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user