Skip to content

Commit

Permalink
ux: show dialog when pressing unrecognized links
Browse files Browse the repository at this point in the history
  • Loading branch information
achou11 authored and staltz committed Oct 3, 2023
1 parent cb669fe commit 8b87edc
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 7 deletions.
4 changes: 4 additions & 0 deletions android/app/src/main/assets/translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
"external_link_confirmation": {
"title": "Open link?",
"description": "Do you want to open {{link}} in your browser?"
},
"unrecognized_link_confirmation": {
"title": "Unrecognized link",
"description": "This is not a web link neither an SSB link. Are you sure you want to open this? {{link}}"
}
},
"date": {
Expand Down
4 changes: 4 additions & 0 deletions android/app/src/main/assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
"external_link_confirmation": {
"title": "Open link?",
"description": "Do you want to open {{link}} in your browser?"
},
"unrecognized_link_confirmation": {
"title": "Unrecognized link",
"description": "This is not a web link neither an SSB link. Are you sure you want to open this? {{link}}"
}
},
"date": {
Expand Down
26 changes: 19 additions & 7 deletions src/frontend/components/Markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
import {
isFeedSSBURI,
isMessageSSBURI,
isSSBURI,
toFeedSigil,
toMessageSigil,
getFeedSSBURIRegex,
Expand Down Expand Up @@ -43,7 +42,7 @@ const ELLIPSIS = '\u2026';
* Match URIs *except* SSB URIs and File URIs
*/
function getMiscURIRegex() {
return /\b((?=[a-z]+:)(?!(ssb:|file:)))[a-z]+:(\/\/)?[^ )\n]+/g;
return /\b((?=[a-z-]+:)(?!(ssb:|file:)))[a-z-]+:(\/\/)?[^ )\n]+/g;
}

