Skip to content
Commits on Source (19)
......@@ -9,6 +9,7 @@ import {
import { onError } from "mobx-react";
import logService from './src/common/services/log.service';
import Sentry from 'react-native-sentry';
onError(error => {
console.log(error);
......@@ -48,7 +49,9 @@ if (!__DEV__) {
* Native Errors
*/
setNativeExceptionHandler((exceptionString) => {
Sentry.captureException(new Error(exceptionString), {
logger: 'NativeExceptionHandler',
});
console.log(exceptionString);
logService.exception(exceptionString);
});
}
import api from '../../../src/common/services/api.service';
import api, { ApiError } from '../../../src/common/services/api.service';
import session from '../../../src/common/services/session.service';
import abortableFetch, {abort} from '../../../src/common/helpers/abortableFetch';
import { MINDS_API_URI } from '../../../src/config/Config';
......@@ -46,14 +46,14 @@ describe('api service POST', () => {
const res = await api.post('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(response);
expect(err).toBeInstanceOf(ApiError);
}
});
it('should return api error', async () => {
const response = { json: jest.fn(), ok: true };
const respBody = { status: 'error', error: 'some error' };
const respBody = { status: 500, error: 'some error' };
response.json.mockResolvedValue(respBody);
const params = {p1: 1, p2: 2};
......@@ -63,7 +63,7 @@ describe('api service POST', () => {
const res = await api.post('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(respBody);
expect(err).toBeInstanceOf(ApiError);
}
});
});
......@@ -105,7 +105,7 @@ describe('api service GET', () => {
const res = await api.get('api/path', params, null);
} catch (err){
// assert on the error
expect(err).toEqual(response);
expect(err).toBeInstanceOf(ApiError);
}
});
......@@ -122,7 +122,7 @@ describe('api service GET', () => {
const res = await api.get('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(respBody);
expect(err).toBeInstanceOf(ApiError);
}
});
});
......@@ -167,7 +167,7 @@ describe('api service DELETE', () => {
const res = await api.delete('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(response);
expect(err).toBeInstanceOf(ApiError);
}
});
......@@ -184,7 +184,7 @@ describe('api service DELETE', () => {
const res = await api.delete('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(respBody);
expect(err).toBeInstanceOf(ApiError);
}
});
});
......@@ -229,7 +229,7 @@ describe('api service PUT', () => {
const res = await api.put('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(response);
expect(err).toBeInstanceOf(ApiError);
}
});
......@@ -245,7 +245,7 @@ describe('api service PUT', () => {
const res = await api.put('api/path', params);
} catch (err) {
// assert on the error
expect(err).toEqual(respBody);
expect(err).toBeInstanceOf(ApiError);
}
});
});
......
......@@ -22,10 +22,10 @@ org.gradle.jvmargs=-Xmx2048m
systemProp.org.gradle.internal.http.connectionTimeout=180000
systemProp.org.gradle.internal.http.socketTimeout=180000
versionName=3.9.0
versionName=3.9.1
# CUSTOM
versionCode=1050000012
versionCode=1050000013
# PLAY STORE
#versionCode=310030
# versionCode=310031
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.9.0</string>
<string>3.9.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>3.9.0</string>
<string>3.9.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.9.0</string>
<string>3.9.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
......@@ -125,4 +125,4 @@
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
\ No newline at end of file
</plist>
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>3.9.0</string>
<string>3.9.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -8,6 +8,15 @@ import abortableFetch from '../helpers/abortableFetch';
import { Version } from '../../config/Version';
import logService from './log.service';
/**
* Api Error
*/
export class ApiError extends Error {
constructor(...args) {
super(...args)
}
}
/**
* Api service
*/
......@@ -48,6 +57,22 @@ class ApiService {
}).join('&');
}
/**
* Throw an error
* @param {any} err
* @param {string} url
*/
_throwError(err, url) {
if (err instanceof Error) {
throw err;
}
const error = new ApiError(err.message || err.responseText || `Request error on: ${url}`);
if (err.status) {
error.status = err.status;
}
throw error;
}
/**
* Api get with abort support
* @param {string} url
......@@ -76,10 +101,12 @@ class ApiService {
// Bad authorization
if (err.status && err.status == 401) {
const refreshed = await session.badAuthorization(); //not actually a logout
if (refreshed) return await this.get(url, params, tag);
if (refreshed) {
return await this.get(url, params, tag);
}
session.logout();
}
throw err;
this._throwError(err, url);
}
}
......@@ -104,11 +131,13 @@ class ApiService {
} catch(err) {
if (err.status && err.status == 401) {
const refreshed = await session.badAuthorization(); //not actually a logout
if (refreshed) return await this.post(url, body);
if (refreshed) {
return await this.post(url, body);
}
logService.log('[ApiService] Token refresh failed: logout');
session.logout();
}
throw err;
this._throwError(err, url);
}
}
......@@ -133,19 +162,21 @@ class ApiService {
} catch(err) {
if (err.status && err.status == 401) {
const refreshed = await session.badAuthorization(); //not actually a logout
if (refreshed) return await this.post(url, body);
if (refreshed) {
return await this.put(url, body);
}
logService.log('[ApiService] Token refresh failed: logout');
session.logout();
}
throw err;
this._throwError(err, url);
}
}
/**
* Upload file to s3, differences with generic upload are headers and formData (wich is not necessary)
* @param {any} lease
* @param {any} file
* @param {function} progress
* @param {any} lease
* @param {any} file
* @param {function} progress
*/
uploadToS3(lease, file, progress) {
......@@ -207,11 +238,13 @@ class ApiService {
} catch(err) {
if (err.status && err.status == 401) {
const refreshed = await session.badAuthorization(); //not actually a logout
if (refreshed) return await this.post(url, body);
if (refreshed) {
return await this.delete(url, body);
}
logService.log('[ApiService] Token refresh failed: logout');
session.logout();
}
throw err;
this._throwError(err, url);
}
}
......
......@@ -312,7 +312,8 @@ export default class FeedsService {
}
if (!await this.fetchLocal()) {
throw new Error('Error fetching feed from remote or local');
// if there is no local data rethrow the exception
throw err;
}
showMessage({
......
......@@ -7,6 +7,7 @@ import settingsService from '../../settings/SettingsService'
import settingsStore from '../../settings/SettingsStore';
import { Sentry } from 'react-native-sentry';
import { isNetworkFail } from '../helpers/abortableFetch';
import { ApiError } from './api.service';
const parseErrorStack = error => {
if (!error || !error.stack) {
......@@ -67,7 +68,7 @@ class LogService {
prepend = null;
}
if (!isNetworkFail(error)) {
if (!isNetworkFail(error) && !(error instanceof ApiError && error.status === 401)) {
// report the issue to sentry
Sentry.captureException(error);
}
......
......@@ -15,7 +15,6 @@ export default class IosPlatfom extends AbstractPlatform {
NotificationsIOS.addEventListener('remoteNotificationsRegistrationFailed', this._onPushRegistrationFailed.bind(this));
NotificationsIOS.addEventListener('notificationOpened', this._onNotificationOpened.bind(this));
NotificationsIOS.requestPermissions();
NotificationsIOS.consumeBackgroundQueue();
}
/**
......
......@@ -61,6 +61,13 @@ class SessionService {
const [accessToken, refreshToken, user] = await this.sessionStorage.getAll();
// if there is no session active we clean up and return;
if (!accessToken) {
this.setToken(null);
this.setRefreshToken(null);
return null;
}
const { access_token, access_token_expires } = accessToken;
const { refresh_token, refresh_token_expires } = refreshToken;
......
......@@ -135,7 +135,11 @@ class DiscoveryStore {
reset() {
this.onFilterChangeDisposer && this.onFilterChangeDisposer();
this.onSearchChangeDisposer && this.onSearchChangeDisposer();
this.filters.clear();
if (this.filters) {
this.filters.clear();
}
this.feedStore.reset();
this.listStore.clear();
this.listenChanges();
......
......@@ -26,6 +26,7 @@ import Colors from '../../styles/Colors';
import stylesheet from '../../onboarding/stylesheet';
import { CommonStyle as CS } from '../../styles/Common';
import i18n from '../../common/services/i18n.service';
import logService from '../../common/services/log.service';
@inject('user', 'wallet')
@observer
......
......@@ -47,7 +47,7 @@ class WalletStore {
if (addresses && addresses.length > 0) {
addresses.forEach(async address => {
if (address.label.toLowerCase() != 'offchain') {
if (address.label.toLowerCase() != 'offchain' && address.address !== '') {
address.ethBalance = await web3Service.getBalance(address.address);
}
});
......
......@@ -7504,10 +7504,10 @@ react-native-elements@^0.19.1:
opencollective "^1.0.3"
prop-types "^15.5.8"
react-native-exception-handler@^2.10.7:
version "2.10.7"
resolved "https://registry.yarnpkg.com/react-native-exception-handler/-/react-native-exception-handler-2.10.7.tgz#3ce2f10d6a8add35fdc036af62c2859c4b7f505c"
integrity sha512-e2zv0BiP9SRdr1vLDUyC2WbWHfgNV1a3BhRxK1ENjXVRY8mu+dfaaIHhFXdvYue//MEuGUQstu61NZoiO1u2KA==
react-native-exception-handler@^2.10.8:
version "2.10.8"
resolved "https://registry.yarnpkg.com/react-native-exception-handler/-/react-native-exception-handler-2.10.8.tgz#1a7f846592d888d23adaf797e31802585f1d9ff0"
integrity sha512-ZN+jwpADRkCUNdad/50k0mZdMoICGrGdtaxgvRU+pNcWRRBAXJhuo4+jY0eQaoVpx1ghycGE6tBu9ka8gL2NOQ==
react-native-exit-app@^1.0.0:
version "1.0.0"
......