Add keyboard shortcuts: new, escape, and hard break (#552)
* Add keyboard shortcuts: new, escape, and hard break * Add preferences modal * Remove code accidentally re-added due to rebase * Fix incorrect copy and lint * Put stuff back so diffs are clearer * Re-add invite codes to settings * Address comments * Tune the copy --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>zio/stable
parent
af905947bc
commit
95f8360d19
|
@ -49,6 +49,7 @@
|
|||
"@sentry/react-native": "4.13.0",
|
||||
"@tiptap/core": "^2.0.0-beta.220",
|
||||
"@tiptap/extension-document": "^2.0.0-beta.220",
|
||||
"@tiptap/extension-hard-break": "^2.0.3",
|
||||
"@tiptap/extension-history": "^2.0.3",
|
||||
"@tiptap/extension-link": "^2.0.0-beta.220",
|
||||
"@tiptap/extension-mention": "^2.0.0-beta.220",
|
||||
|
@ -58,6 +59,7 @@
|
|||
"@tiptap/pm": "^2.0.0-beta.220",
|
||||
"@tiptap/react": "^2.0.0-beta.220",
|
||||
"@tiptap/suggestion": "^2.0.0-beta.220",
|
||||
"@types/node": "^18.16.2",
|
||||
"@zxing/text-encoding": "^0.9.0",
|
||||
"await-lock": "^2.2.2",
|
||||
"base64-js": "^1.5.1",
|
||||
|
|
|
@ -11,6 +11,7 @@ export interface ConfirmModal {
|
|||
title: string
|
||||
message: string | (() => JSX.Element)
|
||||
onPressConfirm: () => void | Promise<void>
|
||||
onPressCancel?: () => void | Promise<void>
|
||||
}
|
||||
|
||||
export interface EditProfileModal {
|
||||
|
@ -86,10 +87,10 @@ export interface ContentFilteringSettingsModal {
|
|||
|
||||
export type Modal =
|
||||
// Account
|
||||
| AddAppPasswordModal
|
||||
| ChangeHandleModal
|
||||
| DeleteAccountModal
|
||||
| EditProfileModal
|
||||
| AddAppPasswordModal
|
||||
|
||||
// Curation
|
||||
| ContentFilteringSettingsModal
|
||||
|
|
|
@ -88,6 +88,30 @@ export const ComposePost = observer(function ComposePost({
|
|||
autocompleteView.setup()
|
||||
}, [autocompleteView])
|
||||
|
||||
const onEscape = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
store.shell.openModal({
|
||||
name: 'confirm',
|
||||
title: 'Cancel draft',
|
||||
onPressConfirm: onClose,
|
||||
onPressCancel: () => {
|
||||
store.shell.closeModal()
|
||||
},
|
||||
message: "Are you sure you'd like to cancel this draft?",
|
||||
})
|
||||
}
|
||||
},
|
||||
[store.shell, onClose],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isDesktopWeb) {
|
||||
window.addEventListener('keydown', onEscape)
|
||||
return () => window.removeEventListener('keydown', onEscape)
|
||||
}
|
||||
}, [onEscape])
|
||||
|
||||
const onPressAddLinkCard = useCallback(
|
||||
(uri: string) => {
|
||||
setExtLink({uri, isLoading: true})
|
||||
|
|
|
@ -4,6 +4,7 @@ import {RichText} from '@atproto/api'
|
|||
import {useEditor, EditorContent, JSONContent} from '@tiptap/react'
|
||||
import {Document} from '@tiptap/extension-document'
|
||||
import History from '@tiptap/extension-history'
|
||||
import Hardbreak from '@tiptap/extension-hard-break'
|
||||
import {Link} from '@tiptap/extension-link'
|
||||
import {Mention} from '@tiptap/extension-mention'
|
||||
import {Paragraph} from '@tiptap/extension-paragraph'
|
||||
|
@ -72,6 +73,7 @@ export const TextInput = React.forwardRef(
|
|||
}),
|
||||
Text,
|
||||
History,
|
||||
Hardbreak,
|
||||
],
|
||||
editorProps: {
|
||||
attributes: {
|
||||
|
|
|
@ -34,8 +34,8 @@ export function Component({altText}: Props) {
|
|||
testID="altTextImageSaveBtn"
|
||||
onPress={onPress}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Save"
|
||||
accessibilityHint="Save alt text">
|
||||
accessibilityLabel="Done"
|
||||
accessibilityHint="Closes alt text modal">
|
||||
<LinearGradient
|
||||
colors={[gradients.blueLight.start, gradients.blueLight.end]}
|
||||
start={{x: 0, y: 0}}
|
||||
|
|
|
@ -19,10 +19,12 @@ export function Component({
|
|||
title,
|
||||
message,
|
||||
onPressConfirm,
|
||||
onPressCancel,
|
||||
}: {
|
||||
title: string
|
||||
message: string | (() => JSX.Element)
|
||||
onPressConfirm: () => void | Promise<void>
|
||||
onPressCancel?: () => void | Promise<void>
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
|
@ -69,12 +71,23 @@ export function Component({
|
|||
style={[styles.btn]}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Confirm"
|
||||
// TODO: This needs to be updated so that modal roles are clear;
|
||||
// Currently there is only one usage for the confirm modal: post deletion
|
||||
accessibilityHint="Confirms a potentially destructive action">
|
||||
accessibilityHint="">
|
||||
<Text style={[s.white, s.bold, s.f18]}>Confirm</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{onPressCancel === undefined ? null : (
|
||||
<TouchableOpacity
|
||||
testID="cancelBtn"
|
||||
onPress={onPressCancel}
|
||||
style={[styles.btnCancel, s.mt10]}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel="Cancel"
|
||||
accessibilityHint="">
|
||||
<Text type="button-lg" style={pal.textLight}>
|
||||
Cancel
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
@ -104,4 +117,12 @@ const styles = StyleSheet.create({
|
|||
marginHorizontal: 44,
|
||||
backgroundColor: colors.blue3,
|
||||
},
|
||||
btnCancel: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 32,
|
||||
padding: 14,
|
||||
marginHorizontal: 20,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -142,9 +142,11 @@ export function ToggleButton({
|
|||
]}
|
||||
/>
|
||||
</View>
|
||||
{label === '' ? null : (
|
||||
<Text type="button" style={[labelStyle, styles.label]}>
|
||||
{label}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</Button>
|
||||
)
|
||||
|
@ -154,6 +156,7 @@ const styles = StyleSheet.create({
|
|||
outer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 10,
|
||||
},
|
||||
circle: {
|
||||
width: 42,
|
||||
|
@ -161,7 +164,6 @@ const styles = StyleSheet.create({
|
|||
borderRadius: 15,
|
||||
padding: 4,
|
||||
borderWidth: 1,
|
||||
marginRight: 10,
|
||||
},
|
||||
circleFill: {
|
||||
width: 16,
|
||||
|
|
|
@ -34,8 +34,8 @@ import {useCustomPalette} from 'lib/hooks/useCustomPalette'
|
|||
import {AccountData} from 'state/models/session'
|
||||
import {useAnalytics} from 'lib/analytics'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
import {isDesktopWeb} from 'platform/detection'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
|
||||
export const SettingsScreen = withAuthRequired(
|
||||
|
@ -54,6 +54,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
light: {color: colors.blue3},
|
||||
dark: {color: colors.blue2},
|
||||
})
|
||||
|
||||
const dangerBg = useCustomPalette<ViewStyle>({
|
||||
light: {backgroundColor: colors.red1},
|
||||
dark: {backgroundColor: colors.red7},
|
||||
|
@ -140,13 +141,12 @@ export const SettingsScreen = withAuthRequired(
|
|||
}, [store])
|
||||
|
||||
return (
|
||||
<View style={s.hContentRegion} testID="settingsScreen">
|
||||
<View style={[s.hContentRegion]} testID="settingsScreen">
|
||||
<ViewHeader title="Settings" />
|
||||
<ScrollView
|
||||
style={s.hContentRegion}
|
||||
style={[s.hContentRegion]}
|
||||
contentContainerStyle={!isDesktopWeb && pal.viewLight}
|
||||
scrollIndicatorInsets={{right: 1}}>
|
||||
<View style={styles.spacer20} />
|
||||
<View style={[s.flexRow, styles.heading]}>
|
||||
<Text type="xl-bold" style={pal.text}>
|
||||
Signed in as
|
||||
|
@ -161,9 +161,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
<Link
|
||||
href={`/profile/${store.me.handle}`}
|
||||
title="Your profile"
|
||||
noFeedback
|
||||
accessibilityLabel={`Signed in as ${store.me.handle}`}
|
||||
accessibilityHint="Double tap to sign out">
|
||||
noFeedback>
|
||||
<View style={[pal.view, styles.linkCard]}>
|
||||
<View style={styles.avi}>
|
||||
<UserAvatar size={40} avatar={store.me.avatar} />
|
||||
|
@ -231,9 +229,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
Add account
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Invite a friend
|
||||
</Text>
|
||||
|
@ -301,9 +297,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
Blocked accounts
|
||||
</Text>
|
||||
</Link>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Advanced
|
||||
</Text>
|
||||
|
@ -338,9 +332,7 @@ export const SettingsScreen = withAuthRequired(
|
|||
Change my handle
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Danger zone
|
||||
</Text>
|
||||
|
@ -355,16 +347,14 @@ export const SettingsScreen = withAuthRequired(
|
|||
<FontAwesomeIcon
|
||||
icon={['far', 'trash-can']}
|
||||
style={dangerText as FontAwesomeIconStyle}
|
||||
size={21}
|
||||
size={18}
|
||||
/>
|
||||
</View>
|
||||
<Text type="lg" style={dangerText}>
|
||||
Delete my account
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Developer tools
|
||||
</Text>
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -4433,6 +4433,11 @@
|
|||
dependencies:
|
||||
tippy.js "^6.3.7"
|
||||
|
||||
"@tiptap/extension-hard-break@^2.0.3":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.3.tgz#aa7805d825e5244bdccc508da18c781e231b2859"
|
||||
integrity sha512-RCln6ARn16jvKTjhkcAD5KzYXYS0xRMc0/LrHeV8TKdCd4Yd0YYHe0PU4F9gAgAfPQn7Dgt4uTVJLN11ICl8sQ==
|
||||
|
||||
"@tiptap/extension-history@^2.0.3":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.3.tgz#8936c15aa46f2ddeada1c3d9abe2888d58d08c30"
|
||||
|
@ -4820,6 +4825,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01"
|
||||
integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==
|
||||
|
||||
"@types/node@^18.16.2":
|
||||
version "18.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.2.tgz#2f610ea71034b3971c312192377f8a7178eb57f1"
|
||||
integrity sha512-GQW/JL/5Fz/0I8RpeBG9lKp0+aNcXEaVL71c0D2Q0QHDTFvlYKT7an0onCUXj85anv7b4/WesqdfchLc0jtsCg==
|
||||
|
||||
"@types/object.omit@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/object.omit/-/object.omit-3.0.0.tgz#0d31e1208eac8fe2ad5c9499a1016a8273bbfafc"
|
||||
|
|
Loading…
Reference in New Issue