const textProps: TextProps = {
Expand Down Expand Up @@ -421,6 +420,14 @@ function makeRenderers(
style: styles.link,
onPress: (event) => {
event.stopPropagation();

if (!isHTTPLink) {
event.preventDefault();
GlobalEventBus.dispatch({
type: 'triggerUnrecognizedLink',
url: properHref,
});
}
},
['href' as any]: properHref,
},
Expand All @@ -434,7 +441,15 @@ function makeRenderers(
style: styles.link,
onPress: (event) => {
event.stopPropagation();
Linking.openURL(props.href);
if (isHTTPLink) {
Linking.openURL(props.href);
} else {
event.preventDefault();
GlobalEventBus.dispatch({
type: 'triggerUnrecognizedLink',
url: props.href,
});
}
},
},
child ?? props.children,
Expand Down Expand Up @@ -517,8 +532,7 @@ export interface Props {
}

function transformLinkUri(uri: string) {
if (isSSBURI(uri)) return uri; // don't interfere with SSB URIs
return ReactMarkdown.uriTransformer(uri); // interfere with all others
return uri; // don't interfere with any URIs
}

export default class Markdown extends PureComponent<Props> {
Expand All @@ -527,7 +541,6 @@ export default class Markdown extends PureComponent<Props> {
const linkifySsbSigilMsgs = linkifyRegex(Ref.msgIdRegex);
const linkifySsbUriFeeds = linkifyRegex(getFeedSSBURIRegex());
const linkifySsbUriMsgs = linkifyRegex(getMessageSSBURIRegex());
const linkifyMiscUris = linkifyRegex(getMiscURIRegex());
const linkifyHashtags = linkifyRegex(
new RegExp('#(' + getUnicodeWordRegex().source + '|\\d|-)+', 'gu'),
);
Expand All @@ -540,7 +553,6 @@ export default class Markdown extends PureComponent<Props> {
.use(linkifySsbUriMsgs)
.use(linkifySsbSigilFeeds)
.use(linkifySsbSigilMsgs)
.use(linkifyMiscUris)
.use(linkifyHashtags)
.use(imagesToSsbServeBlobs, {port: portMappings.get('ssb-serve-blobs')})
.processSync(this.props.text).contents,
Expand Down
6 changes: 6 additions & 0 deletions src/frontend/drivers/eventbus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export interface TriggerHashtagLink {
hashtag: string;
}

export interface TriggerUnrecognizedLink {
type: 'triggerUnrecognizedLink';
url: string;
}

export interface HardwareBackOnCentralScreen {
type: 'hardwareBackOnCentralScreen';
}
Expand Down Expand Up @@ -95,6 +100,7 @@ export type GlobalEvent =
| TriggerFeedCypherlink
| TriggerMsgCypherlink
| TriggerHashtagLink
| TriggerUnrecognizedLink
| HardwareBackOnCentralScreen
| DrawerToggleOnCentralScreen
| AudioBlobComposed
Expand Down
35 changes: 35 additions & 0 deletions src/frontend/screens/global/dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: 2023 The Manyverse Authors
//
// SPDX-License-Identifier: MPL-2.0

import {Stream} from 'xstream';
import {DialogSource} from '~frontend/drivers/dialogs';
import {t} from '~frontend/drivers/localization';
import {Palette} from '~frontend/global-styles/palette';

export interface Actions {
openUnrecognizedLinkDialog$: Stream<string>;
}

export default function dialog(actions: Actions, dialogSource: DialogSource) {
return {
openUnrecognizedLink$: actions.openUnrecognizedLinkDialog$
.map((link) =>
dialogSource
.alert(
t('call_to_action.unrecognized_link_confirmation.title'),
t('call_to_action.unrecognized_link_confirmation.description', {
link,
}),
{
...Palette.dialogColors,
positiveText: t('call_to_action.yes'),
negativeText: t('call_to_action.no'),
},
)
.filter((res) => res.action === 'actionPositive')
.mapTo(link),
)
.flatten(),
};
}
4 changes: 4 additions & 0 deletions src/frontend/screens/global/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ssb from './ssb';
import localization from './localization';
import toast from './toast';
import asyncStorage from './asyncstorage';
import dialog from './dialog';

export interface Sources {
state: StateSource<State>;
Expand All @@ -40,6 +41,7 @@ export interface Sinks {
toast: Stream<Toast>;
globalEventBus: Stream<GlobalEvent>;
asyncstorage: Stream<StorageCommand>;
linking: Stream<string>;
}

export function global(sources: Sources): Sinks {
Expand All @@ -58,6 +60,7 @@ export function global(sources: Sources): Sinks {
const updateLocalization$ = localization(sources.fs);
const req$ = ssb(updateLocalization$, actions);
const toast$ = toast(actions, sources.ssb);
const dialogActions$ = dialog(actions, sources.dialog);

const event$ = xs.merge<GlobalEvent>(
actions.readCheckingNewVersionSetting$
Expand All @@ -84,5 +87,6 @@ export function global(sources: Sources): Sinks {
toast: toast$,
globalEventBus: event$,
asyncstorage: storageCommand$,
linking: dialogActions$.openUnrecognizedLink$,
};
}
8 changes: 8 additions & 0 deletions src/frontend/screens/global/intent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
GlobalEvent,
TriggerFeedCypherlink,
TriggerHashtagLink,
TriggerUnrecognizedLink,
TriggerMsgCypherlink,
} from '~frontend/drivers/eventbus';
import {SSBSource} from '~frontend/drivers/ssb';
Expand Down Expand Up @@ -204,6 +205,12 @@ export default function intent(
.flatten()
.take(1);

const openUnrecognizedLinkDialog$ = (
globalEventBus.filter(
(ev) => ev.type === 'triggerUnrecognizedLink',
) as Stream<TriggerUnrecognizedLink>
).map((ev) => ev.url);

return {
handleUriClaimInvite$,
handleUriConsumeAlias$,
Expand All @@ -217,5 +224,6 @@ export default function intent(
goToSearch$,
goToCompact$,
readCheckingNewVersionSetting$,
openUnrecognizedLinkDialog$,
};
}
2 changes: 2 additions & 0 deletions typings/i18n-js.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ declare module 'i18n-js' {
| 'call_to_action.close_dialog.accessibility_label'
| 'call_to_action.external_link_confirmation.title'
| 'call_to_action.external_link_confirmation.description'
| 'call_to_action.unrecognized_link_confirmation.title'
| 'call_to_action.unrecognized_link_confirmation.description'
| 'date.relative.past.years'
| 'date.relative.past.months'
| 'date.relative.past.weeks'
Expand Down

0 comments on commit 8b87edc

Please sign in to comment.