MM-50354 - do not show push disabled notification once acknowledged
This commit is contained in:
parent
4f5b42abba
commit
0da1b5c6a4
11 changed files with 117 additions and 11 deletions
|
|
@ -77,3 +77,11 @@ export const removeLastViewedChannelIdAndServer = async () => {
|
|||
export const removeLastViewedThreadIdAndServer = async () => {
|
||||
return storeGlobal(GLOBAL_IDENTIFIERS.LAST_VIEWED_THREAD, null, false);
|
||||
};
|
||||
|
||||
export const storePushDisabledInServerAcknowledged = async (serverUrl: string) => {
|
||||
return storeGlobal(`${GLOBAL_IDENTIFIERS.PUSH_DISABLED_ACK}${serverUrl}`, 'true', false);
|
||||
};
|
||||
|
||||
export const removePushDisabledInServerAcknowledged = async (serverUrl: string) => {
|
||||
return storeGlobal(`${GLOBAL_IDENTIFIERS.PUSH_DISABLED_ACK}${serverUrl}`, null, false);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ export const GLOBAL_IDENTIFIERS = {
|
|||
ONBOARDING: 'onboarding',
|
||||
LAST_VIEWED_CHANNEL: 'lastViewedChannel',
|
||||
LAST_VIEWED_THREAD: 'lastViewedThread',
|
||||
PUSH_DISABLED_ACK: 'pushDisabledAck',
|
||||
};
|
||||
|
||||
export enum OperationType {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import CookieManager, {type Cookie} from '@react-native-cookies/cookies';
|
|||
import {AppState, type AppStateStatus, DeviceEventEmitter, Platform} from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
import {storeOnboardingViewedValue} from '@actions/app/global';
|
||||
import {removePushDisabledInServerAcknowledged, storeOnboardingViewedValue} from '@actions/app/global';
|
||||
import {cancelSessionNotification, logout, scheduleSessionNotification} from '@actions/remote/session';
|
||||
import {Events, Launch} from '@constants';
|
||||
import DatabaseManager from '@database/manager';
|
||||
|
|
@ -21,7 +21,7 @@ import {getCurrentUser} from '@queries/servers/user';
|
|||
import {getThemeFromState} from '@screens/navigation';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {deleteFileCache, deleteFileCacheByDir} from '@utils/file';
|
||||
import {isMainActivity} from '@utils/helpers';
|
||||
import {extractCleanDomain, isMainActivity} from '@utils/helpers';
|
||||
import {addNewServer} from '@utils/server';
|
||||
|
||||
import type {LaunchType} from '@typings/launch';
|
||||
|
|
@ -168,6 +168,8 @@ class SessionManager {
|
|||
|
||||
await this.terminateSession(serverUrl, removeServer);
|
||||
|
||||
await removePushDisabledInServerAcknowledged(extractCleanDomain(serverUrl));
|
||||
|
||||
if (activeServerUrl === serverUrl) {
|
||||
let displayName = '';
|
||||
let launchType: LaunchType = Launch.AddServer;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,22 @@ export const getDontAskForReview = async () => {
|
|||
return Boolean(records?.[0]?.value);
|
||||
};
|
||||
|
||||
export const getPushDisabledInServerAcknowledged = async (serverDomainString: string) => {
|
||||
const records = await queryGlobalValue(`${GLOBAL_IDENTIFIERS.PUSH_DISABLED_ACK}${serverDomainString}`)?.fetch();
|
||||
return Boolean(records?.[0]?.value);
|
||||
};
|
||||
|
||||
export const observePushDisabledInServerAcknowledged = (serverDomainString: string) => {
|
||||
const query = queryGlobalValue(`${GLOBAL_IDENTIFIERS.PUSH_DISABLED_ACK}${serverDomainString}`);
|
||||
if (!query) {
|
||||
return of$(false);
|
||||
}
|
||||
return query.observe().pipe(
|
||||
switchMap((result) => (result.length ? result[0].observe() : of$(false))),
|
||||
switchMap((v) => of$(Boolean(v))),
|
||||
);
|
||||
};
|
||||
|
||||
export const getFirstLaunch = async () => {
|
||||
const records = await queryGlobalValue(GLOBAL_IDENTIFIERS.FIRST_LAUNCH)?.fetch();
|
||||
if (!records?.[0]?.value) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ describe('components/channel_list/header', () => {
|
|||
canJoinChannels={true}
|
||||
canInvitePeople={true}
|
||||
displayName={'Test!'}
|
||||
pushDisabledAck={true}
|
||||
/>,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ type Props = {
|
|||
iconPad?: boolean;
|
||||
onHeaderPress?: () => void;
|
||||
pushProxyStatus: string;
|
||||
pushDisabledAck: boolean;
|
||||
}
|
||||
|
||||
const getStyles = makeStyleSheetFromTheme((theme: Theme) => ({
|
||||
|
|
@ -111,6 +112,7 @@ const ChannelListHeader = ({
|
|||
iconPad,
|
||||
onHeaderPress,
|
||||
pushProxyStatus,
|
||||
pushDisabledAck,
|
||||
}: Props) => {
|
||||
const theme = useTheme();
|
||||
const isTablet = useIsTablet();
|
||||
|
|
@ -166,7 +168,7 @@ const ChannelListHeader = ({
|
|||
|
||||
const onPushAlertPress = useCallback(() => {
|
||||
if (pushProxyStatus === PUSH_PROXY_STATUS_NOT_AVAILABLE) {
|
||||
alertPushProxyError(intl);
|
||||
alertPushProxyError(intl, serverUrl);
|
||||
} else {
|
||||
alertPushProxyUnknown(intl);
|
||||
}
|
||||
|
|
@ -206,7 +208,7 @@ const ChannelListHeader = ({
|
|||
>
|
||||
{serverDisplayName}
|
||||
</Text>
|
||||
{(pushProxyStatus !== PUSH_PROXY_STATUS_VERIFIED) && (
|
||||
{pushProxyStatus !== PUSH_PROXY_STATUS_VERIFIED && !pushDisabledAck && (
|
||||
<TouchableWithFeedback
|
||||
onPress={onPushAlertPress}
|
||||
testID='channel_list_header.push_alert'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ import withObservables from '@nozbe/with-observables';
|
|||
import {combineLatest, of as of$} from 'rxjs';
|
||||
import {distinctUntilChanged, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {observePushDisabledInServerAcknowledged} from '@app/queries/app/global';
|
||||
import {extractCleanDomain} from '@app/utils/helpers';
|
||||
import {Permissions} from '@constants';
|
||||
import {withServerUrl} from '@context/server';
|
||||
import {observePermissionForTeam} from '@queries/servers/role';
|
||||
import {observeConfigBooleanValue, observePushVerificationStatus} from '@queries/servers/system';
|
||||
import {observeCurrentTeam} from '@queries/servers/team';
|
||||
|
|
@ -16,7 +19,11 @@ import ChannelListHeader from './header';
|
|||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
type Props = WithDatabaseArgs & {
|
||||
serverUrl: string;
|
||||
}
|
||||
|
||||
const enhanced = withObservables([], ({serverUrl, database}: Props) => {
|
||||
const team = observeCurrentTeam(database);
|
||||
|
||||
const currentUser = observeCurrentUser(database);
|
||||
|
|
@ -57,7 +64,8 @@ const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
|||
distinctUntilChanged(),
|
||||
),
|
||||
pushProxyStatus: observePushVerificationStatus(database),
|
||||
pushDisabledAck: observePushDisabledInServerAcknowledged(extractCleanDomain(serverUrl)),
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(enhanced(ChannelListHeader));
|
||||
export default withDatabase(withServerUrl(enhanced(ChannelListHeader)));
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
import withObservables from '@nozbe/with-observables';
|
||||
import {of as of$} from 'rxjs';
|
||||
|
||||
import {extractCleanDomain} from '@app/utils/helpers';
|
||||
import {Tutorial} from '@constants';
|
||||
import {PUSH_PROXY_STATUS_UNKNOWN} from '@constants/push_proxy';
|
||||
import DatabaseManager from '@database/manager';
|
||||
import {observeTutorialWatched} from '@queries/app/global';
|
||||
import {observePushDisabledInServerAcknowledged, observeTutorialWatched} from '@queries/app/global';
|
||||
import {observePushVerificationStatus} from '@queries/servers/system';
|
||||
|
||||
import ServerItem from './server_item';
|
||||
|
|
@ -26,6 +27,7 @@ const enhance = withObservables(['highlight'], ({highlight, server}: {highlight:
|
|||
server: server.observe(),
|
||||
tutorialWatched,
|
||||
pushProxyStatus: serverDatabase ? observePushVerificationStatus(serverDatabase) : of$(PUSH_PROXY_STATUS_UNKNOWN),
|
||||
pushDisabledAck: observePushDisabledInServerAcknowledged(extractCleanDomain(server.url)),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ type Props = {
|
|||
server: ServersModel;
|
||||
tutorialWatched: boolean;
|
||||
pushProxyStatus: string;
|
||||
pushDisabledAck: boolean;
|
||||
}
|
||||
|
||||
type BadgeValues = {
|
||||
|
|
@ -147,6 +148,7 @@ const ServerItem = ({
|
|||
server,
|
||||
tutorialWatched,
|
||||
pushProxyStatus,
|
||||
pushDisabledAck,
|
||||
}: Props) => {
|
||||
const intl = useIntl();
|
||||
const theme = useTheme();
|
||||
|
|
@ -428,7 +430,7 @@ const ServerItem = ({
|
|||
>
|
||||
{displayName}
|
||||
</Text>
|
||||
{server.lastActiveAt > 0 && pushProxyStatus !== PUSH_PROXY_STATUS_VERIFIED && (
|
||||
{server.lastActiveAt > 0 && pushProxyStatus !== PUSH_PROXY_STATUS_VERIFIED && !pushDisabledAck && (
|
||||
<CompassIcon
|
||||
name='alert-outline'
|
||||
color={theme.errorTextColor}
|
||||
|
|
|
|||
|
|
@ -162,3 +162,45 @@ export function isMainActivity() {
|
|||
android: ShareModule?.getCurrentActivityName() === 'MainActivity',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the domain name or IP address from a serverUrl.
|
||||
*
|
||||
* @param {string} input - The serverUrl, potentially with a port and protocol.
|
||||
* @returns {string} The extracted domain name or IP address,
|
||||
* or empty if no match is found.
|
||||
*
|
||||
* // Output:
|
||||
* // Input: https://example-something.com => Result: example-something
|
||||
* // Input: http://192.168.1.1 => Result: 192.168.1.1
|
||||
* // Input: https://127.0.0.1:3000 => Result: 127.0.0.1
|
||||
*/
|
||||
export function extractDomain(input: string) {
|
||||
const regex = /^(https?:\/\/)?([\w.-]+)(:\d+)?$/;
|
||||
const match = input.match(regex);
|
||||
|
||||
if (match && match[2]) {
|
||||
return match[2].replace(/[\W.]/g, '');
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain name or IP address from a serverUrl without special characters.
|
||||
*
|
||||
* @param {string} domain - The extracted domain from a serverUrl.
|
||||
* @returns {string} The extracted domain name or IP address, modified to remove special characters,
|
||||
* or empty .
|
||||
*
|
||||
* // Output:
|
||||
* // Input: example-something => Result: examplesomething
|
||||
* // Input: 192.168.1.1 => Result: 19216811
|
||||
* // Input: 127.0.0.1 => Result: 127001
|
||||
*/
|
||||
export function extractCleanDomain(domain: string) {
|
||||
if (!domain) {
|
||||
return '';
|
||||
}
|
||||
return extractDomain(domain).replace(/[\W.]/g, '');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,30 @@
|
|||
|
||||
import {Alert} from 'react-native';
|
||||
|
||||
import {storePushDisabledInServerAcknowledged} from '@actions/app/global';
|
||||
import {getPushDisabledInServerAcknowledged} from '@app/queries/app/global';
|
||||
import {PUSH_PROXY_RESPONSE_NOT_AVAILABLE, PUSH_PROXY_RESPONSE_UNKNOWN, PUSH_PROXY_STATUS_NOT_AVAILABLE, PUSH_PROXY_STATUS_UNKNOWN, PUSH_PROXY_STATUS_VERIFIED} from '@constants/push_proxy';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
|
||||
import {extractCleanDomain} from './helpers';
|
||||
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
export function canReceiveNotifications(serverUrl: string, verification: string, intl: IntlShape) {
|
||||
export async function pushDisabledInServerAck(serverUrl: string) {
|
||||
const extractedDomain = extractCleanDomain(serverUrl);
|
||||
const pushServerDisabledAck = await getPushDisabledInServerAcknowledged(extractedDomain);
|
||||
return pushServerDisabledAck;
|
||||
}
|
||||
|
||||
export async function canReceiveNotifications(serverUrl: string, verification: string, intl: IntlShape) {
|
||||
const a = await pushDisabledInServerAck(serverUrl);
|
||||
|
||||
switch (verification) {
|
||||
case PUSH_PROXY_RESPONSE_NOT_AVAILABLE:
|
||||
EphemeralStore.setPushProxyVerificationState(serverUrl, PUSH_PROXY_STATUS_NOT_AVAILABLE);
|
||||
alertPushProxyError(intl);
|
||||
if (!a) {
|
||||
alertPushProxyError(intl, serverUrl);
|
||||
}
|
||||
break;
|
||||
case PUSH_PROXY_RESPONSE_UNKNOWN:
|
||||
EphemeralStore.setPushProxyVerificationState(serverUrl, PUSH_PROXY_STATUS_UNKNOWN);
|
||||
|
|
@ -23,7 +37,14 @@ export function canReceiveNotifications(serverUrl: string, verification: string,
|
|||
}
|
||||
}
|
||||
|
||||
export function alertPushProxyError(intl: IntlShape) {
|
||||
const handleAlertResponse = async (buttonIndex: number, serverUrl: string) => {
|
||||
if (buttonIndex === 0) {
|
||||
// User clicked "Okay" acknowledging that the push notifications are disabled on that server
|
||||
await storePushDisabledInServerAcknowledged(extractCleanDomain(serverUrl));
|
||||
}
|
||||
};
|
||||
|
||||
export function alertPushProxyError(intl: IntlShape, serverUrl: string) {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.push_proxy_error.title',
|
||||
|
|
@ -35,6 +56,7 @@ export function alertPushProxyError(intl: IntlShape) {
|
|||
}),
|
||||
[{
|
||||
text: intl.formatMessage({id: 'alert.push_proxy.button', defaultMessage: 'Okay'}),
|
||||
onPress: () => handleAlertResponse(0, serverUrl),
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue